What ax knows about your agent.
A tour of the data ax keeps on your laptop - the transcripts it indexes, the graph it builds, the stages it derives, the interventions it proposes, and the hooks it watches in real time.
One developer's local graph, as of June 2026. Turn count is role-filtered to user + assistant exchanges - the real signal, not raw provider events.
Everything your agent already wrote down.
Five coding harnesses, plus git and your installed skills. ax reads all of them.
A LaunchAgent (com.necmttn.ax-watch) tails your Claude and Codex transcript directories and runs ax ingest --since=1 in the background within seconds of a new turn. A weekly self-improve cron for deep-scan backfill is on the roadmap (wire-up pending). Nothing is uploaded, queued, or phoned home - every read stays on the same filesystem your agent already writes to.
A typed graph of who did what, where.
Transcripts become nodes and edges. Sessions own turns. Turns invoke tools. Tools touch files. Files end up in commits.
sessionone agent conversation, start → endcompactioncontext ran out and got summarizedturna single user-assistant exchangetool_callRead, Edit, Bash, MCP - one invocationskillan installed Claude/Agents skillfilea path the agent read or wrotecommitgit commit attributed to a sessioninvokedturn → skill (Skill tool call)editedturn → file (Edit/Write)touchedcommit → fileproducedsession → commitRaw events become findings.
Once the graph is built, ax runs a chain of small derive stages. Each one writes back into the same database, so every later query can ask the typed question instead of the raw one.
Proposals, lifecycle, and safety gates.
Patterns that recur in your graph turn into Intervention proposals. Each one moves through a tracked lifecycle, and any change to your harness ships with a written rollback contract.
~/.claude/agents/~/.ax/hooks/, fanned into both harnessesrecovery_pathwritten rollback steps. Required on every hook + automation.smoke_test_commandone shell command that proves the agent still works after.disable_commandkill switch you can paste from memory in a panic.failure_modefail_open (let through if hook errors) or fail_closed.settings.json, hooks, LaunchAgents, cron, or shell scripts directly. An accepted intervention emits a task brief at .ax/tasks/<id>.md with the safety contract on top. You - or your agent - apply it. ax improve lint reads the marker you left behind to reconcile the proposal back to accepted state.--- form: hook experiment: experiment:chk_skip_test_runner recovery_path: Remove the matching block from ~/.claude/settings.json, restart Claude Code, run smoke test. smoke_test_command: bun test src/ingest/turns.test.ts disable_command: jq 'del(.hooks.PreToolUse[] | select(.matcher=="Bash"))' \ ~/.claude/settings.json > /tmp/s.json && mv /tmp/s.json ~/.claude/settings.json failure_mode: fail_open --- # Hook: block `bun test` without the wrapper Add to ~/.claude/settings.json → hooks.PreToolUse: { "matcher": "Bash", "hooks": [{ "type": "command", "command": "echo 'ax:chk_skip_test_runner' && ax-hook check-test-runner" }] } The echo line is the marker ax improve lint looks for.
Write a hook once, run it in both.
Claude Code and Codex each have their own hook config and zero shared tooling. @ax/hooks-sdk lets you author a guardrail once in typed Effect TypeScript, backtest it against your own tool history, and install the same file into both harnesses.
import { defineHook, Verdict, GitEnv } from "@ax/hooks-sdk"; import { Effect } from "effect"; export default defineHook({ name: "enforce-worktree", events: ["PreToolUse"], matcher: { tools: ["Bash"] }, run: (event) => Effect.gen(function* () { const git = yield* GitEnv; // block branch switches on the primary tree if (switchesBranch(event) && (yield* git.isPrimaryTree(event.cwd))) return Verdict.block("use a worktree instead"); return Verdict.allow; }), });
ax hooks init scaffolds ~/.ax/hooks. ax hooks install <file> --providers=claude,codex fans the same hook into both provider configs, idempotently. Fire path is bun <file>.ts - about 70ms, no daemon.ax hooks backtest ./my-hook.ts --days=14 replays your real tool_call history through the hook in-process: would-block count and rate, per-project breakdown, sample blocked commands. First real run: 10,992 calls replayed, 0.8% would-block.run returns a verdict - allow, block with a reason, warn, or inject context. A hook that throws fails open: the tool call proceeds, and a buggy guard never wedges your agent.One CLI, every query.
Everything ax knows is reachable from ax. The dashboard, TUI, and MCP server are the same queries with different paint.
127.0.0.1:1738 with the same data the TUI sees.One process, one database, one laptop.
ax is a single binary that runs as a LaunchAgent, talks only to localhost, and stores everything in a SurrealDB instance you own.
ax, db main.ax install. Survives reboots.ax uninstall removes it. Commercial license available.“Your transcripts are already on your laptop. ax just reads them where they sit.”