claude-code-guide tells you what to do when you ask.
fairway tells you what to do when you don't know what to ask — and gives you hooks to encourage patterns and discourage antipatterns.
A monolith of small Claude Code devtools sharing one Go binary, one WAL-mode SQLite store safe for multi-process writes, one transcript reader, and one MCP server (JSON-RPC 2.0 over HTTP + SSE) — anything one tool writes another can read, and the MCP surface is the seam for future wire-ins like calling claude-code-guide from inside PreToolUse to enrich hook decisions at fire time.
Pick the ones you want: most are read-only pull commands that need nothing installed, and two wire into your setup with explicit install / uninstall verbs.
go install github.com/bespy/fairway/cmd/fairway@latest
The binary alone creates no files, opens no ports, writes no config. Each tool is opt-in on its own.
Two optional apps consume the daemon's HTTP + MCP surface. Both live in separate repos; neither is required to use anything below.
bespy/fairway-mac (coming soon) — a native SwiftUI menu-bar app. Subscribes to the daemon's SSE stream, aggregates events across sessions, and renders notifications, a waiting queue and per-repo status without polling. The always-on companion for anyone whose primary machine is a Mac.
bespy/fairway-web (coming soon) — a React 19 + Vite + TypeScript + Tailwind CSS v4 dashboard. Consumes the same MCP + REST surface as the Mac app; pairs the live SSE stream with TanStack Table for filterable views over the store, motion for state transitions, lucide-react for iconography. Runs anywhere the daemon is reachable, headless-friendly for CI or remote access.
fairway gaps Claude Code features you own but haven't tried
fairway friction recurring frictions in your sessions, matched to features
fairway insights a mechanical usage profile from your local transcripts
fairway agents who else is live in this repo right now
fairway status what fairway is wired into, and what has fired
fairway report an HTML page of what the rules have caught
fairway replay import a retired hook JSONL into the store (dev-only)
Cross-references Anthropic's feature index (code.claude.com/llms.txt) against your local transcripts and shows what you own but haven't used. Currently naive string matching; LLM-in-the-loop to come. Sample output:
◇ Connect to external tools with MCP unknown
Configure MCP servers to extend your agent with external tools…
https://code.claude.com/docs/en/agent-sdk/mcp.md
◇ Find bugs with ultrareview unknown
Run a deep, multi-agent code review in the cloud with /code-review ultra…
https://code.claude.com/docs/en/ultrareview.md
◆ Rewind file changes with checkpointing dormant 14+ days
◇ never used. ◆ known but dormant. --json for machine-readable output. Cached — runs offline after the first fetch.
claude /insights writes an HTML report with a "Where Things Go Wrong" section that summarises the frictions Anthropic's own facet extractor found in your sessions. fairway friction reads the same facet files (~/.claude/usage-data/facets/*.json), aggregates the friction counts across every judged session in the last 30 days, and prints them ranked with a per-friction prescription — the specific Claude Code feature that addresses each. One CLI line per friction, fresh on every run (the HTML report is only regenerated when you invoke /insights manually). Runs offline. --json for machine-readable output.
claude /insights generates a local HTML report analysing patterns across your sessions — features you use, tools you lean on, where things go wrong. fairway insights derives an equivalent profile from every local transcript on the machine, cross-referenced against the fairway store (which rules fired, in which repo). The counterpart to gaps — that one names features you own but haven't tried; this one names the ones you've tried but forgotten about. The token-and-money axis will land as its own subcommand extending claude /usage (planned; fw-35).
claude agents opens the agent view for sessions dispatched from it or backgrounded with /bg. fairway agents is the same view over the wider set: every live Claude Code session on this machine, because writing to the session registry is a side effect of starting rather than an opt-in.
Grouped the same way — Needs input · Working · Completed — so the natural next line is "enrol these in claude agents" rather than "use mine instead". --json for machine-readable output.
Which rules fired, in which repo, blocking or warning. Same shape as git status, for the rule engine. Also reports which wire-in tools are installed and where their wiring lives, so a silent misconfiguration is visible.
Renders the local store to a self-contained HTML page: no script, no listener, no network. Cross-links Claude Code's own /insights output when it exists on disk. --demo renders a generated 21-day dataset alongside, so the layout is legible before you have real fires.
Dev instrument. replay <file.jsonl>... replays captured hook payloads into the local store, for testing rule changes offline. Stays wired for debugging; not part of the pitch.
fairway hook install PreToolUse / PostToolUse guards, written into .claude/settings.json
fairway serve install long-lived HTTP + MCP daemon, wired via launchd or systemd
Both have matching uninstall verbs that remove exactly what install added.
Claude Code lets you register shell commands as PreToolUse and PostToolUse hooks; fairway hook install writes fairway's entries into <cwd>/.claude/settings.json (project-scoped by default; --global targets ~/.claude/settings.json, with confirmation). Claude Code then invokes the hook on every tool call: involuntary, deterministic, fails open. fairway hook uninstall removes only fairway's entries and leaves the rest of your settings.json alone.
The failure that made this tool exist:
Terminal 1 (feature work) Terminal 2 (same checkout)
┌────────────────────────┐ ┌────────────────────────┐
│ Claude A │ │ Claude B │
│ editing src/auth/*.ts │ │ about to `git merge` │
│ 3 files uncommitted │ │ │
│ │ ◀────── │ ⚠ warned BEFORE the │
│ │ fairway │ merge — names the │
│ │ hook │ peer and the paths │
└────────────────────────┘ └────────────────────────┘
Two sessions in one repo, one runs git add -A or a merge, and a peer's uncommitted work is contaminated or gone. Parallelism doesn't cause the failure — it amplifies the blast radius.
A real intervention, verbatim from the receiving session's transcript:
fairway shared-checkout warning (not a block): you are about to run `git merge`
while this repo has 3 uncommitted path(s) AND 1 other live session(s) working
in it. Some of that work may belong to the other session.
Confirm none of it is theirs — or say so to the user — before rewriting the
working tree.
The agent stopped, checked, reported to the human, and continued — without ever having been told the protocol existed. The hook exists to train the agent; the guide exists to train the user.
Rules are plain Go. Adding your own is the point; the catalogue of what's worth catching is as much the product as the code.
Optional. fairway serve install writes a launchd agent (macOS) or systemd user unit (Linux) that keeps the daemon running on 127.0.0.1:47822. uninstall unloads and removes it. Only needed if you want live cross-session state fed back to any Claude Code session as an MCP tool, or exposed to a UI over REST + SSE.
MCP is JSON-RPC 2.0 at POST /mcp. Tools any session can call once fairway is under mcpServers:
fairway.awaiting— who else is waiting on youfairway.sessions— the full state listfairway.worst_sessions— sessions ranked by frictionfairway.stuck_exploration— cwds where you're stuck scopingfairway.gaps— the ranked list above
Ask Claude "who else is waiting on me" and it calls fairway.awaiting and answers inline. String fields originating in other sessions are wrapped as <untrusted-session-input> so a hostile prompt in one session cannot instruct Claude through the tool response in another. Only Host: 127.0.0.1:47822 or localhost:47822 is accepted — everything else returns 421.
fairway emit is the sidecar advisory hooks (Notification, Stop, PermissionRequest, SessionStart, PostToolUse) invoke to push their payload into serve. Fails open on everything; a broken daemon must not break the session's hook chain.
- claude-code-guide — reference for setup, commands, workflows, agents, skills and tricks
- ccusage — token-usage and cost reports from your local Claude Code data
- claude-trace — capture Claude Code's HTTP traffic, browse it in an HTML viewer
- ccmanager — multi-session manager across Claude Code, Gemini, Codex and friends
- claude-peers-mcp — Claude Code instances discover each other and send messages
- cross-claude-mcp — message bus across Claude, ChatGPT and Gemini
- claude-code-hooks — library of ready-made hooks with an installable marketplace
- Anthropic's
/insights— retrospective analysis of your session history, in-product
Not just this project's problem — prior similar issues in other projects, all open:
- claude-peers-mcp#72 — repo-scoped work claims and leases for parallel sessions
- openclaw#43367 — concurrent agents overwriting each other's config, session-lock failures
- Fusion#2186 — per-session sandboxes and symbol-level conflict locking
- claude-peers-mcp#23 — repo scope breaks under git worktrees
A fairway is the safe route through a hazardous space: in a harbour, the marked channel deep enough to navigate; in golf, the mown strip you're aiming for.
Early, and in daily use by its author. agents, hook, status, report and gaps run against real sessions every day. serve and its MCP tools are stable enough to point a UI at. If you have an antipattern that has cost you real work — yours or your agent's — open an issue.
Do I have to run the daemon to use the hook?
No. fairway hook pretooluse is invoked by Claude Code directly. The daemon (fairway serve) is only needed for the MCP tools and any UI wired against them.
Do I have to install the hook to use fairway gaps (or report, or insights)?
No. The read-only tools work against files already on your disk. Nothing to wire, nothing to enable.
Does go install do anything besides put the binary on my PATH?
No. No directories, no config, no store, no daemon. Each tool has its own opt-in.
Does fairway send anything anywhere?
No. The only network calls are the local daemon on 127.0.0.1:47822 and the one-shot fetch of code.claude.com/llms.txt for fairway gaps. Cache-first; the daemon runs offline forever.
I see macOS code in here — what is that for?
The fairway CLI, hook and daemon run wherever Go runs. fairway serve install writes launchd on macOS and systemd on Linux. The macOS-specific bits beyond that are for the optional companion apps described in Companions above.
Agentic AI — agent-orchestration · agent-harness · agent-supervisor · agentic-infrastructure · prompting · tool-use · structured-output · multi-step-workflows · mcp · llm-observability · non-deterministic-systems · production-ai
Backend & production — go · sqlite · wal-mode · multi-process-write · no-cgo · pure-go-sqlite · http-server · json-rpc-2.0 · sse · cross-platform · local-first · zero-dependency · fails-open · defence-in-depth · security-hardening · test-driven · cli
Frontend & native (companions) — react · react-19 · typescript · vite · tailwind · tailwind-v4 · tanstack-table · motion · lucide · oxlint · swift · swiftui · macos · menu-bar-app · sse-consumer · rest-client
Domain — claude-code · hooks · intercepts · usage-analytics · distributed-supervisor
Coming soon — launchd* · systemd* · token-cost-tracking* · retrieval* · evals* · datasets* · metrics* · experiments* · web-agents* · real-time-data* · structured-data-extraction*
* on the roadmap; open issues in the tracker.