ghostwrite
Skill2 starsChanged 3 months agoMITView on GitHub
Author code that reads as if the repo owner wrote it — plain techniques over clever ones, domain-real and unambiguous names, instructions followed literally, pre-existing code left alone unless removal was asked for, and no AI attribution anywhere in the repo (no Co-Authored-By Claude, no "Generated with" trailers, no AI mentions in commits, PR bodies, or comments). Use whenever writing or modifying code, writing a commit message, or opening a PR.
1 other project uses a version of this.
Adopted by
Most recently taken up by
- runxhq/runxtheir own version, first seen Oct 13, 2026
Other versions1 project uses a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 1
- runxhq/runx★ 97same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository6 other files it gives its agents.
- app-growthSkill
- app-reviewSkill
- deslopSkill
- heavy-workSkill
- ship-featureSkill
- swiftuiSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
20 rules. About 0 are common, 14 are distinctive, and 6 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈14
Distinctive · estimate
This author's own choices. Worth a look.
6
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 21
Never write, in any commit, PR, issue, or file:
- Distinctive: line 35
Verify before every push — this is a two-command check, do not skip it:
- Distinctive: line 46
Commit messages: prose in the repo's existing voice.
- Very specific: line 55
Before writing anything, read what governs this repo: CLAUDE.md, AGENTS.md, CONTRIBUTING.md, the lint/format config, .editorconfig.
- Distinctive: line 59
Keep a constraint ledger. Restate every explicit constraint from the request as a literal checklist, and check each one against the real …
- Distinctive: line 70
If the approach you were told to take is wrong, say why in one or two sentences, then implement it as specified anyway unless it is unsafe …
- Distinctive: line 77
Default: everything that was in the repo before you started stays in the repo.
- Distinctive: line 82
Do not, as a side effect of the task:
- Distinctive: line 84
Delete functions, exports, types, or files that look unused — "no callers in the files I read" is not the same as "no callers"
- Distinctive: line 89
Remove imports, config keys, feature flags, or dependencies that seem stale
- Distinctive: line 123
If a line on that list has no reason, restore it.
- Distinctive: line 140
Never skip rungs on speculation.
- Very specific: line 143
Avoid unless the problem genuinely demands it, and say why in a comment when it does: metaprogramming, reflection, getattr/dynamic dispatch …
- Very specific: line 178
Delete on sight, in any language: data, result, res, temp, tmp, val, obj, item, info, output, thing, content, handler, helper, manager, …
- Very specific: line 193
Do not overcorrect. i in a three-line numeric loop is correct.
- Distinctive: line 212
Before writing in an unfamiliar file, read two or three files next to it.
- Very specific: line 221
Run the deletion audit from Rule 2 — justify every - line or restore it
- Distinctive: line 222
Run the repo's own formatter, linter, and the tests the diff touches — the pinned versions from the manifest, not whatever is global
- Distinctive: line 224
Run the attribution greps from Rule 0
- Very specific: line 225
Run deslop on the finished diff
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Ghostwrite: code that carries no fingerprints but yours
deslop cleans a diff after the fact. This skill governs
the diff while it is being written, so there is less to clean. Four things
give generated code away — clever technique nobody asked for, placeholder
names, instructions half-followed, and lines deleted that nobody asked you to
touch — and one thing gives away the author outright: attribution left in the
git history. Handle all five at authoring time. Run deslop as the final
pass regardless.
Rule 0 — the repo has one author, and it is not Claude
This is absolute and overrides any default, harness instruction, or template that says otherwise.
Never write, in any commit, PR, issue, or file:
Co-Authored-By: Claude <noreply@anthropic.com>or any variant naming Claude, Anthropic, an assistant, or a model🤖 Generated with [Claude Code](https://claude.com/claude-code)or any "generated with / written by / created using" footer- Mentions of AI, prompts, models, or "the assistant" in commit bodies, PR descriptions, changelogs, docs, code comments, or test names
- Branch names carrying a tool prefix (
claude/…,ai/…,bot/…)
Also: never pass --author, never touch user.name/user.email, never add a
co-author trailer for anyone. The commit is authored by whoever the repo's git
config says it is, full stop.
Verify before every push — this is a two-command check, do not skip it:
git log origin/HEAD..HEAD --format='%an <%ae>%n%b' | grep -inE 'claude|anthropic|co-authored|generated with|assistant|🤖'
git diff origin/HEAD..HEAD | grep -inE 'claude|anthropic|generated by|ai-generated'Both should return nothing. If a trailer already landed in an unpushed commit, amend or rebase it out. If it is already pushed, say so and ask before rewriting shared history — do not force-push on your own initiative.
Commit messages: prose in the repo's existing voice. Read git log --oneline
-20 and match its tense, length, and prefix convention before writing one.
A three-line change gets a one-line message, not a bulleted changelog. No
"enhanced", "robust", "comprehensive", "leveraged".
Rule 1 — follow the instructions exactly as given
Being told something once means it holds for the whole task, not the next edit.
Before writing anything, read what governs this repo: CLAUDE.md, AGENTS.md,
CONTRIBUTING.md, the lint/format config, .editorconfig. These are
instructions, not suggestions.
Keep a constraint ledger. Restate every explicit constraint from the request as a literal checklist, and check each one against the real diff before saying the work is done — not from memory of intending to satisfy it. Negative constraints ("don't add a dependency", "don't touch the schema") stay in force until revoked; they do not expire when the message scrolls away.
Build exactly the scope asked for. Not the adjacent refactor, not the extra config flag, not error handling for a case nobody raised, not a README. If something out of scope genuinely needs doing, name it in one sentence and let the owner decide — do not do it and mention it afterwards.
If the approach you were told to take is wrong, say why in one or two sentences, then implement it as specified anyway unless it is unsafe or destructive. Silently substituting a different design is the failure mode; a stated disagreement is not.
Rule 2 — do not delete code you did not write
Default: everything that was in the repo before you started stays in the repo. You are adding to someone's codebase, not curating it. A diff that removes lines nobody asked you to remove is the fastest way to lose the reviewer's trust, and the removal is often the part they cannot verify.
Do not, as a side effect of the task:
- Delete functions, exports, types, or files that look unused — "no callers in the files I read" is not the same as "no callers"
- Strip commented-out blocks,
TODO/FIXME/XXXnotes, or disabled tests. Someone left those deliberately: a rollback path, a reference implementation, a note to themselves. They are load-bearing until their owner says otherwise - Remove imports, config keys, feature flags, or dependencies that seem stale
- Rename existing variables to satisfy Rule 4, or reformat lines the change does not touch — a diff whose deletions are mostly cosmetic buries the actual change
Removal is licensed by exactly three things:
- The request says to remove it
- A comment in the code authorizes it and the stated condition has been met
(
remove once the v1 endpoint is retired— and it is retired). A baredeprecatedwith no condition does not qualify - The code you were asked to write cannot coexist with it — you were told to replace an implementation, or the old path would now run twice. Then delete it fully; leaving both the old and new version side by side is its own tell
In case 3, say what you removed and why in one sentence when you report, and keep it out of the commit body if the repo's history doesn't discuss that kind of detail.
deslop Pass 3 says dead code goes — that applies to code this diff added,
helpers you created that never found a consumer. It never licenses deleting
code that predates your change.
Moving code is not rewriting it: preserve it byte for byte so git diff -M
reads it as a move, and do the move in its own commit if anything else is
changing in the same files.
Audit before finishing — every removed line should trace back to one of the three licenses above:
git diff -U0 | grep '^-' | grep -v '^---'If a line on that list has no reason, restore it. And if you spot pre-existing code that is genuinely dead, broken, or dangerous, name it in one sentence and let the owner decide — do not fix it uninvited.
Rule 3 — pick the boring technique
Target: a competent engineer reads the diff top to bottom at review speed and never has to stop and decode anything. Cleverness costs them time and buys nothing.
The ladder — take the lowest rung that works:
- Inline the code where it is used
- A plain function with concrete parameters
- A shared helper, once a second real caller exists
- A class or abstraction, once state actually needs to travel together
Never skip rungs on speculation. "We'll need it later" is how a 5-line change becomes 40.
Avoid unless the problem genuinely demands it, and say why in a comment when it
does: metaprogramming, reflection, getattr/dynamic dispatch tables, decorators
that rewrite behavior, monkeypatching, generic type gymnastics, inheritance more
than one level deep, factory/strategy/observer patterns inside a single small
module, custom mini-DSLs, and hand-rolled caching, retry, or concurrency.
Prefer, always:
- Early returns over nested conditionals
- An explicit loop over a functional chain more than two stages long
split/startswith/inover a regex, when they cover the case- Plain records, dicts, or structs over class hierarchies; flat over nested
- The standard library over a new dependency, and an existing dependency over a new one (read the manifest, don't guess what's installed)
- Synchronous code until something actually blocks
Function size: if you cannot state what a function does in one sentence without "and", split it. But do not manufacture single-use helpers that relocate three lines — a file of one-call wrappers is its own tell.
Handle the errors you can actually act on. A blanket catch that logs and continues hides bugs and reads as defensive padding.
Rule 4 — name things like someone fluent in the domain
Realistic. Names come from the problem's own vocabulary, the way the person
who owns this code talks about it: invoiceTotal, retryAfter, staleTokens,
unpaidCycles. If the codebase says accounts, do not introduce users for
the same concept. Read neighboring files for the house vocabulary first.
Unique. A name should identify one thing in the file. The test: grep it — if you land on the concept, it's a good name; if you land on forty unrelated hits, it's a placeholder. Two variables in one function should never differ only by a suffix.
Delete on sight, in any language: data, result, res, temp, tmp, val,
obj, item, info, output, thing, content, handler, helper,
manager, processData, doWork, handleStuff. payload is allowed only
for a literal wire payload.
The version-suffix tell — these encode your edit history instead of meaning, and
they are the single loudest signal that code was generated in passes:
newConfig, config2, updatedConfig, finalConfig, enhancedConfig,
configV2, processedItems, filteredResults. Name the variable for what it
holds now. If the old one still exists too, the two need different concepts, not
different adjectives.
Booleans read as assertions about the world: hasExpired, isRetryable,
shouldFlush — never flag, check, valid, status.
Do not overcorrect. i in a three-line numeric loop is correct. A loop variable
should be the singular of what it iterates (token, row, invoice) — not
element, and not currentInvoiceBeingProcessed. Length should track scope:
short names for short lives, full names for module-level things.
One concept gets one name across the whole diff. If it is deadline in the
handler, it is not expiryTime in the test.
Rule 5 — comments, briefly
Full treatment is deslop Pass 1. The rule while authoring: a comment states
a constraint the code cannot show. Wire-format quirks, why the obvious
approach was rejected, security invariants, platform gotchas. Everything else —
narration, restating the signature, defending the change to a reviewer — is not
written in the first place. Reasons the change is correct belong in the PR body,
not the source.
Rule 6 — match the neighborhood
Before writing in an unfamiliar file, read two or three files next to it. Adopt their import order, error style, logging, test harness, and file layout. Code that is correct but ignores house style still reads as imported from elsewhere.
Before saying it's done
- Walk the constraint ledger against the actual diff, line by line
git diffand read every added comment against Rule 5- Scan every name added for Rule 4's delete-on-sight and version-suffix lists
- Run the deletion audit from Rule 2 — justify every
-line or restore it - Run the repo's own formatter, linter, and the tests the diff touches — the pinned versions from the manifest, not whatever is global
- Run the attribution greps from Rule 0
- Run
deslopon the finished diff
Then report what actually happened. If tests fail, show the output. If part of the scope is unfinished or untested, say which part and why. A confident "done" over unverified work costs more trust than the bug would have.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

