codetools / Deploy

codetools deploy

codetools deploys itself with its own deploy engine, the deploy package (SPEC-012). The deployed copy lives in /opt/codetools. Every other consumer runs that copy, never the checkout: Claude's MCP server, the codebase-map hook, orchestrata's realize output and the packages/contracts tests. The checkout is ~/workspace/orchestrata.codetools. This page describes the engine, the launcher that drives it, and the state measured on 2026-10-23. For how this deployment sits among the others on the host, see Deployment.

Sources:

Release layout on disk

Diagram projects-codetools-deploy-1

Item Measured 2026-10-23
current /opt/codetools/releases/58dc55ce7d9ba893/
VERSION commit a5c419f5720972267039adaf5efc932b19f835a4, repo .
release content the whole repository tree at the commit (src/, tests/, specs/, plans/, reports/, plugins/, uv.lock, ...), plus .venv/ and artifact.json
release venv pyvenv.cfg home = ~/.local/share/uv/python/cpython-3.14+freethreaded-linux-x86_64-gnu/bin; the interpreter resolves to uv's cpython-3.14.7+freethreaded
releases kept 52 directories
prefix size 9.3 GB on /dev/nvme0n1p2, the root NVMe
entry points in bin/ codetools, plus the console scripts of its dependencies (coverage, debugpy, dulwich, mcp, ruff, uvicorn, ...); no orchestrata entry point

The engine: codetools deploy install

install(repo, ref, prefix, python="python3.14t") "deploys the committed content of a git ref - never the working tree - into prefix/releases/<hash>, with a uv venv built and smoke-checked at that final release path before current ever points at it, then links prefix/.venv, prefix/VERSION and prefix/bin through current/...; an already-current sha is a no-op" (deploy/install.py).

The pipeline has four phases, each a stage with its own gate (deploy/pipeline.py):

Diagram projects-codetools-deploy-2

More rules from the docstrings:

Identity: codetools deploy verify-identity

"Health is not identity: a unit can report active mid-restart race; verify_identity proves the running units ARE the deployed release" (deploy/identity.py). It checks:

Every check reports its own name and reason. With --mcp-json, it also requires the registered codetools command to resolve inside the current release.

The launcher: ct-install (the Hermes model, 2026-10-22)

~/bin/ct-install <label> [ref] is the approved way to deploy codetools. It runs without a permission prompt through an allow rule in settings.local.json. On 2026-10-22, Mohamed said "make the installer like hermes". Since then, the launcher builds the release from its lockfile and promotes it with --no-verify, so no test-suite gate runs at deploy time. It then proves the result through the installed command, and rolls the promote back if either proof fails.

Diagram projects-codetools-deploy-3

What the launcher does, step by step:

  1. Refusals. It refuses when a codetools deploy install process is already running (RUL-032: one run per code state), when reports/ct8-install<label>.log already exists, or when the working tree is dirty. Its own logs and .claude/ are the only exceptions to the clean-tree rule.
  2. Environment. It unsets PYTHONPATH and PYTEST_ADDOPTS. Install 68 died because the scope inherited PYTHONPATH=/opt/orchestrata-tools/shim from the Claude shell, and the suite's import-shadow guard rejected it (commit 6979a4ad). It sets PYINFRA_VENV, CC=/usr/bin/gcc and CXX=/usr/bin/g++.
  3. Install. It runs uv run codetools deploy install --repo . --ref <sha> --prefix /opt/codetools --python python3.14t --no-verify inside a detached systemd-run --user --scope, logging to reports/ct8-install<label>.log.
  4. Proof. It runs /opt/codetools/bin/codetools deploy verify-identity --prefix /opt/codetools --expect-commit <sha>, then ct-smoke <sha>.
  5. Rollback. If either proof fails, it runs codetools deploy rollback --prefix /opt/codetools, prints ROLLED-BACK after a failed post-promote check, and exits 12.
  6. Markers. The log ends with WALL <seconds>s and INSTALL-EXIT <code>.

ct-smoke <commit> makes three live calls through the installed command:

It prints SMOKE-OK <commit>, or SMOKE-FAIL <check> and exits 1.

The suite-gated verify is still available: run codetools deploy install by hand, without --no-verify. The launcher's comment gives the reason for skipping it: the full verify takes minutes, and on install 72 even --affected-scope "spent 60 s selecting, then ran 8 shards for 3+ min".

Install record, 2026-10-22 and 2026-10-23

Install Ref Outcome
69 6979a4ad stopped by Mohamed ("stop install 69, run the fast install")
70, 71 6979a4ad INSTALL-EXIT 8: test collection refused the tmpfs /tmp basetemp; fixed by e1ffbc36
72 e1ffbc36 stopped by Mohamed ("make the installer like hermes") after 60 s of selection
73 e1ffbc36 INSTALL-EXIT 0, 26 s; release a37fbde65c97813a
74 b518f88a INSTALL-EXIT 0, 27 s; release 6ab0e3036ce3f300
75 a5c419f5 INSTALL-EXIT 0, 43 s; release 58dc55ce7d9ba893; IDENTITY OK a5c419f57209 ยท 0 unit(s) proven; SMOKE-OK

The audit log holds 52 promote lines. The last three promotes record verify=skipped. The last two verified baseline entries (2026-10-18) were full-scope and red, with 20 and 28 failed tests.

How the codetools deploy relates to orchestrata

Diagram projects-codetools-deploy-4

Open question: where codetools is hosted

The codetools repository has no git remote (git remote -v is empty on 2026-10-23). Everything that consumes it reaches it by local path:

Nothing is backed up off this machine, and no other machine can install codetools from a ref. The question is open and has not been ruled:

Option What changes For Against
A. A GitLab remote for orchestrata.codetools (the MSamy GitLab, like hermes and the orchestrata repo) push master and tags. The plugin marketplace becomes a git source, like the orchestrata plugin. ct-install and orchestrata pin a commit of the remote. codetools stays a separate, project-agnostic tool with its own release engine and ADR log (ADR-0020, ADR-0030, ADR-0038). Matches how hermes and the orchestrata plugin are deployed. Gives an off-machine copy. Two repos to keep in step. orchestrata's realize output still pins a codetools release by path until a published wheel or a git pin replaces it.
B. packages/codetools inside the orchestrata repo codetools becomes one more component of orchestrata's packages/ tree and ships with orchestrata's ship. One repo and one ship. The realize output and its codetools.rtm dependency live beside each other. codetools is used outside orchestrata: by the codemap hook in every project, and by the plugin, which its README describes as "for a work computer whose only agent is Claude Code". Its separate release engine, its /opt/codetools deploy and its 44 ADRs would have to fold into orchestrata's. The role of packages/ is itself still disputed.

Recommendation: A. It keeps codetools project-agnostic, matches the existing GitLab-sourced deployments, and closes the no-remote gap without moving code. This is a recommendation only. It becomes a decision when Mohamed rules on it, and then an ADR in docs/adr/.