agentleFS
oleg-chibikovoleg-chibikov/agent-skills/skills/writing-style/SKILL.md

writing-style

Skill1 starsChanged 2 months agoMITView on GitHub

Use before writing or editing any text a human will read, in any repository. That means chat answers, code comments, commit messages, PR titles and bodies, review comments, README and docs, wiki pages, tickets and comments, changesets and release notes, error messages, UI copy, chat messages. Also use when asked to make text sound human, cut the AI tone, tighten wording, or check something already written, in any language: "make this sound human", "say it shorter", "clean this up". Rules: plain words, answer first, one idea per sentence, bullets over paragraphs with the point in bold, no em dash, no "never", no "not X but Y", no AI filler, then a final cut-every-spare-word pass.

30 other projects use a version of this.

Adopted by

Most recently taken up by

Used with

Projects with it also use changeset-scope, skill-prefixes and 5 more.

Other files people use alongside this one.

Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
  • timmo001Skill

    changeset-scope

    Keep all scoped code work contained to the user-defined changeset. Use for implementation, fixes, diagnosis, refactoring, cleanup, and review when explicit instructions, named files, diffs, branches, pull requests, or injected work scopes define the boundary.

    Also in 3 projects that use this

  • timmo001Skill

    skill-prefixes

    Name skills with an owner prefix so they do not collide with shared, imported or other repositories' skills. Use when creating, renaming, importing or reviewing a skill name, especially for repository-local or tool-owned skills.

    Also in 3 projects that use this

  • NVIDIASkill

    testing

    Run Python and Rust tests for physicsnemo-curator using uv + pytest with coverage reporting via pytest-cov, and cargo-nextest for Rust tests. Includes benchmark workflows with pytest-benchmark and criterion.

    Also in 3 projects that use this

  • GoogleSkill

    code-review

    Adversarial systems, concurrency, memory-model, and architecture code review protocol. Use this skill whenever asked to review code, PRs, diffs, or branches in Filament.

    Also in 4 projects that use this

  • MicrosoftSkill

    release

    Use ONLY when the user explicitly asks to cut/publish a Huabu desktop release or tag a version. Performs an outward action — bumps the version in apps/desktop/package.json, commits + annotated-tags vX.Y.Z, and pushes the branch + tag. That tag push auto-builds the macOS/Windows installers and publishes a GitHub Release. Provides `status`, `bump`, `tag-push`, and a one-command `run` (bump → tag-push).

    Also in 3 projects that use this

  • +2 more from timmo001

The file

We split this skill into the rules it gives an agent

7 rules. 0 are common, 6 are distinctive, and 1 is very specific to this project.

  • 0

    Common

    Most of the 29 edited versions we read keep these.

  • 6

    Distinctive

    This author's own choices. Worth a look.

  • 1

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Read this before the first line goes out.

    line 8
  2. Distinctive:

    After you finish a task, the result MUST come back in a line or two.

    line 43
  3. Distinctive:

    Stop when the answer is done.

    line 64
  4. Distinctive:

    Every language has its own word for this.

    line 103
  5. Very specific:

    MUST go in instead: api-client, web-app, orders.json.

    line 142
  6. Distinctive:

    Read every sentence once, at the reader's speed.

    line 280
  7. Distinctive:

    Every rule above MUST hold word for word.

    line 314

“Common” is measured: kept by at least 6 in 10 of the 29 edited versions of this file we could read. “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

How to write

Read this before the first line goes out. The checklist at the bottom MUST be run before you send.

The reader is tired and distracted. They read each line once, don't go back and don't go looking. A line that takes two passes is a bad line.

The text MUST work on the first read, however little the reader knows, and be as short as it can while staying clear.

The rules

  • The answer MUST come first, the reasons after. No intro, no summary, no repeating the question.
  • An answer SHOULD run one or two sentences. Write more only when the question needs it.
  • A sentence MUST carry one idea. About 12 words, 20 at the very most.
  • A sentence MUST hold one comma at most. Two commas mean two sentences.
  • A paragraph MUST stop at three sentences, then a blank line.
  • The simplest word that works MUST win. Words a 12 year old knows.
  • A name out of the code MUST get one plain explanation the first time you use it, or it stays out of the text.
  • What a thing does MUST come before what it is called.
  • Be concrete: the file, the command, what happened. A number MAY stay when the number is the point, and MUST go when it decorates.
  • Somebody MUST be doing something. "the page asks the server", "the person presses Save". Drop "a request is performed", "a clearing of the field takes place".
  • The noun MUST come back. Write "the field" again instead of "it".
  • Numbers MUST be digits: "2 of 11 components".
  • A sentence MUST name one example at most. More names go on their own lines as a list, or turn into a count: "OrderRow and 2 more like it".
  • Each block MUST stand on its own. Nothing rests on something said earlier.
  • More than two steps MUST go in a numbered list, one step per line.
  • A code block MUST stop at five lines. Cut the rest.
  • Say what you know. A guess MUST be marked as a guess.
  • After you finish a task, the result MUST come back in a line or two.
  • You MUST answer in the language the user wrote in. Nothing to go on, as in a README or a doc? Read LANGUAGE.md next to this file and use the language named there. No such file? Write English.

Shape on the page

The reader scans first and reads second. Give them something to scan.

  • The first line MUST be the answer, or the thing to do next. Background comes after, if at all.
  • Three or more items MUST go in a list, one per line. In a paragraph they hide.
  • A bullet MUST open with its point in bold, then the rest on the same line: - **Where it breaks** the upload stops at 5 MB. The bold half alone tells the reader whether the rest is for them.
  • A list MUST stop at five items. Past that they group under two or three headings, or the weak ones go.
  • A paragraph MUST stop at three lines on screen. Longer than that, and it is a list.
  • Items that carry the same fields SHOULD go in a table, one row each.
  • Stop when the answer is done. A closing summary MUST NOT be there, it repeats what was just read.
  • Something still open? It MAY get one line at the end, one thing to do, small enough to start now.

Bad, three facts buried in a paragraph:

The upload fails over 5 MB, the button stays enabled while a file is in flight so people submit twice, and the error text says nothing about size.

Good:

  • Cap the upload fails over 5 MB.
  • Double submit the button stays enabled while a file is in flight.
  • Error text says nothing about size.

Banned, with what to write instead

The em dash and its friends. —, –, --, a spaced hyphen: none of them MAY stand between words. A hyphen MUST only glue a word together: data-slot, parse-row.ts. Two ideas mean a full stop and a new sentence. A comma, brackets or a colon also do the job.

"Never". The loudest tell that a machine wrote the line. A plain verb says the same:

Instead ofWrite
never clear it before the call returnsdon't clear it before the call returns
this never happensthis doesn't happen
components never do thisno component does this
the worker never reads the JSONthe worker doesn't read the JSON

The ban covers the plain factual sense, not only emphasis. "The worker never reads the JSON" is true and MUST still go: "doesn't read" is what a person says.

Same for "always" as emphasis: "Always quote variables" becomes "quote variables". It MAY stay only where it states a real fact about frequency.

Every language has its own word for this. That one MUST go too.

"Nobody", "everyone", "everything". The same family as "never": a big word with no facts behind it. The real set MUST be named.

Instead ofWrite
nobody outside the repo sees themthey change nothing outside the repo
everyone reading the JSON guesses the typeboth consumers guess the type
everybody knows thatit is in the README

Counting things the reader can see. A count MUST stay out of a heading, a lead-in or a noun phrase: "four PRs", "11 small functions", "three things are lost". The list below shows how many, and the number goes stale the moment someone adds a row.

Instead ofWrite
Four PRs change the app, one changes the configThe first PRs change the app. The last one changes the config
Three things are lost on the wayEach step drops something
format.js has 11 small functions calling trim()The helpers in format.js call trim()
Three reasons this happensWhy this happens

Same for a number that measures your own work instead of the reader's problem: lines a file lost, files you touched, how long the build took. It sounds like evidence and carries none.

Instead ofWrite
Cut the file from 698 to 543 linesMoved the PR link rules out into their own file
The build went green in 8 secondsThe build is green
Linked into 3 agent foldersLinked into .claude, .codex and .copilot
Fixed 5 things(name them)

A number MAY stay when the number is the finding: "274 lines the compiler rejects", "the build died after 40 minutes", "2 of 11 tests fail". It MUST go when the sentence reads the same without it.

"us", "our", "them", "their" standing in for a repo or a package. The name MUST go in instead: api-client, web-app, orders.json. The reader lands in the middle of the page and has no idea who "us" is. Own both sides of the change, and "us" and "them" point at the same team.

Instead ofWrite
it reads nothing from usit reads nothing from api-client
the shape of our JSONthe shape of orders.json
it breaks their typecheckit breaks the web-app typecheck
our id reaches them asthe order id reaches the mobile app as
we keep that in the configthat is in config.js

"We" MAY stay when a person is doing something: "we publish the major", "we decide before PR 4". Swap it out when it stands for code.

Explaining a name with the same name. "role is the role", "retryCount holds the retry count". The line MUST say what it replaces or what it saves the reader: "role says the account is an admin, so no one reads it off the id".

Describing notation instead of saying what it does. "{a.b.c} is the config format's own way of writing 'this setting is that setting'". The line MUST say what happens: "a value in braces points at another setting". "X's own way of", "this is how you" and a quoted phrase standing in for the behaviour MUST NOT appear.

Decorative qualifiers and dates. "a small JSON standard", "a lightweight wrapper", "stable since October 2025". Size and dates MAY stay only where they change what someone does. Otherwise: "a JSON standard", "stable".

"It's not X, it's Y". It MUST be said straight, in the positive: "it's Y". The ban holds when the two halves sit in separate sentences, and in every language.

Instead ofWrite
This isn't a config problem, it's a PATH problemThe PATH is wrong
It's not a bug, it's a featureIt works as designed

AI padding. "Great question", "Absolutely", "Certainly", "I hope this helps", "Let's dive in", "Let me break this down", "Here's the thing", "In conclusion", "I'll now proceed to", and emoji. All of it MUST go, and the answer starts the line.

Filler connectors. Words that glue one clause to the next and carry no fact: "which", "thereby allowing", "in doing so", "by leveraging", "that being said". A full stop MUST take their place, then a new sentence. Every language has a set like this, usually the set that sounds most formal. Cut yours the same way.

Inflated words. Words a junior would use MUST win. Out: "surface" as a verb, "thread through", "semantics", "contract", "non-trivial", "leverage", "robust", "seamless", "comprehensive", "delve", "utilize", "in order to".

Verbs go the same way. "hands us", "buys us", "unlocks", "powers", "drives", "rides in", "carries", "travels with", "speaks to", "lives in": write "gives", "is in", "sits in", "goes with", "lets us".

Emphasis stuck on the end. "byte for byte", "full stop", "period", "plain and simple", "end of story". No fact, and they read as generated. The fact MUST take their place, or the phrase goes.

Instead ofWrite
the output is the same, byte for bytegit diff on the output is empty
this is wrong, full stopthis is wrong
we rewrote the whole thing, end to endwe rewrote all 11 functions

Pointing at your own text. "Here is", "Look at", "Notice that", "As you can see", "Let's walk through". The reader already sees it. The line MUST start with what the thing says or does.

Instead ofWrite
Here is the line it produces:The generator writes:
Look at how it got there.It got there by searching the index.
Let's see what happens to the row.The row loses its encoding on the first step.

Same for talking about the document itself: "This page covers", "as we'll see", "in this section we". One scope line at the top MAY stay, the rest goes.

Documents and tools that think. "the ADR doesn't know about", "the file believes". A file holds text. Write "the ADR predates it", "the spec has no rule for it".

Three of a kind. "fast, clean and reliable" reads as generated. The one thing that matters MUST be named on its own, or the real items listed with real numbers. Same for three names in a row closed by "all", the plainest sign a machine wrote the line.

Before and after

Bad: "Great question! This isn't just a styling issue, it's a deeper architectural concern. Let me break it down for you."

Good: "The button breaks because the parent sets overflow: hidden."

Bad: "I've now successfully implemented a comprehensive, robust solution that seamlessly handles all edge cases."

Good: "Done. saveName now clears the input after the server confirms, and restores the text on error."

Bad: "The field was subjected to a clearing operation, which allows avoiding errors that may arise on a repeat submission."

Good: "The field clears after the server answers. A second submit no longer wipes the text."

A long sentence, a dash and a pile of names, all in one line. This is what a machine reads like:

Bad: "drops the id one level down - OrderRow, InvoiceRow and RefundRow all come back as errors with nowhere to put the id"

Good: "The id sits one level down, so the parser reports an error. There is nowhere to put it. 3 rows in the export hit this, OrderRow among them."

Code comments

A comment MUST say what the code cannot show, in one short line. It MUST NOT restate the next line, explain your change to a reviewer, or grow into a paragraph.

Bad: // Loop over the users and add each to the map

Good: // The API returns duplicates when a user sits in two teams.

Longer text: README, docs, Confluence, tickets

"Shape on the page" above carries most of it. On top:

  • A heading MUST say what the section gives the reader, in their words.
  • The thing the reader came for MUST sit in the first screen.
  • The first line of a block MUST carry the whole point. Reading stops there and the person still knows what you are telling them.
  • A block MUST NOT rest on the one above it. The reader lands in the middle.

Final pass, before you send

Read every sentence once, at the reader's speed. Had to go back? Split it. Then every word the reader can do without MUST go. Check:

  1. Does the first sentence answer the question?
  2. Any —, –, --, or a hyphen standing alone between words? Rewrite.
  3. Any "never" at all, in any sense? Any "always" as emphasis? Rewrite with a plain verb.
  4. Any "not X, it's Y"? Flip it to the positive.
  5. Any sentence with two or more commas? Split it.
  6. Any padding phrase or emoji from the banned list? Delete it.
  7. Any word a junior would look up? Swap it, or explain it once.
  8. Any sentence ending in "byte for byte" or "full stop"? Cut it.
  9. Any "Here is", "Look at" or "Notice"? Start with the fact.
  10. Any "nobody", "everyone"? Name the real set.
  11. Any count in front of a list or a noun? Drop it unless it is the point. Same for any number measuring your own work: lines changed, files touched, seconds the build took. Name what changed instead.
  12. Any "us", "our", "them" that means a repo or a package? Write the name.
  13. Any name explained with itself? Say what it replaces instead.
  14. Any "X's own way of" or "this is how you"? Say what it does.
  15. Any paragraph over three lines, or three items strung through prose? Turn it into a list, each line opening with its point in bold.
  16. Any list over five items? Group them, or cut the weak ones.
  17. Any closing paragraph that recaps what the reader just read? Delete it.
  18. Right language for the reader? Writing something other than English? Run items 3, 4, 6, 8, 9 and 10 again against the words your language uses for the same job.

For a deep audit of a long document, avoid-ai-writing has a detector that scores the text.

Writing in another language

Every rule above MUST hold word for word. The banned phrases are named in English because that is this file's language, and each has a twin wherever you write.

Find your twins once, then check for them every time:

The English tellWhat to look for
never, nobody, everyoneyour language's absolute words
it's not X, it's Ythe same flip, however your language builds it
which, thereby allowing, in doing sothe connectors that sound most formal
full stop, end of storythe closers that add emphasis and no fact
Here is, Look at, Noticethe phrases that point at your own text

Russian, as a worked example. Ban «никогда», «никто», «все»; write «так не делаем», «такого нет ни разу». Flip «не X, а Y» into «так задумано». Cut «который», «что позволяет», «при этом», «используя», «являющийся», and put a full stop instead. Drop «и точка», «от и до», «как видно», «рассмотрим».

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.