Repository navigation
First-day fixes: plainer messages, a Claude Code quickstart, and an uninstall that says what it keeps - #628
Open
LoopGlitch26 wants to merge 13 commits into
Open
LoopGlitch26 wants to merge 13 commits into
LoopGlitch26 wants to merge 13 commits into
Conversation
`tracekit --help` printed every subcommand as one flat list in the order they were registered, and `tracekit` alone was an argparse error. - `tracekit help` and a bare `tracekit` print an overview: each command under what a person runs it for, one entry each from its own help text (up to where its usage starts), experimental ones marked as their help marks them, then the features that are not commands (witnesses and anchoring, Tracekit Box, the SDKs and integrations) with their pages. - `tracekit help NAME` is `tracekit NAME --help`; an unknown name lists the commands and exits 2. - The parser is built in `_parser()` so the overview and the tests read the registered commands; tests/test_cli.py checks every command is in exactly one group. - docs/quickstart-v2.md names `tracekit help`.
…ninstall that says what it keeps A new-user walkthrough of main in a clean container found these; each is fixed at its cause. - The dev-mode line says how to guard (system mode, Tracekit Box), with links. - doctor: no Claude Code and no witness are info in dev, not warnings; a healthy dev run ends with "dev setup OK"; the system-mode fix names the wiki and a Python init accepts. - init --dev --v2 ends with a next step, and points to lines that exist today. - tracekit last with no runs says instrument() records only the frameworks it lists. - Framework quickstarts lead with their no-key --scripted route and name what the live example needs (langchain-openai and OPENAI_API_KEY, ANTHROPIC_API_KEY). - docs/quickstarts/claude-code.md: init, a new session, a hold, answering with !, retry, last, view, uninstall. - tracekit pending lists the v2 signer's held calls when there is no v1 signer. - uninstall lists what it keeps with the commands that delete it, deletes a settings file init made that is now empty, and its help no longer says "ledger". - approvals show gives the cause the hook gives; an unclosed quote has its own cause; the Claude Code `!` hint is for Claude Code runs only; list and show give expiry as UTC time and minutes left. - view: --approval's help says it starts the viewer; plain start lines; a clickable 127.0.0.1 link for an any-address bind; --host and --port help. - verify: an empty run says "no tool calls recorded". - status prints a summary; --json keeps the JSON. - The hook command for a checkout or --user install is clear text, not base64. - quickstart-v2: a short step 2, the server pattern, the wait table and socket details under Deeper, a Remove it section, and the scripted snippet says when the wait ran out. - Help text for up, down, policy, uninstall, observe; ingest, otel and daemon say experimental. - Nits: demo --server's approval line, report's side_effect label, last says when it waits.
… doctor, what uninstall names, status - Windows: the hook command passed the tree, branch and event as arguments quoted for the C runtime, which Git Bash, PowerShell and cmd.exe read as shell text (backslashes lost, a quote breaking the line, a branch `fix&calc` or `f$(id)` running a command). They are Python literals inside the double-quoted code now, every character those shells read escaped (install._literal); doctor reads the tree back from them. POSIX keeps quoted arguments. - doctor took a `"` off every word of a POSIX hook command; only Windows' split keeps them. - uninstall named the client config's signer_home in any mode: on a v1 system mode host, /var/lib/tracekit. Only a dev mode's home, never under a system config, as uninstall() stops it. - uninstall named a shared per-user runtime dir with no endpoint.json as this HOME's. It names only dirs provably this HOME's and says when the shared one can't be told. - status crashed on a settings file it can't read and printed "(0 events)" for one without Tracekit's hooks; it says which file it can't read and how to add hooks. - approvals list and show use #627's _expires_left, so the two branches agree.
…elp's own description From #619's review: - The overview cut each help at the first `; ` or `: \``, which dropped audit's "read-only, not a signed record". It now cuts only where usage starts: a `; ` or `: ` before a backquote, `--` or a URL. - daemon, observe, ingest, otel and proxy (the v1 path) move to a "Legacy (v1)" group, so they don't read as current server tools. - `tracekit help causeway|sql|proofpack` gives the "moved to a separate package" answer `tracekit causeway` gives. - `tracekit help help` has a description and its argument a help line.
- Root-only SystemV2Install expected purge to leave {} in the project's
settings; uninstall now deletes a settings file init made when nothing
else is in it, as the ClaudeConfigDir tests already expect.
- own_runtime_dirs' test set HOME only; Windows' ~ is USERPROFILE, and its
temp dir is inside the profile, so the shared dir read as this HOME's.
- Reinit wrote /opt's venv Python with / separators; it is install.OPT_PYTHON,
which doctor matches with os.sep.
…ines - doctor: the dev signer uses the public witness by default since #625; its D-WITNESS-CONFIGURED info is for none until a release names it, or after --no-witness (docs/doctor.md, the DEV_INFO comment, test comments). - uninstall on Windows: the runtime dir inside the data dir isn't named again in Remove-Item, and the pip line starts with & so PowerShell runs a quoted Python path; a test checks both printed commands. - a test for demo --server's self-approval line; view's label comment says what it means.
Conflicts in tracekit/view.py and tests/test_view.py: the viewer keeps this branch's --approval help and start lines, and takes #609's --transcripts option and tips line after them; both tests stay.
…s line - doctor: before the dev signer's first start (no store yet, as right after init) the content key, record key and key hygiene rows are info and say they're checked after that start, so doctor straight after init --dev --v2 ends with dev setup OK, as the Claude Code quickstart says. - status: names the Claude Code plugin's hooks, and a --no-hooks choice (dev or system mode), instead of telling both that init adds hooks.
test_content_vault's doctor test turned the vault on and expected warn with no key yet, in a data dir no signer had used: dev now reports that as info until the first start (test_doctor_v2 covers it). The test gives it the store a started signer leaves, so it checks the warning it was written for.
This branch has not been deployed
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.
A new-user walkthrough of main (8967779) in a clean container hit the problems below. Each one is fixed where it starts, and each change to code has a test that fails without it. F10 (a policy rule) is handled elsewhere.
Based on #619 (
tracekit help, branchagent/tracekit-help): this branch sits on top of it, so the diff here is only these fixes. Merge #619 first.Outputs are from a throwaway HOME on macOS (
env HOME=… <venv>/bin/python -m tracekit …), with paths shortened to~.F1: "Box" is unexplained (init, up, status, doctor)
Before:
After:
F2:
doctorwarns on a healthy dev setupclaudeon PATH, no~/.claude) isinfo, not WARN. The witness check isinfoin dev. Only D-PROCESS-BOUNDARY, which is what dev mode is, stays a WARN.--jsongains the statusinfo(docs/doctor.md says so).docs/deploy.md. It names doctor's own Python when only root can change it (init refuses any other), and/usr/bin/python3otherwise (a user's venv, or/opt/tracekit's venv, which init can't run from on 3.9 or 3.10)._settingdoes.Before:
After:
With no Claude Code:
info no Claude Code here (no claude on PATH, no ~/.claude), so no hooks: runs that SDK clients send (tracekit.instrument()) are still recorded (D-HOOKS-PRESENT).F3:
init --dev --v2gives no next step, and its link has no targetThe anchor
#when-tracekit-stops-a-callisn't on the published wiki yet (it arrives with the next release). The line now points to the file the plugin ships those lines in, which is on GitHub today.Before:
After:
With no
claudeon PATH the line startsnext: install Claude Code (noclaudeon PATH yet), then start a session.F4: the framework quickstarts
LangChain's example called
create_agent("openai:gpt-5", ...)withoutlangchain-openai(ImportError: Initializing ChatOpenAI requires the langchain-openai package) or a word aboutOPENAI_API_KEY. Each quickstart (LangChain, OpenAI Agents, Claude Agent SDK, MCP) now:pip install .plus the framework, thenpython examples/v2/<x>/agent.py --scripted. All four ran here with noOPENAI_API_KEYorANTHROPIC_API_KEYset and printedIntegrity: VERIFIED.;langchain-openaiandOPENAI_API_KEY(or another provider's package and key); OpenAI AgentsOPENAI_API_KEY; Claude Agent SDKANTHROPIC_API_KEY(it runs the Claude Code it bundles); MCP needs no key, andmy-mcp-serveris your server's command.F5:
tracekit lastfound no runs afterinstrument()Before:
After:
The First-run errors row in quickstart-v2 says the same.
F7: no Claude Code setup page
New
docs/quickstarts/claude-code.md: install and init, start a new session, what a deny and a hold look like (copied from real hook output), answering with!, the retry,tracekit last/last --open/view --dev, and uninstall. It only states what the code does. Linked fromdocs/integrations.mdand the quickstart index. The README link is drafted in the report, not edited here.F8:
tracekit pendingwith v2 holds and no v1 signerBefore:
After (no v1 signer configured, and none at the default socket):
F9: uninstall is silent about what it keeps
Before:
(and
settings.json, which init had made, stayed behind holding{})After:
_tracekit_created, like the existing_tracekit_thinking). Uninstall deletes that file only when nothing else is left in it. A file you had before stays./tmp/tk-501, which another HOME's live signer was using.autospawn.own_runtime_dirs()leaves out a dir whoseendpoint.jsonnames another data dir.uv tool uninstall/pipx uninstall. Windows getsRemove-Item -Recurse -Force.remove hooks (the ledger is kept)→remove Tracekit's hooks (your signed runs and keys stay: it says where, and how to delete them too).F11:
approvals show, the parser's cause, the!hintapprovals showused TK-SHELL-PARSE's general text where the hook used the decision's cause. It now runs the same engine on the signer's copy of the arguments to get that cause. An unclosed',"or$'now has its own cause,quote(cause texts incompile.pyand the error class in the parser; the verdict is unchanged, stillask). The Claude Code!hint shows only for runs a Claude Code session on this machine owns (the v2 hook's session state names the run).Before (hook, then
approvals show):After:
For an SDK agent's run the
answerline has no!part.F12, F13: the viewer
--approvalstarts the viewer and prints a link that opens the held call, and that is what people want fromapprovals show'srecordline (a printed link to a viewer that isn't running opens nothing). So the help now says what it does.Before:
After:
(the second run was
--host 0.0.0.0 --insecure-http: the link is 127.0.0.1; before, the line printed the--hostvalue as given, sohttp://0.0.0.0:…)F14: an empty run
Before:
VERIFIED: 5 signed records, none changed, removed or added after signing.After:
VERIFIED: no tool calls recorded; 5 signed records, none changed, removed or added after signing.Exit codes and
--jsonare unchanged (tested).F15:
tracekit statusBefore: a page of JSON (45 lines here). After:
--jsonprints the JSON as before. The one test that parsed it anddocs/portability.mdnow use--json. Nothing else in the repo reads it.F16: the scripted snippet's approval wait
Before:
if run.call("approval_wait", ...)["state"] == "approved" and ...:with nothing on timeout. After: the snippet keeps the state and printscall-3 not run: no answer within 5 minuteswhen the wait ends with the call stillrequested.F17: the hook command was base64
Before (a checkout or
pip install --user):After:
The tree, the branch and the event are quoted arguments after the code, so the code holds no path. Behaviour is the same: the branch-switch message (the existing
WorkingTreetest passes unchanged, including the no-git case), fail-closed wrapping, and the event name. A new test runs the hook from a path with a space, both quotes and$HOMEin it. doctor's D-VERSIONS probe reads the tree from the new form and still reads the old base64 form in hooks already installed.docs/quickstart-v2.mdandplugin/README.mddescribe the command.F18: quickstart-v2 step 2
Step 2 is now the one line, what
instrument()records (and what to do when it finds nothing), how a held call looks from an SDK agent, and links to Claude Code and TypeScript. The server pattern, the 17-row wait table and the socket internals moved under Deeper: drive the signer yourself (the headings and their anchors are unchanged). Also new: a Remove it section, the Claude Code quickstart in the per-framework list, andtracekit statusmentioned in step 3.Help text (
tracekit help, #619)up:start the local signer (dev mode), or find the running one;down:stop the local signer (dev mode);policy:check a v2 policy and try it on past runs;status:what is set up here: hooks, signer, policy, capture sources;ingest,otel,daemonsay(experimental);observe:the old name oftracekit view --ledger: the v1 ledger or a v1 bundle in a read-only web page;uninstallas above.tests/test_cli.pypins none of these.Nits
demo --server:Bash 'ls': allow(trailing space) →Bash 'ls': allow.approved apr-… (self-approved: True)→approved apr-…, by the run's own user: a self-approval, so the run's assurance stays dev.approvals listandapprovals showprint the signer's ISO time plus the minutes left,2026-11-05T15:20:40.046351Z (in 59 min)(main's_expires_leftsince CLI: print remaining time on approvals list as show does #627, which this branch now uses). The hook's held line keeps15:20 UTCalone (claude_code.expires): harnesses such as Cursor cut that message at 500 characters, and the extra words pushed the remedy past the cut (an existing test caught it), and a transcript keeps the line after the minutes have passed. The viewer's approval page keeps its local-time display; v1pendingkeeps its seconds.report:TK-F004 1 side_effect→TK-F004 1 side effect(a rule's label is shown with spaces, in the viewer too).lastsaystracekit last: run r1 (a) just closed; waiting up to 15 s while the signer finalises itonce, instead of waiting in silence.<run id>.trust.jsonwording: drafted in the report, not edited here.Checks
ClearText(test_hook_invocation),FirstDayandtest_the_reinit_fix_names_the_wiki_and_a_python_init_accepts(test_doctor_v2),TestFirstDayCli(test_signer_approvals: show cause,!hint, pending),test_uninstall_deletes_the_settings_file_init_made_and_says_what_it_keeps(test_hook_v2),test_uninstall_names_only_this_homes_runtime_dirs(test_signer_dev),test_status_prints_a_summary_and_json_only_with_json(test_dev_mode_line),test_the_start_lines_are_plain_and_the_link_is_one_a_browser_opens,test_last_says_it_waits_for_a_run_that_just_closedand label/no-runs assertions (test_view), the empty-run summary (test_verify_short), thequotecause (test_policy2).PYTHONPATH=$PWD TRACEKIT_PYTHON=<venv python> make test-ts lint build test): test-ts 150 passed, 0 failed; lint clean; build OK; 4452 passed, 394 skipped, 10 xfailed.scripts/wiki.pybuilds the wiki (128 pages) with every link and anchor resolved.HH:MM UTCalone.Remove-Itemline and the hook command's Windows quoting are covered by reading the code and the existingIsolatedCommandtest only), Linux (CI runs it).