diff --git a/CLAUDE.md b/CLAUDE.md index 3266555..4600595 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -13,7 +13,7 @@ This is a security-hardened Docker container that runs Claude Code with pre-inst The container is built on Node.js 22 (LTS) with the following layers: 1. **Base System** - Debian Trixie (glibc 2.41) with hardened security settings -2. **Toolchain (npm)** - All global npm CLIs installed via `npm ci` from `tools/package.json` + `tools/package-lock.json` (sha512-integrity, exact pinned versions, no `@latest`). Bins exposed via PATH (`/opt/toolchain/node_modules/.bin`). Includes Claude Code (2.1.245), OpenSpec (1.10.0), CodeGraph (1.5.0), caveman-shrink (0.1.0), the MCP servers, and dev tools (pnpm 11.22.0, typescript 6.0.3, ts-node 10.9.2, prettier 3.9.6, eslint 10.8.1) +2. **Toolchain (npm)** - All global npm CLIs installed via `npm ci` from `tools/package.json` + `tools/package-lock.json` (sha512-integrity, exact pinned versions, no `@latest`). Bins exposed via PATH (`/opt/toolchain/node_modules/.bin`). Includes Claude Code (2.1.246), OpenSpec (1.10.0), CodeGraph (1.5.0), caveman-shrink (0.1.0), the MCP servers, and dev tools (pnpm 11.22.0, typescript 6.0.3, ts-node 10.9.2, prettier 3.9.6, eslint 10.8.1) 3. **OpenSpec** - initialized into the build HOME (`/home/claude`) at build time, with telemetry disabled via `OPENSPEC_TELEMETRY=0`. The project itself is NOT initialized at build — it is overlaid by the runtime mount 4. **RTK** - Rust Token Killer; static musl binary in `/usr/local/bin` (version via `RTK_VERSION` build arg, sha256-verified); `rtk init -g --auto-patch` installs a Claude Code PreToolUse hook that rewrites Bash commands through `rtk` 5. **Caveman** - Output-compression skill for Claude Code, installed at build time via its plugin mechanism (`claude plugin install`), pinned to tag `v1.9.1` @@ -139,7 +139,7 @@ stdio MCP server invokes a **pre-installed, pinned binary** (`mcp-server-sequent `npx -y `. Nothing is fetched from the network to start a server. HTTP servers (`context7`, `cloudflare-docs`) have nothing to pre-install by construction. **Verified by build+run:** all **six** servers show `✓ Connected` under the **default** `MCP_TIMEOUT=10000` (10s) — the whole -`claude mcp list` health check takes ~6.9s wall-clock (median of 3 runs, 6.5-7.0s), including the +`claude mcp list` health check takes ~4.1s wall-clock (median of 3 runs, 4.0-4.2s), including the 280 MB `codebase-memory-mcp` binary (its size does not cost cold-start latency). There is no package download to race the timeout (the earlier `npx -y` form intermittently failed on a cold cache). When adding a @@ -361,7 +361,7 @@ prints a constant without loading the compiler; the build gate therefore also ru parser (`1/true/yes/on`). `autoMode.classifyAllShell`, `agentPushNotifEnabled` and `workflowSizeGuideline` are *accepted* — they appear in the 2.1.220 settings-key table, their values come from the binary's own enum/parser, and `claude doctor` on - **2.1.245** reports "No installation issues found." (the only note is the expected Remote Control + **2.1.246** reports "No installation issues found." (the only note is the expected Remote Control full-scope-token caveat) — but their runtime effect was **not** observed: the workflow-size system reminder is not injected in `-p`/headless runs, and `agentPushNotifEnabled` cannot do anything until Remote Control actually connects (which needs `claude auth login`). @@ -434,7 +434,7 @@ One extra entrypoint exists beside the autonomous `run_claude.sh`; it shares the - Source: https://github.com/colbymchenry/codegraph - **codebase-memory-mcp** - Tree-sitter code-intelligence engine (knowledge graph of functions, classes, call chains, HTTP routes) served over MCP (`codebase-memory-mcp` binary) - **Installed from the GitHub release, NOT from npm** (`ARG CBM_VERSION=v0.10.8`, per-arch `-portable` static asset, sha256-pinned in the Dockerfile). The npm package `codebase-memory-mcp` is a 12 kB shim: its `postinstall` downloads the binary from GitHub Releases outside npm's sha512 integrity, treats a missing `checksums.txt` as non-fatal (silently skipping verification), and `bin.js` re-downloads the binary on first run if absent — a runtime fetch, which this image forbids - - Single static binary, **280 MB** unpacked (vendored tree-sitter grammars + a vendored embedding model). **Measured on the built image:** it occupies a **279.6 MB** layer — third-largest, behind the `npm ci` toolchain layer (**1132.0 MB**, of which **743 MB** is `@anthropic-ai/claude-code` — it grew from 641 MB at 2.1.238 to 743 MB at 2.1.245) and the `apt-get install` system-deps layer (**426.2 MB**); the whole image is **2.11 GB** + - Single static binary, **280 MB** unpacked (vendored tree-sitter grammars + a vendored embedding model). **Measured on the built image:** it occupies a **279.6 MB** layer — third-largest, behind the `npm ci` toolchain layer (**856.9 MB**, of which **468 MB** is `@anthropic-ai/claude-code`) and the `apt-get install` system-deps layer (**426.2 MB**); the whole image is **1.84 GB**. The claude-code share swings a lot between patch releases — measured in this image: 641 MB at 2.1.238, 743 MB at 2.1.245, 468 MB at 2.1.246 — so re-measure after a bump instead of trusting the last number - The `-portable` Linux asset is the fully-static build; the plain `linux-*` asset needs glibc >= 2.38 (trixie has 2.41, so both would run — static is chosen to avoid the libc coupling) - Local SQLite graph under `$CBM_CACHE_DIR`, no API keys. Upstream states "zero network requests, no telemetry, no background version checks" — **not independently verified here**; note the binary does have a manual `update` subcommand and a `CBM_DOWNLOAD_URL` override, i.e. a download path exists (unlike codegraph, there is no env switch to forbid it; nothing invokes it in this image) - Registered as the `codebase-memory-mcp` MCP server, invoked with **no args** (the binary detects MCP stdio mode itself) diff --git a/README.md b/README.md index e9178b6..bc50de1 100644 --- a/README.md +++ b/README.md @@ -180,7 +180,7 @@ Base: `node:22-trixie-slim` (Node 22 LTS, Debian 13 / glibc 2.41). Multi-arch (a Toolchain pinned in `tools/package.json`, locked in `tools/package-lock.json` (`npm ci`, sha512 integrity, exact versions): -- `@anthropic-ai/claude-code` (2.1.245), `@fission-ai/openspec` (1.10.0) +- `@anthropic-ai/claude-code` (2.1.246), `@fission-ai/openspec` (1.10.0) - `@colbymchenry/codegraph` (1.5.0, MCP) wrapped by `caveman-shrink` (0.1.0) - MCP servers: `sequential-thinking`, `context7` (HTTP), `cloudflare-docs` (HTTP, no API key), `perplexity`, `codebase-memory-mcp` (GitHub-release binary, see below) diff --git a/tools/package-lock.json b/tools/package-lock.json index ae64c22..2b94070 100644 --- a/tools/package-lock.json +++ b/tools/package-lock.json @@ -8,7 +8,7 @@ "name": "claude-container-toolchain", "version": "1.0.0", "dependencies": { - "@anthropic-ai/claude-code": "2.1.245", + "@anthropic-ai/claude-code": "2.1.246", "@colbymchenry/codegraph": "1.5.0", "@fission-ai/openspec": "1.10.0", "@modelcontextprotocol/server-sequential-thinking": "2026.7.4", @@ -22,9 +22,9 @@ } }, "node_modules/@anthropic-ai/claude-code": { - "version": "2.1.245", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-code/-/claude-code-2.1.245.tgz", - "integrity": "sha512-+7baJddJXZukgd6AgC7xStHGsMTVHDPlRcAoqTSPx2NQ+QwKGtvCZQLgbnKuhjkwq9v9vKvYwIhLOwGiE77mVQ==", + "version": "2.1.246", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-code/-/claude-code-2.1.246.tgz", + "integrity": "sha512-E2PEKkal9D05dWnsc2fcPclJpEbJbnIE3D1vp33aPrsFbmdbqyNzEcc9/SeFIj53hvP/M5BuHygOFbeoBWEAOg==", "hasInstallScript": true, "license": "SEE LICENSE IN README.md", "bin": { @@ -34,20 +34,20 @@ "node": ">=22.0.0" }, "optionalDependencies": { - "@anthropic-ai/claude-code-darwin-arm64": "2.1.245", - "@anthropic-ai/claude-code-darwin-x64": "2.1.245", - "@anthropic-ai/claude-code-linux-arm64": "2.1.245", - "@anthropic-ai/claude-code-linux-arm64-musl": "2.1.245", - "@anthropic-ai/claude-code-linux-x64": "2.1.245", - "@anthropic-ai/claude-code-linux-x64-musl": "2.1.245", - "@anthropic-ai/claude-code-win32-arm64": "2.1.245", - "@anthropic-ai/claude-code-win32-x64": "2.1.245" + "@anthropic-ai/claude-code-darwin-arm64": "2.1.246", + "@anthropic-ai/claude-code-darwin-x64": "2.1.246", + "@anthropic-ai/claude-code-linux-arm64": "2.1.246", + "@anthropic-ai/claude-code-linux-arm64-musl": "2.1.246", + "@anthropic-ai/claude-code-linux-x64": "2.1.246", + "@anthropic-ai/claude-code-linux-x64-musl": "2.1.246", + "@anthropic-ai/claude-code-win32-arm64": "2.1.246", + "@anthropic-ai/claude-code-win32-x64": "2.1.246" } }, "node_modules/@anthropic-ai/claude-code-darwin-arm64": { - "version": "2.1.245", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-code-darwin-arm64/-/claude-code-darwin-arm64-2.1.245.tgz", - "integrity": "sha512-jjXl0zI4v3UXpkOlvDdPzJzz0rQ1QwvzDlKMSUIw5rGMReiOErq8o8DJyQJNgERejGG5Et9DiUFm+Bg6Tq9IBw==", + "version": "2.1.246", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-code-darwin-arm64/-/claude-code-darwin-arm64-2.1.246.tgz", + "integrity": "sha512-PWL+E62jHriRMD5VXQU7fgDl+g3ZbOl8VGo6yi6fhmo3aD9Fkl0yX/p4/vQDP/AurM0UqbM+N8FMi9ZTs4ZKdA==", "cpu": [ "arm64" ], @@ -58,9 +58,9 @@ ] }, "node_modules/@anthropic-ai/claude-code-darwin-x64": { - "version": "2.1.245", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-code-darwin-x64/-/claude-code-darwin-x64-2.1.245.tgz", - "integrity": "sha512-4WJJ+nHOuhV00/55I3LoVhfWDBU4KGgYdBe/lZjuufOSFhoREeG8T/HT2bYS/qTbFZUbkBau80M1TBMiBDbnbw==", + "version": "2.1.246", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-code-darwin-x64/-/claude-code-darwin-x64-2.1.246.tgz", + "integrity": "sha512-yF0wroatdrfgiL4CDVwgs0NFqDUpK7tPA4jq71r81NX4hzv4clehmiuzrslwzBSy7wCARyS66Qitq/viap+/Ng==", "cpu": [ "x64" ], @@ -71,9 +71,9 @@ ] }, "node_modules/@anthropic-ai/claude-code-linux-arm64": { - "version": "2.1.245", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-code-linux-arm64/-/claude-code-linux-arm64-2.1.245.tgz", - "integrity": "sha512-Qbn5HnZbYeW4GdifVkDGfcVKqj3/f3U9sfVd3LEaUZh08CcS8D/ptJ76zuBfQUGHJHfToAdNVfak86uJ84b1Dg==", + "version": "2.1.246", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-code-linux-arm64/-/claude-code-linux-arm64-2.1.246.tgz", + "integrity": "sha512-ls5pIYYTcLdSZcGGJ3vFFAU2ZrL6YRVg/F+pM87c+j95NYztEbKv/N9R35ROz83u+fEx8OljgDgV/5xBc9OFkw==", "cpu": [ "arm64" ], @@ -84,9 +84,9 @@ ] }, "node_modules/@anthropic-ai/claude-code-linux-arm64-musl": { - "version": "2.1.245", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-code-linux-arm64-musl/-/claude-code-linux-arm64-musl-2.1.245.tgz", - "integrity": "sha512-Fb6aeNv5NZf8XhFbBqb0HG5gT3Y+3FtrJetPoYbN36i74Jqt5Xsw85o/JyCPBULWBoNHDBm/ljYfn+/KwRerFg==", + "version": "2.1.246", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-code-linux-arm64-musl/-/claude-code-linux-arm64-musl-2.1.246.tgz", + "integrity": "sha512-96MZBGD1upw5tO2yxT44mqH5/8zUrlYUNKpnCk4Qted+AJIzR9s0oRsfqoGiq3/cRutlGi+Ze65KImlYbtULQA==", "cpu": [ "arm64" ], @@ -97,9 +97,9 @@ ] }, "node_modules/@anthropic-ai/claude-code-linux-x64": { - "version": "2.1.245", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-code-linux-x64/-/claude-code-linux-x64-2.1.245.tgz", - "integrity": "sha512-SRO5w2f9iHKZmREp389kPKxWAr6qEODxggdhhS7zF16OMwaUHjV5Yu7Oq8jSMD57gQiBjOfvFp/SJg3CdfHCtA==", + "version": "2.1.246", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-code-linux-x64/-/claude-code-linux-x64-2.1.246.tgz", + "integrity": "sha512-1BNvhwngvo8AAoWcQb+9TWgQ3Gdvwfriz4bBEbsI59rKqdm0//O0/6xuplWePUuFNWK7Z6nWbwT8pEZd/9jY9Q==", "cpu": [ "x64" ], @@ -110,9 +110,9 @@ ] }, "node_modules/@anthropic-ai/claude-code-linux-x64-musl": { - "version": "2.1.245", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-code-linux-x64-musl/-/claude-code-linux-x64-musl-2.1.245.tgz", - "integrity": "sha512-loThtx/opxdpmwk07VmjQL7ALhOKJJozdJs2T5SXVY7iAEZwX+nPK+Zz0CyvT3XRtxtimbEeNaQPmk43PUkFag==", + "version": "2.1.246", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-code-linux-x64-musl/-/claude-code-linux-x64-musl-2.1.246.tgz", + "integrity": "sha512-LK8Is52EhjgQlNBD2R+rMXj6mYsnOA66RfTMTNx3xq3/3UWIuCTVB3ssw5qpoQKV2Xt62PvdQ8c63tHf2T9eQQ==", "cpu": [ "x64" ], @@ -123,9 +123,9 @@ ] }, "node_modules/@anthropic-ai/claude-code-win32-arm64": { - "version": "2.1.245", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-code-win32-arm64/-/claude-code-win32-arm64-2.1.245.tgz", - "integrity": "sha512-gG/B3EU+nQZA9tjp43JE94p2VoCh0VotfaxyKYOf1eW0JmJRYzcpvV2Iih8/5i/FkL9TWghPAtRV8YcxwzTtow==", + "version": "2.1.246", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-code-win32-arm64/-/claude-code-win32-arm64-2.1.246.tgz", + "integrity": "sha512-jpMjgof1659UukdQVD8eZ2R3mnZdSnA8xjT4iwI797I5sA/Af0Pwrd5IVMGz6SrligXQKwJiBAXGs93qKyIBtA==", "cpu": [ "arm64" ], @@ -136,9 +136,9 @@ ] }, "node_modules/@anthropic-ai/claude-code-win32-x64": { - "version": "2.1.245", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-code-win32-x64/-/claude-code-win32-x64-2.1.245.tgz", - "integrity": "sha512-/SVV2dUpKIyuNylzsHo0pFqKAn6HGcqNB/fEpluahvUIaYsgluJsBs8m3uIgYLfU4nFnPbemrYj0ekoG626SgA==", + "version": "2.1.246", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-code-win32-x64/-/claude-code-win32-x64-2.1.246.tgz", + "integrity": "sha512-5ELyn5TdYYO6qYVE+gWfE+JmkdprJ1FZOSbX3B3hk7GvWotGEvvcSd+z+U26S1+oYIvouNWQ6PtBnJHWF1lrzQ==", "cpu": [ "x64" ], diff --git a/tools/package.json b/tools/package.json index b477e84..b541af6 100644 --- a/tools/package.json +++ b/tools/package.json @@ -4,7 +4,7 @@ "private": true, "description": "Pinned, lockfile-controlled global CLI toolchain for the claude-standalone container. Installed via `npm ci` for bit-for-bit reproducible npm tarballs (integrity-verified). Do not add `^`/`~` ranges here — exact versions only; regenerate package-lock.json inside node:22 after any change.", "dependencies": { - "@anthropic-ai/claude-code": "2.1.245", + "@anthropic-ai/claude-code": "2.1.246", "@fission-ai/openspec": "1.10.0", "@colbymchenry/codegraph": "1.5.0", "caveman-shrink": "0.1.0",