Skip to content

/gaia-fitness

/gaia-fitness checks your project’s Claude integration (skills, commands, agents, rules, hooks, settings, CLAUDE.md files, and the wiki) and reports an F-to-A+ grade. A linter (a script that gives the same result every time) does the checking and the grading. A separate review by Claude covers what a script can’t judge. It only gives advice and never changes the grade.

It runs like every maintenance command: from the main checkout, with any fixes on a branch of its own, ending in a pull request. Only you start it, by typing it; Claude never runs it on its own.

Claude picks a skill by its description and reads every always-loaded file before you type anything, so a vague description, an oversized file, or a broken path quietly makes Claude worse at following your guidance. Most of the rules follow Anthropic’s skill authoring best practices (opens in a new tab), such as a third-person description that says what the skill does and when to use it, and a SKILL.md under 500 lines.

Run it after adding or editing skills, rules, commands, or agents, or when Claude starts ignoring guidance you know is there.

The statusline suggests /gaia-fitness for the first of these reasons that holds. Harness files are the files this command checks, except wiki pages and third-party files such as an installed skill.

NudgeShows when
💪 /gaia-fitness (grade B+)The check finds something in a file your project owns. The reason is the overall grade.
💪 /gaia-fitness (3 blended files)An /update-gaia run combined your team’s edits with GAIA’s changes in harness files, and no /gaia-fitness run has reviewed them since the update reached your main checkout.
💪 /gaia-fitness (15 harness commits)Your team has made at least 15 commits that change harness files since the last /gaia-fitness run. GAIA’s own scaffold and update commits do not count, and neither do commits not yet pulled into your main checkout. Before your first run, every commit counts. In a shallow clone, this reason never shows.

The commit count defaults to 15. To change it, ask Claude:

Change the /gaia-fitness nudge to show after 30 harness commits instead of 15.

Claude sets fitness_commit_threshold in .gaia/project.json, your team’s shared GAIA settings, to a positive whole number. It is a team setting, so the change lands through a pull request. Without a valid value, the count is 15.

A run clears the blended-files and harness-commits reasons and refreshes the nudge right away. It does not clear the grade reason: that one clears only when you fix the finding or suppress it with a reason. An oversized CLAUDE.md belongs to /gaia-cleanse and never shows this nudge.

/gaia-fitness runs a fixed list of 57 rules over your project’s own files. Each rule belongs to one category, and every category except memory gets its own grade.

CategoryWhat its rules check
authoringHow skills, commands, and agents are written: a description that says what the file does and when to use it, in the third person; files under 500 lines; a table of contents on long files; links that resolve; reference files that something links to; no Windows-style paths.
CLAUDE.mdYour CLAUDE.md files (rule ids start claudemd.): a root CLAUDE.md exists, each file stays within its size budget, @ imports and paths resolve, and no path names a folder on one person’s machine (such as /Users/<name>/).
frontmatterThe block at the top of each skill, command, and agent: it parses, has a valid name and a non-empty description within the length limits, and no two share a name.
hooksHooks registered in your settings: each uses an event Claude Code knows, and each names a script that exists and can run, by a path that works from any folder.
memoryMemory files that name a path in the project that no longer exists. Counted in the inventory, but not graded and not shown on the card.
promptWording that tends to make Claude work worse, such as all-caps MUST or NEVER in a description, “think step by step”, “keep updates brief”, or unbalanced XML tags.
rulesRule files: valid paths: globs, paths that exist, and no rule importing a skill.
settingsSettings files: valid JSON, no secrets in env, settings.local.json kept out of git, no duplicate permissions, and a valid suppression file (see Suppressing a finding).
wikiWiki pages that cite a path that no longer exists, or that no other page links to.

Each finding has a severity, and the category’s grade follows from its findings:

  • A structural problem (such as a file that cannot be parsed) is an F.
  • Errors give a C+ for one, down to D- for six or more.
  • Warnings give a B+ for one, B for two, and B- for three or more.
  • Informational findings give an A for one or two, and A- for three or more. They never lower a grade further than A-.

The overall grade is the lowest category grade. A category with nothing to check shows n/a.

Only your own files are graded. A finding in a file GAIA ships is listed separately, in an upstream section, and is fixed by /update-gaia.

The run also reports whether Claude Code’s own built-in checks (claude doctor, claude plugin validate) ran or were skipped. For the Claude Code diagnostics and prompt review it does not run, use /doctor and /doctor prompt-audit interactively.

When there is something to judge, one Sonnet agent (fitness-judge) answers four questions no script can. It reads files but never changes them.

  • Description substance: does a skill’s or command’s description say when to use it?
  • Trigger overlap: do two skills claim the same requests?
  • Rule scope: does a rule’s content fit the files its paths: globs load it for?
  • Terminology: does one skill use one term for one thing?

Its findings are advice only. They are not graded, and nothing is fixed from them.

The report starts with a report card: one row per category, with the count of findings and the grade, and the overall grade at the top. Under it, each finding names its severity, the file and line, the rule, and how to fix it. For a skill whose description reads I write release notes.:

+------------------------------------------------------------------------------+
| GAIA FITNESS OVERALL B+ |
+------------------------------------------------------------------------------+
| authoring 1 warning, 2 info B+ |
| CLAUDE.md A+ |
| frontmatter A+ |
| hooks n/a |
| prompt A+ |
| rules n/a |
| settings n/a |
| wiki n/a |
+------------------------------------------------------------------------------+
| FINDINGS |
| |
| authoring: B+ |
| [warning] .claude/skills/release-notes-helper/SKILL.md:3 |
| authoring.skill.description.first-person |
| Write the description in the third person, as what the file does |
| and when to use it. |
| [info] .claude/skills/release-notes-helper/SKILL.md:3 |
| authoring.skill.description.no-when |
| Add a trigger to the description, for example "Use when the user |
| asks for ...". |
| [info] .claude/skills/release-notes-helper/SKILL.md:3 |
| authoring.skill.description.too-short |
| Describe what it does and when to use it in a full sentence or |
| two. |
+------------------------------------------------------------------------------+

Here one warning sets the authoring grade to B+, and because it is the lowest category grade, the overall grade is B+ too. The two informational findings alone would have given an A. hooks, rules, settings, and wiki show n/a because this project has nothing in them to check.

After the card come the built-in checks, Claude’s advisory findings from the judgment pass, and how to fix each finding.

  1. Check the repository state. If the repository is in the middle of a rebase, merge, cherry-pick, or bisect, or on a detached HEAD, the run reports and grades but makes no fixes, and tells you how to get out of that state.
  2. Check and judge. The linter, the built-ins, and the judgment pass run.
  3. Report. The report card prints as a box, followed by the built-in checks, Claude’s advisory findings, and how to fix each finding.
  4. Fix. For each finding the linter marks as fixable, a separate Sonnet agent proposes the complete new file. You see the diff and answer Apply or Skip, one file at a time. Fixes are written only to your project’s own files. Before writing, GAIA checks again that the file is yours, refuses a path that leads outside the project through a symlink, and refuses a file that changed since you saw the diff. A GAIA-shipped file is never edited. When a fix would change too much, you get a recommended approach instead of a diff.
  5. Verify. The linter runs once more and reports what was fixed and anything new, with a fresh report card. There is no second round of fixes.
  6. Publish, asked once when at least one fix was applied:
    • Publish (recommended): commit, push, open a pull request, and merge it through the audit gate.
    • Open PR only: commit, push, and open a draft pull request without merging.
    • Keep for review: leave the changes on the run’s branch, uncommitted, with the commands to review or discard them.

A clean run prints No findings. Overall A+. No changes made, no branch created. A run with nobody to answer (a headless session) reports and stops without fixing anything.

The run ends with a cost line.

When a finding is deliberate, ask Claude to suppress it. Give the rule, the file, and your reason:

Suppress the authoring.playbook.max-lines fitness finding for
.claude/skills/my-skill/references/big.md. Reason: it is a generated reference, and
splitting it would break the generator.

Claude adds an entry to .claude/gaia-fitness.json, by rule id and path, with your reason:

{
"version": 1,
"ignore": [
{
"rule_id": "authoring.playbook.max-lines",
"path": ".claude/skills/my-skill/references/big.md",
"reason": "Generated reference; splitting it would break the generator."
}
]
}

An entry without a reason is not applied. A malformed file, or an entry that names a rule or path that no longer exists, is itself a finding.

/gaia-cleanse reviews what your project’s memory and auto-loaded files say. /gaia-fitness reviews whether the integration is built well.