From cheese-flow
Hash-anchored file editing using tilth MCP. Replace specific functions or blocks using hash anchors from tilth_read, not entire file rewrites. Use when: editing code, replacing functions, deleting blocks, or making precise surgical changes. Always read first to get hash anchors. Do NOT use for reading files — use cheez-read. Do NOT use for searching — use cheez-search. Examples: "replace the validateToken function with this new implementation", "delete lines 44-89", "update the authenticate method".
How this skill is triggered — by the user, by Claude, or both
Slash command
/cheese-flow:cheez-writeThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
> **Hard dependency**: If `mcp__tilth__tilth_edit` is unavailable, stop immediately and report
Hard dependency: If
mcp__tilth__tilth_editis unavailable, stop immediately and report "tilth MCP server is not loaded — cannot proceed." Do NOT fall back toEdit,Write, or any host tool.
Hash-anchored file editing via tilth MCP (tilth_edit).
Never rewrite whole files. Use hash anchors from tilth_read to make precise, surgical edits.
Traditional AI editing rewrites entire files, wasting tokens and risking data loss. tilth_edit uses hash anchors — unique identifiers for each line — to:
The protocol:
tilth_read → get hash anchorstilth_edit with those anchors and new contentWhen you read a file with tilth_read, lines have anchors:
42:a3f│ let x = compute();
43:f1b│ return x;
Format: <line>:<hash>│ <content>
The hash is a short content fingerprint. If someone else edits the file, hashes change, and your edit is safely rejected.
Single line edit:
tilth_edit({
"path": "src/auth.ts",
"edits": [
{ "start": "42:a3f", "content": " let x = recompute();" }
]
})
Multi-line range replacement:
tilth_edit({
"path": "src/auth.ts",
"edits": [
{
"start": "44:b2c",
"end": "89:e1d",
"content": "export function handleAuth(req, res, next) {\n // new implementation\n const token = extractToken(req);\n if (!token) return res.status(401).end();\n next();\n}"
}
]
})
Delete a block:
tilth_edit({
"path": "src/auth.ts",
"edits": [
{ "start": "44:b2c", "end": "89:e1d", "content": "" }
]
})
Multiple edits in one call:
tilth_edit({
"path": "src/auth.ts",
"edits": [
{ "start": "12:a1b", "content": "import { newHelper } from './helpers';" },
{ "start": "44:b2c", "end": "89:e1d", "content": "// replaced function\n..." }
]
})
Show diff in response:
tilth_edit({
"path": "src/auth.ts",
"diff": true,
"edits": [...]
})
tilth_read(path: "src/auth.ts", section: "44-89")
Output:
44:b2c│ export function handleAuth(req, res, next) {
45:c3d│ const token = req.headers.authorization?.split(' ')[1];
...
88:d4e│ next();
89:e1d│ }
44:b2c (first line of function)89:e1d (closing brace)tilth_edit({
"path": "src/auth.ts",
"edits": [{
"start": "44:b2c",
"end": "89:e1d",
"content": "export function handleAuth(req, res, next) {\n const token = extractToken(req);\n if (!validateToken(token)) {\n return res.status(401).json({ error: 'Invalid token' });\n }\n req.user = decodeToken(token);\n next();\n}"
}]
})
This is the most common use case. The pattern:
Read the function (outline first if file is large):
tilth_read(path: "src/auth.ts")
# See: [44-89] export fn handleAuth(req, res, next)
tilth_read(path: "src/auth.ts", section: "44-89")
# Get hash anchors
Note start/end anchors from the hashlined output
Replace the entire function body:
tilth_edit({
"path": "src/auth.ts",
"edits": [{
"start": "44:b2c",
"end": "89:e1d",
"content": "<your new function implementation>"
}]
})
If the file changed since you read it:
Error: Hash mismatch at line 44
Expected: b2c
Found: f9a
Current content:
44:f9a│ export async function handleAuth(req, res, next) {
...
Recovery:
This is a safety feature, not a bug.
When you edit a function signature, tilth_edit shows callers that may need updating:
Edit applied to src/auth.ts
── callers that may need updates ──
src/routes/api.ts:34 router.use('/api/*', handleAuth)
src/routes/admin.ts:12 app.use(handleAuth)
src/middleware.ts:8 const wrapped = handleAuth(...)
Check these locations and update if needed.
Use the start anchor of the line AFTER where you want to insert:
tilth_edit({
"path": "src/auth.ts",
"edits": [{
"start": "13:abc",
"content": "import { newHelper } from './helpers';\nimport { oldImport } from './old';"
}]
})
This replaces line 13. To truly "insert", include the original line 13 content in your new content.
tilth_edit({
"path": "src/auth.ts",
"edits": [
{ "start": "44:b2c", "end": "89:e1d", "content": "" },
{ "start": "120:f4g", "end": "180:h5i", "content": "" }
]
})
Make separate tilth_edit calls per file (cannot batch across files):
tilth_edit({ path: "src/auth.ts", edits: [...] })
tilth_edit({ path: "src/routes.ts", edits: [...] })
For large files, tilth_read shows an outline, not hashlined content:
# src/giant.ts (2400 lines, ~32k tokens) [outline]
[1-20] imports
[22-89] interface Config
[91-450] class GiantHandler
[100-180] fn process
[182-340] fn validate
To edit, drill into the specific section:
tilth_read(path: "src/giant.ts", section: "100-180")
# Now you get hashlined content for fn process
Then edit with those anchors.
Provides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub paulnsorensen/cheese-flow