Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions analysis/dead-code.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ fallow dead-code --unresolved-imports --unlisted-deps
```json
{
"schema_version": 9,
"version": "3.17.0",
"version": "3.19.0",
"elapsed_ms": 160,
"total_issues": 401,
"unused_files": [
Expand Down Expand Up @@ -152,9 +152,9 @@ fallow dead-code --unresolved-imports --unlisted-deps
```json
{
"$schema": "https://json.schemastore.org/sarif-2.1.0.json",
"version": "3.17.0",
"version": "3.19.0",
"runs": [{
"tool": { "driver": { "name": "fallow", "version": "3.17.0" } },
"tool": { "driver": { "name": "fallow", "version": "3.19.0" } },
"results": [
{
"ruleId": "fallow/unused-export",
Expand Down
72 changes: 72 additions & 0 deletions cli/agent.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
---
title: "fallow agent"
description: "CLI reference for fallow agent. Wire fallow into Claude Code, Codex, and Cursor in one pass: AGENTS.md task map, skill, MCP server registration, and the commit/push gate, with status and uninstall."
keywords: ["fallow agent", "agent install", "Claude Code", "Codex", "Cursor", "MCP", "AGENTS.md", "skill", "onboarding", "CLI"]
icon: "terminal"
---

Wire fallow into the coding-agent harnesses a project uses, in one command. `fallow agent install` detects Claude Code, Codex, and Cursor, then writes what each one reads: an `AGENTS.md` task map, the fallow skill, the MCP server registration, and the commit/push gate. `fallow agent status` shows what is installed, and `fallow agent uninstall` removes exactly what fallow wrote.

```bash
fallow agent install --dry-run # show the plan first
fallow agent install # wire every detected harness
```

<Info>
`fallow init --agents`, `fallow hooks install --target agent`, and the hand-written MCP snippet keep working. `agent install` composes them; it does not replace them.
</Info>

## Detection

Without `--harness`, a harness is selected when any of its signals is present. Nothing is fabricated when no signal exists: a Cursor-only repository never gets a `.claude/` directory.

| Harness | Project | Home | Session |
|:--------|:--------|:-----|:--------|
| Claude Code | `.claude/`, `CLAUDE.md`, `.mcp.json` | `~/.claude/` | `CLAUDECODE` |
| Codex | `.codex/` | `~/.codex/` | `CODEX_THREAD_ID` |
| Cursor | `.cursor/` | `~/.cursor/` | `CURSOR_AGENT` |

When nothing is detected, only the harness-neutral files are written (`AGENTS.md` and `.agents/skills/fallow`) and the output names the `--harness` values you can pass. `AGENTS.md` itself is not a detection signal, because every harness and fallow write it.

## What each step writes

| Step | Claude Code | Codex | Cursor |
|:-----|:------------|:------|:-------|
| `guide` | `AGENTS.md` task map; `CLAUDE.md` gains an `@AGENTS.md` import (created when absent, appended as a marked block otherwise) | `AGENTS.md` task map | `AGENTS.md` task map (Cursor reads it) |
| `skill` | `.claude/skills/fallow/` | `.agents/skills/fallow/` | `.agents/skills/fallow/` |
| `mcp` | `mcpServers.fallow` in `.mcp.json` | `[mcp_servers.fallow]` in `.codex/config.toml` | `mcpServers.fallow` in `.cursor/mcp.json` |
| `hooks` | PreToolUse gate in `.claude/settings.json` plus `.claude/hooks/fallow-gate.sh` | marked gate block in `AGENTS.md` | skipped (`unsupported_harness`) |

**Skill.** When the project has `node_modules/fallow/skills/fallow`, the installed skill is a small pointer to that copy, so it never drifts from the fallow version the project pins. Without it, the version-matched skill embedded in the binary is written. A skill named `fallow` that fallow did not write is refused (`skill_name_taken`) unless you pass `--force`.

**MCP.** The command is probed before anything is written: `npx --no fallow-mcp` for an npm-installed project, `fallow-mcp` from `PATH`, or the running binary when it is the npm multicall build. When none exists the step is skipped with `mcp_entry_unavailable` instead of writing a registration that cannot start. A project-level `.codex/config.toml` only applies once Codex trusts the project, so the output leads with the `codex mcp add fallow -- ...` command that works immediately.

**Approval.** Claude Code asks before starting a project-scoped MCP server. `--approve` records that approval for you by listing `fallow` in `.claude/settings.local.json`; it is opt-in and refused when that file is tracked by git.

## Markers, idempotency, and uninstall

Every file or block carries a `<!-- fallow:agent-install v1 ... -->` marker. Re-running is byte-stable and reports every step as `unchanged`. Files fallow did not write are never overwritten without `--force`; a `fallow` MCP entry counts as fallow's only when its command is one fallow writes, so a hand-written entry is refused (`mcp_entry_foreign`) and kept. `--force` on an unparsable config file saves the old bytes as `<file>.fallow-bak` first. `uninstall` removes managed blocks and entries, deletes a config file it emptied, and deletes `AGENTS.md` or `CLAUDE.md` only while the file still matches what fallow authored.

## Options

| Flag | Applies to | Description |
|:-----|:-----------|:------------|
| `--harness <auto\|claude\|codex\|cursor>` | `install`, `uninstall` | Repeatable; default `auto` |
| `--without <guide\|skill\|mcp\|hooks>` | `install` | Skip a step; repeatable |
| `--dry-run` | `install`, `uninstall` | Print the plan without touching the filesystem |
| `--force` | `install`, `uninstall` | Replace or remove skills, hook scripts, or config files fallow did not write |
| `--approve` | `install` | Pre-approve the project MCP server for yourself in `.claude/settings.local.json` |
| `--user` | `install`, `uninstall` | Skill and MCP config under `$HOME` instead of the project; the guide step is skipped, and Claude Code prints the `claude mcp add --scope user` command instead of editing `~/.claude.json` |
| `--gitignore-claude` | `install` | Append `.claude/` to `.gitignore` |

The root is the git toplevel of the current directory unless `--root` is passed explicitly, so a run from a monorepo package still writes where the harnesses read. The chosen root is the first line of output.

## Output

Human output groups paths under "Shared with your team (commit these)" and "Local to you". With `--format json` the envelope carries `kind` (`agent-install`, `agent-uninstall`, `agent-status`), `schema_version`, and `fallow_version`, and every step carries `harness`, `step`, `status` (`written`, `removed`, `unchanged`, `skipped`, `refused`, `failed`), `scope`, `path`, and a `reason` when it was skipped or refused, followed by `next_actions` (each flagged `mutating` when running it would write harness config, unlike the read-only `next_steps` of the analysis commands). The exit code is 2 when any step is `refused` or `failed`; every other step still runs.

```bash
fallow agent install --format json --quiet
fallow agent status --format json
fallow agent uninstall --dry-run
```
2 changes: 1 addition & 1 deletion cli/audit.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ Audit scope: 12 changed files vs main (d4a2f91..HEAD)
```json title="$ fallow audit --format json"
{
"schema_version": 10,
"version": "3.17.0",
"version": "3.19.0",
"command": "audit",
"verdict": "fail",
"changed_files_count": 12,
Expand Down
2 changes: 1 addition & 1 deletion cli/flags.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ fallow flags --production
```json title="$ fallow flags --format json"
{
"schema_version": 8,
"version": "3.17.0",
"version": "3.19.0",
"elapsed_ms": 116,
"feature_flags": [],
"total_flags": 0
Expand Down
20 changes: 10 additions & 10 deletions cli/health.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ The `--save-snapshot` flag forces file-scores and hotspot computation so that al
```json title="snapshot.json"
{
"snapshot_schema_version": 10,
"version": "3.17.0",
"version": "3.19.0",
"timestamp": "2026-03-25T14:30:00Z",
"git_sha": "a1b2c3d",
"git_branch": "main",
Expand Down Expand Up @@ -718,7 +718,7 @@ fallow health --coverage-gaps --file-scores
```json title="$ fallow health --format json --top 2"
{
"schema_version": 11,
"version": "3.17.0",
"version": "3.19.0",
"elapsed_ms": 140,
"summary": {
"files_analyzed": 252,
Expand Down Expand Up @@ -804,7 +804,7 @@ When `--file-scores` is used, the JSON output includes additional fields:
```json title="$ fallow health --file-scores --format json --top 2"
{
"schema_version": 11,
"version": "3.17.0",
"version": "3.19.0",
"elapsed_ms": 320,
"summary": {
"files_analyzed": 252,
Expand Down Expand Up @@ -858,7 +858,7 @@ When `--hotspots` is used, the JSON output includes a `hotspots` array and `hots
```json title="$ fallow health --hotspots --format json --top 2"
{
"schema_version": 11,
"version": "3.17.0",
"version": "3.19.0",
"elapsed_ms": 480,
"summary": {
"files_analyzed": 252,
Expand Down Expand Up @@ -924,7 +924,7 @@ When `--targets` is used, the JSON output includes a `targets` array:
```json title="$ fallow health --targets --format json --top 2"
{
"schema_version": 11,
"version": "3.17.0",
"version": "3.19.0",
"elapsed_ms": 520,
"summary": {
"files_analyzed": 252,
Expand Down Expand Up @@ -1006,7 +1006,7 @@ When file-scores are enabled (via `--file-scores` or implicitly via `--save-snap
```json title="$ fallow health --file-scores --format json (vital_signs excerpt)"
{
"schema_version": 11,
"version": "3.17.0",
"version": "3.19.0",
"vital_signs": {
"dead_file_pct": 4.2,
"dead_export_pct": 12.8,
Expand Down Expand Up @@ -1232,7 +1232,7 @@ coverage-gaps = "warn"
```json title="$ fallow health --coverage-gaps --format json"
{
"schema_version": 11,
"version": "3.17.0",
"version": "3.19.0",
"elapsed_ms": 280,
"coverage_gaps": {
"summary": {
Expand Down Expand Up @@ -1277,7 +1277,7 @@ When `--runtime-coverage` is used, the JSON output includes a `runtime_coverage`
```json title="$ fallow health --runtime-coverage ./coverage --format json"
{
"schema_version": 11,
"version": "3.17.0",
"version": "3.19.0",
"elapsed_ms": 412,
"runtime_coverage": {
"verdict": "hot-path-touched",
Expand Down Expand Up @@ -1391,9 +1391,9 @@ fallow health --format sarif
```json title="$ fallow health --format sarif (excerpt)"
{
"$schema": "https://json.schemastore.org/sarif-2.1.0.json",
"version": "3.17.0",
"version": "3.19.0",
"runs": [{
"tool": { "driver": { "name": "fallow", "version": "3.17.0" } },
"tool": { "driver": { "name": "fallow", "version": "3.19.0" } },
"results": [
{
"ruleId": "fallow/high-cyclomatic-complexity",
Expand Down
2 changes: 2 additions & 0 deletions cli/init.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ Anything ambiguous stays blank rather than guessed: fallow never sniffs a packag
fallow init --agents
```

[`fallow agent install`](/cli/agent) writes the same guide together with the skill, the MCP registration, and the commit/push gate for every harness it detects.

## Pre-commit hook

Use the hooks namespace to scaffold a git hook that runs `fallow audit` against the base branch before each commit:
Expand Down
1 change: 1 addition & 0 deletions cli/schema.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ The manifest is also the source the agent-skill tables are generated from (the c
| `issue_types` | One row per reportable issue type across all analyses (see below). |
| `task_matrix` | The agent task-to-command cheat sheet: one row per common agent intent (`task`) with the read-only command to run (`command`, may contain `<placeholder>` tokens) and an optional `note`. The same matrix renders into `fallow init --agents`, the managed AGENTS.md block, the root `--help`, and the fallow skill. Rows never name mutating commands. |
| `mcp_tools` | Every MCP server tool with a `kind` grouping (`analysis`, `trace`, `fix`, `introspection`, `runtime-coverage`, `composition`), a one-line description, `key_params` (a curated subset; the live MCP `list_tools` schemas are authoritative), `license` plus `license_note`, and `read_only`. |
| `mcp_resources` | Every MCP resource and resource template (`uri`, `name`, `title`, `description`, `mime_type`, `template`): the read-only reference channel of `fallow-mcp` (tool manifest, issue-type registry, explain index and template, task matrix, JSON Schemas). Same order as `resources/list`. |
| `plugins` | Built-in framework plugin count and names, derived live from the plugin registry. |
| `environment_variables` | Every user-facing `FALLOW_*` variable with a one-line description. |
| `output_formats`, `exit_codes`, `severity_levels`, `suppression_comments` | Output and exit-code contract reference. Formats include accepted aliases and are derived from the CLI parser; exit codes include the complete public workflow ladder. |
Expand Down
4 changes: 2 additions & 2 deletions cli/security.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ One `security-sink` token covers every catalogue category. Use suppression only
{
"kind": "security",
"schema_version": 8,
"version": "3.17.0",
"version": "3.19.0",
"elapsed_ms": 42,
"config": {
"rules": {
Expand Down Expand Up @@ -248,7 +248,7 @@ One `security-sink` token covers every catalogue category. Use suppression only
{
"kind": "security",
"schema_version": 8,
"version": "3.17.0",
"version": "3.19.0",
"elapsed_ms": 42,
"config": {
"rules": {
Expand Down
1 change: 1 addition & 0 deletions docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@
"cli/fix",
"cli/watch",
"cli/init",
"cli/agent",
"cli/recommend",
"cli/plugin-check",
"cli/migrate",
Expand Down
4 changes: 4 additions & 0 deletions integrations/agent-skills.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ The [fallow-skills](https://github.com/fallow-rs/fallow-skills) package includes

## Installation

<Tip>
A project that already has fallow installed from npm can skip the manual steps: [`fallow agent install`](/cli/agent) writes the skill where Claude Code, Codex, and Cursor look for it, together with the MCP registration, an `AGENTS.md` task map, and the commit/push gate. `--dry-run` shows the plan first.
</Tip>

<Tabs>
<Tab title="Claude Code">
```bash
Expand Down
4 changes: 4 additions & 0 deletions integrations/claude-hooks.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ fallow hooks install --target agent (install):
AGENTS.md managed block inserted
```

<Note>
[`fallow agent install`](/cli/agent) installs this gate together with the skill, the MCP registration, and an `AGENTS.md` task map for every harness it detects. The older `fallow setup-hooks` command is deprecated: it still works throughout fallow 3 with a warning and is removed in the next major.
</Note>

## Install globally for every repo

Pass `--user` to install the gate under your home directory instead of per-project. The settings file lands at `~/.claude/settings.json`, the hook script at `~/.claude/hooks/fallow-gate.sh`, and the emitted handler command uses `"$HOME"` in place of `"$CLAUDE_PROJECT_DIR"` so it resolves in every repo Claude Code opens:
Expand Down
19 changes: 17 additions & 2 deletions integrations/mcp.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ The MCP server uses <Tooltip tip="Communication via standard input/output stream
claude mcp add fallow --scope project fallow-mcp
```

`--scope project` creates `.mcp.json` in the repository root. You can write that file by hand instead:
`--scope project` creates `.mcp.json` in the repository root. [`fallow agent install`](/cli/agent) writes the same entry for every detected harness, probing for a working launcher first. You can also write the file by hand:

```json
{
Expand Down Expand Up @@ -269,7 +269,7 @@ Cloud runtime tools can include source-map confidence metadata when the response
```json Example response
{
"schema_version": 9,
"version": "3.17.0",
"version": "3.19.0",
"elapsed_ms": 42,
"total_issues": 1,
"unused_exports": [
Expand Down Expand Up @@ -349,6 +349,21 @@ The array is deduplicated, priority-ordered, capped at three, and omitted when e

The `value_schema` URL is a JSON Pointer fragment into fallow's published `schema.json`. Agents that want to validate `value` before writing it into a user's config (for example, to reject a malformed `{ file, exports }` rule object on the `ignoreExports` action) can fetch the linked schema and apply it locally. The field is strictly additive: actions that did not have a schema before continue to work without one, and agents that ignore the field keep working unchanged.

## Resources

Besides tools, the server exposes read-only reference material as MCP resources: no subprocess, no analysis run, cacheable by URI (your client reads them through its own resource tool, for example `ReadMcpResourceTool` in Claude Code). Every payload is plain JSON; the server version travels in each content item's `_meta.fallow_version`, so a cached copy is self-describing and the schema resources stay valid strict JSON Schema. The catalogue is fixed at build time (no subscriptions, no list-changed notifications).

| Resource | Content |
|:---------|:--------|
| `fallow://tools` | The tool manifest: name, one-line description, nearest CLI fallback, key parameters, license, and read-only flag for every tool |
| `fallow://issue-types` | Every issue type with its command, category, config key, zero-config default severity, opt-in and fixable flags, docs URL, and explain URI |
| `fallow://explain` | Index of every explainable issue type with a one-line summary and its `fallow://explain/{issue_type}` URI |
| `fallow://explain/{issue_type}` | The explain document for one issue type, the same payload as `fallow explain <issue-type> --format json` |
| `fallow://task-matrix` | The task-to-command matrix that also drives `AGENTS.md` and `fallow --help`: which read-only command to run before deleting, refactoring, committing, or scoping work |
| `fallow://schema/config`, `fallow://schema/plugin`, `fallow://schema/rule-pack` | The JSON Schemas printed by `fallow config-schema`, `fallow plugin-schema`, and `fallow rule-pack-schema` |

`{issue_type}` accepts the bare id (`unused-export`), the namespaced id (`fallow/unused-export`), or the CLI filter spelling. Unknown URIs return a structured error whose `data` lists the known URIs; an unknown issue type lists the nearest matches. The numeric code is `-32002` for clients on protocol versions before 2026-07-28 and `-32602` from then on, so key on `data` rather than the code. The same catalogue is published as `mcp_resources` in [`fallow schema`](/cli/schema).

## Combined output from bare `fallow`

Running bare `fallow` (no subcommand) executes all analyses in one pass and returns a combined JSON object with `dead_code`, `duplication`, and `health` sections:
Expand Down