Skip to content

docs: AI-agent setup guides, per-tool tuning guides, and full SEO pass - #1

Merged
andylbrummer merged 8 commits into
mainfrom
docs/seo-and-agent-guides
Jul 31, 2026
Merged

docs: AI-agent setup guides, per-tool tuning guides, and full SEO pass#1
andylbrummer merged 8 commits into
mainfrom
docs/seo-and-agent-guides

Conversation

@andylbrummer

Copy link
Copy Markdown
Member

Grows the site from 2 pages to 28, adds the technical SEO layer it never had, and records the audit.

Two new sections

/setup/ — 9 per-agent guides. Organised around the one property that decides what tman can do, verified from vendor docs rather than assumed:

tier agents
rewrites the command Claude Code, Codex CLI, Gemini CLI, opencode
gates it (allow/deny only) Cursor, Antigravity, Kimi, Copilot CLI
shims only Aider, Amp, Windsurf, Zed, CI

Codex CLI turned out to use field-for-field the same PreToolUse payload as Claude Code, so the shipped hook drops in unmodified. Cursor, Antigravity, and Copilot CLI genuinely cannot rewrite, so those guides deny and hand the model the supervised command to re-issue. Every adapter shells out to tman hook pretooluse rather than re-implementing the classifier.

/tuning/ — 15 per-tool guides. Vitest, Jest, pytest, go test, dotnet test, cargo, Playwright, RSpec, Gradle/Maven, ESLint, Ruff, Biome, golangci-lint, tsc, Vite/webpack. Every value is labelled a starting point derived from how the tool behaves — not a measurement of the reader's machine — and each page closes with the command that replaces it with a real one.

Verification

All three published scripts were extracted from the built HTML and executed. That caught two defects pre-publication: an unquoted ${verdict:-{\}} that broke the gate adapter on an empty verdict, and a test harness that ran inside a supervised tree and so exercised the no-double-supervision path instead of the plugin.

Measured on dist: 28 canonicals with 0 served-URL mismatches, 518 internal links with 0 broken, all JSON-LD parses, titles ≤50 chars, descriptions 128–151, no page under 756 words. Suite green at 232/232, and all 7 commits build (verified in a throwaway worktree).

Blocked, and worth acting on separately

https://standardbeagle.github.io/ returns 404 — the user-site repo does not exist — so no robots.txt is servable for any of the 11 Pages sites on that host. Creating standardbeagle/standardbeagle.github.io with a robots.txt and a landing page is the highest-leverage SEO change available across the account. Details in docs/seo-audit-2026-07-29.md §5.

Three tman findings

Not SEO issues, but they affect whether the documented setups work — §6 of the audit:

  1. The hook requires tool_name to be exactly "Bash" (probed). Accepting known shell-tool names would remove three wrappers.
  2. The rewrite omits permissionDecision: "allow", which Codex documents alongside updatedInput. Flagged in the guide with a verification recipe rather than claimed to work.
  3. Command resolution does not check the executable bit — tman run -- env exited 127 naming a non-executable file a shell's PATH search skips. Same class as the ~/.local/bin/test note in the project rules.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Xous3KdDmZhowvDgsSC6c8

claude and others added 8 commits July 29, 2026 10:05
The site shipped two pages carrying a description tag and nothing else: no
canonical, no Open Graph, no structured data. Shares rendered as bare text
links, and a crawler had no statement of which URL a page claims for itself.

URLs are built by one helper rather than by concatenating BASE_URL at each
call site, which is what previously produced inconsistent base-path handling.
The helper appends a trailing slash to directory URLs deliberately: Astro
emits docs/index.html, which the host serves at /tman/docs/ and reaches from
/tman/docs only via a redirect, so the slash-less form would declare a
canonical that differs from the URL a crawl actually resolves to.

The block vocabulary and renderer land here unused. They are the contract the
guide sections in the following commits are written against, and keeping them
separate from their first consumer makes clear that the vocabulary is
deliberately small — a guide needing an element outside it has usually drifted
from the others, and the drift is the thing worth noticing.

og.png is generated rather than sourced because there was no image to serve at
all; the card is the same 1200x630 for every page.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xous3KdDmZhowvDgsSC6c8
Shims catch commands that go through a shell lookup; an agent calling a Bash
tool with `npm test` walks straight past them. Which mechanism closes that gap
depends on a property of the agent, not of tman: whether its pre-tool hook can
replace a shell command, only gate it, or does not exist. The section is
organised around that axis because it is the first thing a reader needs and
the last thing the vendor docs state plainly.

Verified against vendor documentation rather than assumed, and the answers are
not uniform. Codex CLI turned out to use field-for-field the same PreToolUse
payload as Claude Code, so the shipped hook drops in unmodified. Gemini CLI and
opencode can rewrite but name their fields differently, so each carries a
wrapper. Cursor, Antigravity, and Copilot CLI genuinely cannot rewrite at all —
they return a permission decision — so those guides deny the unsupervised
command and hand the model the supervised string to re-issue.

Every adapter shells out to `tman hook pretooluse` instead of re-implementing
the classifier. Which commands count as test or build work, whether a project
is adopted, and whether the supervising binary can be safely named are
decisions tman already makes and tests; a second copy in bash or JavaScript is
a second thing to keep in sync and a second place for it to drift.

Guides are generated from one data module rather than hand-written per agent,
so a shared step cannot say two different things on two pages.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xous3KdDmZhowvDgsSC6c8
Attaching tman decides that a command is supervised; it does not decide what
the caps should be, and the right answer differs sharply per tool. A cold Rust
build is the longest legitimate silence tman will ever see. A Playwright suite
leaks browsers and binds a port. A dev server is designed never to exit, so a
wall-clock limit on it is guaranteed to fire and guaranteed to mean nothing.
Without a page saying so, the numbers get copied from whichever guide the
reader found first.

Every value is labelled a starting point derived from how the tool behaves,
not a measurement of the reader's machine, and each page closes with the one
command that replaces it with a real one. A table of numbers published without
that qualifier is what people paste into a config and then debug for an
afternoon — the same failure shape as a default that reports success without
doing work.

The recurring theme is layering: where a tool has its own limit that fails
informatively — `go test -timeout` printing a goroutine dump, golangci-lint
naming the analyser still running, the JVM's OutOfMemoryError — the guide sets
it below tman's, so the diagnosis comes from the tool and tman stays the
backstop for a process too wedged to produce one.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xous3KdDmZhowvDgsSC6c8
The guides existed but nothing pointed at them: no nav entry, no home page
section, no cross-link from the reference docs, and no sitemap. 518 internal
links now resolve, verified against the built file tree rather than assumed.

The sitemap is a 30-line endpoint rather than @astrojs/sitemap. That
integration earns its keep by discovering routes you did not enumerate; here
every route is already enumerated in the two data modules the endpoint
imports, so adding a dependency to re-derive a list it already holds is a net
loss — and a generated sitemap cannot drift from routes it is generated from.

Prose links go through the same href() helper as everything else, which
removes nine hardcoded /tman/ paths that would have broken silently the moment
the deploy base changed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xous3KdDmZhowvDgsSC6c8
Both registries rank partly on keywords, and neither package declared any — so
tman was effectively unlisted for every term except its own name, which is
also a Unix manual command and therefore a poor thing to be found by.

Neither package pointed at the documentation site or the issue tracker, so the
registry pages were dead ends for anyone who arrived there first.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xous3KdDmZhowvDgsSC6c8
The README is the highest-authority page this project has and was a wall of
prose with no navigation surface. `# tman` alone ranks for nothing: the query
returns the Unix manual command, so the heading now says what the thing is.

The agent table is the answer to the question most readers arrive with —
"does this work with the agent I use" — and previously required reading to the
Claude Code section to find a partial answer. Every row links to a guide with
the exact config for that agent.

Anchors in the contents block were verified to resolve; a table of contents
with a dead link is worse than none, because it is trusted.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xous3KdDmZhowvDgsSC6c8
Written so the next person can re-derive every claim rather than trust it:
each figure names what it was measured against, and the runnable snippets were
extracted from the built HTML and executed rather than eyeballed.

Records three findings that are not SEO issues but were surfaced by the work
and affect whether the documented setups function: the hook requires tool_name
to be exactly "Bash" (probed), the rewrite omits the permissionDecision field
Codex documents alongside updatedInput, and command resolution does not check
the executable bit — which turned `tman run -- env` into an exit 127 naming a
non-executable file a shell's PATH search skips.

The blocked item is deliberately stated as blocked with its measurement rather
than quietly omitted. The root domain 404s because the user-site repository
does not exist, so robots.txt is unservable for all eleven Pages sites on that
host, and no file in this repository can change that.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xous3KdDmZhowvDgsSC6c8
§5 described the missing user site as blocked from this repository, which was
true when written and is no longer. standardbeagle/standardbeagle.github.io now
exists, so the root serves a project index, the first robots.txt any of the
eleven Pages sites has ever had, a host-wide 404, and a sitemap index.

The original measurement is kept rather than replaced. It is the reason that
repository exists, and an audit that quietly rewrites a finding once it is
addressed leaves nothing to check the fix against.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xous3KdDmZhowvDgsSC6c8
@andylbrummer
andylbrummer merged commit b6f4921 into main Jul 31, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants