agentleFS
31Carlton731Carlton7/skills/ghostwrite/SKILL.md

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

  • Other versions1 project uses a version of this.

    Word for word · 0

    None found.

    Edited · 0

    None found.

    Wrote their own version · 1

    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.

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
  1. Distinctive:

    Never write, in any commit, PR, issue, or file:

    line 21
  2. Distinctive:

    Verify before every push — this is a two-command check, do not skip it:

    line 35
  3. Distinctive:

    Commit messages: prose in the repo's existing voice.

    line 46
  4. Very specific:

    Before writing anything, read what governs this repo: CLAUDE.md, AGENTS.md, CONTRIBUTING.md, the lint/format config, .editorconfig.

    line 55
  5. Distinctive:

    Keep a constraint ledger. Restate every explicit constraint from the request as a literal checklist, and check each one against the real …

    line 59
  6. Distinctive:

    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 …

    line 70
  7. Distinctive:

    Default: everything that was in the repo before you started stays in the repo.

    line 77
  8. Distinctive:

    Do not, as a side effect of the task:

    line 82
  9. Distinctive:

    Delete functions, exports, types, or files that look unused — "no callers in the files I read" is not the same as "no callers"

    line 84
  10. Distinctive:

    Remove imports, config keys, feature flags, or dependencies that seem stale

    line 89
  11. Distinctive:

    If a line on that list has no reason, restore it.

    line 123
  12. Distinctive:

    Never skip rungs on speculation.

    line 140
  13. Very specific:

    Avoid unless the problem genuinely demands it, and say why in a comment when it does: metaprogramming, reflection, getattr/dynamic dispatch …

    line 143
  14. Very specific:

    Delete on sight, in any language: data, result, res, temp, tmp, val, obj, item, info, output, thing, content, handler, helper, manager, …

    line 178
  15. Very specific:

    Do not overcorrect. i in a three-line numeric loop is correct.

    line 193
  16. Distinctive:

    Before writing in an unfamiliar file, read two or three files next to it.

    line 212
  17. Very specific:

    Run the deletion audit from Rule 2 — justify every - line or restore it

    line 221
  18. Distinctive:

    Run the repo's own formatter, linter, and the tests the diff touches — the pinned versions from the manifest, not whatever is global

    line 222
  19. Distinctive:

    Run the attribution greps from Rule 0

    line 224
  20. Very specific:

    Run deslop on the finished diff

    line 225

≈ “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.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

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/XXX notes, 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:

  1. The request says to remove it
  2. 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 bare deprecated with no condition does not qualify
  3. 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:

  1. Inline the code where it is used
  2. A plain function with concrete parameters
  3. A shared helper, once a second real caller exists
  4. 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/in over 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

  1. Walk the constraint ledger against the actual diff, line by line
  2. git diff and read every added comment against Rule 5
  3. Scan every name added for Rule 4's delete-on-sight and version-suffix lists
  4. Run the deletion audit from Rule 2 — justify every - line or restore it
  5. Run the repo's own formatter, linter, and the tests the diff touches — the pinned versions from the manifest, not whatever is global
  6. Run the attribution greps from Rule 0
  7. Run deslop on 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.

Download now (ZIP)

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
What did you use it for? e.g. Reviewing pull requests in a Rails app

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.