docs: AI-agent setup guides, per-tool tuning guides, and full SEO pass - #1
Merged
Conversation
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
temporarily deployed
to
github-pages
July 31, 2026 14:28 — with
GitHub Actions
Inactive
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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:Codex CLI turned out to use field-for-field the same
PreToolUsepayload 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 totman hook pretooluserather 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 norobots.txtis servable for any of the 11 Pages sites on that host. Creatingstandardbeagle/standardbeagle.github.iowith arobots.txtand a landing page is the highest-leverage SEO change available across the account. Details indocs/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:
tool_nameto be exactly"Bash"(probed). Accepting known shell-tool names would remove three wrappers.permissionDecision: "allow", which Codex documents alongsideupdatedInput. Flagged in the guide with a verification recipe rather than claimed to work.tman run -- envexited 127 naming a non-executable file a shell's PATH search skips. Same class as the~/.local/bin/testnote in the project rules.🤖 Generated with Claude Code
https://claude.ai/code/session_01Xous3KdDmZhowvDgsSC6c8