Skip to content

docs: v0.62 sharing levers, a what-Paddock-touches page, and a full-site audit - #703

Merged
edspencer merged 5 commits into
mainfrom
docs/062-claude-sharing-levers
Aug 6, 2026
Merged

docs: v0.62 sharing levers, a what-Paddock-touches page, and a full-site audit#703
edspencer merged 5 commits into
mainfrom
docs/062-claude-sharing-levers

Conversation

@edspencer

Copy link
Copy Markdown
Owner

Docs for v0.62.0 — the release that split Paddock's single Claude-home lever into five independent keys (#691) — plus an audit of the whole site against packages/server/src at a809cd5.

Verified against the tree at a809cd5 (v0.62.0) with @herdctl/core 5.29.1 installed. #702 was open and unmerged while I worked; I documented what is true on main today, which means the --mcp-config argv exposure warning #702 adds is not described here. #700 (plugin-provided MCP servers) is not documented at all — it does not work.


The plan

Audited: all 48 doc pages under website/src/content/docs/**, plus README.md, packages/server/NPM-README.md, the CLI USAGE string, and astro.config.mjs. Three parallel audits (concepts+architecture / configuration+reference / using+guides+READMEs), each establishing ground truth from source rather than from the changelog.

Two judgement calls the brief asked me to make explicitly:

  1. Do the five levers deserve their own page? Partly. Not a reference page — configuration/config-file.md already covers all five keys in real depth, and it is genuinely good; a second reference page would duplicate and drift. But the question the incidents were about had no home, so I added guides/what-paddock-touches.md: a file-by-file table of what is read, written and never opened by default, the one write Paddock ever makes outside its data dir, what --here does and does not decide, and two commands to verify the claim rather than trust it. Filed under Security in the sidebar, since that group is already "what a turn can do".
  2. whats-new should say what you must do. It leads with instructions: host as an action, not with the mechanism — see correction 2 below for why that matters more than it looks.

Changed, and why:

Page Why
whats-new.mdx No 0.62 entry existed. Added one, plus the Reading older entries aside the house style assumes exists but which was absent, and a supersession note on 0.61.1's --isolated-claude-home advice
guides/what-paddock-touches.md New. The guarantee page
cli/args.ts USAGE Listed four levers; mcpServers was missing. Changeset included
README.md, NPM-README.md Docker snippets that cannot boot; claude: block absent from README config; NPM-README listed 4 of 5 levers
configuration/config-file.md Two claims the code contradicts (below) + a stale keeperDriveMode key in the example
configuration/environment.md Undocumented env var, and a claim that it doesn't exist
configuration/instance-settings.md The five lever rows and the deliberate mcpServers: omission were undocumented
architecture/overview.md, herdctl-and-paddock.mdx, concepts/{chats,projects,agents}.md, guides/{kubernetes,dev-box-flavor}.md, contributing/testing.md ~/.claude/projects/<enc> as the transcript home; dangling citations
components/diagram/StorageDiagram.astro The figure showed the wrong path — fixing the prose alone would leave it on screen
concepts/hooks.md, reference/hooks.md "hooks" now means two unrelated things, one word apart in config
guides/agent-capabilities.md, guides/securing.md, guides/untrusted-content.md The levers are a capability/isolation surface these pages didn't mention
reference/self-mcp.md paddock/paddock_manage are reserved names
using/working-in-chats.md Delete-releases-under-host was documented nowhere user-facing
getting-started.md Two flags missing; --verbose is worth one run (correction 2)

Deliberately left:


What the docs claimed and the code contradicts

This is the part worth reviewing. All verified from source, not inferred.

  1. A released chat is still listed. config-file.md said that under transcripts: host, deleting "releases it — the chat leaves your list". It does not leave the list. deleteSession calls unadoptSession, which drops the adoption record, and the engine rediscovers the transcript structurally on the next listing. There is a passing test in the shipped code asserting exactly this (delete-chat-host-transcripts.test.ts, "does NOT yet remove it from the list (the tombstone is still owed)"), tracked as A chat deleted in a Claude home Paddock doesn't own is released but still listed #693. The page written by the release PR claimed the intent was honoured.

  2. The instructions: own startup notice is invisible on the documented install path. config-file.md said Paddock "names the key at startup … so the fix is one line and you are told where". The notice is level: "info" (claude-home.ts), and cli/paddock.ts sets LOG_LEVEL=warn unless --verbose. So on npx @edspencer/paddock — the primary documented path — it is filtered out. A server run (LOG_LEVEL default info) does show it. This is why the What's New entry carries the warning instead of deferring to the notice.

  3. README.md and NPM-README.md's docker run snippets cannot start. The image sets HOST=0.0.0.0 (Dockerfile:65), auth defaults to none (config.ts:827), nothing sets PADDOCK_DANGEROUSLY_ALLOW_OPEN, and evaluateBindSafety returns refuse. The container exits. getting-started.md and guides/deploying.md both have the flag — the READMEs were the outlier. NPM-README additionally published -p 4000:4000 on a routable address.

  4. overview.md's QueuedMessageStore note is inverted. It warned the key separator is "a space, not the NUL byte the others use — a benign inconsistency". It is a NUL, identical to the other four sidecars. The callout warned contributors about an inconsistency that doesn't exist; deleted.

  5. environment.md said the Management API has no PADDOCK_* variables of its own. PADDOCK_MANAGEMENT_TRUSTED_PROXIES exists (management-config.ts:255, env wins over file) and appeared in no table on the every-env-var page. Two other pages already documented it correctly.

  6. Three dangling code citations. ensureKeeperModel (0 hits — it's ensureAgentModel), KEEPER_DEFAULT_MODEL (0 hits — it's DEFAULT_MODEL), and cfg.keeperDriveMode (it's cfg.driveMode). overview.md contradicted its own sequence diagram, which already said ensureAgentModel. A config example also used the pre-0.50 keeperDriveMode: key, which the loader silently ignores.

  7. agent-capabilities.md said no Paddock setting changes the toolset. Two v0.62 keys widen the allow-list by mcp__<name>__* — they have to, or both would be no-ops with no error.

  8. contributing/testing.md described a deleted guard (the Paddock should own its Claude home; ~/.claude should be read-only #620 refuse-to-migrate-out-of-an-unowned-home branch, removed by Design: independent levers for what Paddock shares with the host's Claude Code (transcripts / credentials / MCP / instructions / hooks) #691) and said the fake claude resolves ~/.claude, when it resolves CLAUDE_CONFIG_DIR first.

One correction to the brief itself

The brief says the instructions: own default "will silently drop their curated CLAUDE.md". That is true only on the CLI paths — the sweeper, triggers, and driveMode: batch chats. On a default SDK chat turn those files were already inert before v0.62: herdctl's sdk-adapter.js sets settingSources = ["project"] for any agent with a working_directory, which is every Paddock keeper, so the Claude home's CLAUDE.md / agents / commands / settings.json are never loaded there. I verified this in the installed bundle (sdk-adapter.js:139-150, and cli-runtime.js:152 passing --setting-sources only when an agent declares it) rather than taking #697's word for it. The What's New entry states both halves; writing the simpler version would have been the confident-and-wrong outcome this effort keeps producing.

Caveat I can't close: the box has @herdctl/core@5.29.1 installed against a declared ^5.31.0. That behaviour is verified for 5.29.1; #697 reached the same conclusion by live probe against the SDK.


Verification

  • cd website && npm install && npm run build — passes, exit 0, 50 page(s) built (baseline before this PR: 49; +1 is the new page). npm install works fine under the box's NODE_ENV=production, as website/CLAUDE.md says.
  • Internal links: 403 checked, 0 broken. Starlight does not fail a build on a bad link, so I resolved every internal link in every page against the built routes in dist/, including anchors — each fragment checked against the id= attributes actually emitted by the target page.
  • Sidebar: 0 orphans, 0 dangling. Every page file appears in astro.config.mjs; every sidebar entry resolves to a real page.
  • The new page is in the sidebar (Security group) — it would be invisible otherwise.
  • A YAML frontmatter error and three duplicate-id warnings both surfaced and are resolved. The first was mine (an unquoted claude: inside a description). The second turned out to be a stale incremental content cache — a clean rm -rf .astro dist build is warning-free. Worth knowing, because the warning text implies a content problem.
  • cli-paddock.test.ts + config.test.ts: 131 passed. These initially showed 3 failures caused by this box leaking 20 PADDOCK_* vars into the suite; green with the list derived from env and unset. Unrelated to this change.
  • Leak scan for host/LAN identifiers: clean (the one 192.168. hit is pre-existing prose about proxies).

I have not run E2E locally: npm run build at the repo root fails on the pre-existing reapChatSession typecheck error from the @herdctl/core version skew above, which is present on main untouched. CI installs fresh — status in the checks below.

🤖 Generated with Claude Code

HomeLab Agent and others added 5 commits August 5, 2026 21:57
…uches

The release that split one Claude-home lever into five independent keys had
no What's New entry, and no page answering the question every incident behind
it was really about: what does this thing actually read and write on my
machine?

The entry leads with the action rather than the mechanism. `instructions`
defaults to `own`, so a curated ~/.claude/CLAUDE.md stops reaching agents on
the CLI paths — and the startup notice that says so is written at `info`,
which the npx launcher's quiet default filters out. Nobody is going to be
told, so the docs have to be what tells them.

Adds the `Reading older entries` aside the house style assumes exists, and
marks 0.61.1's `--isolated-claude-home` advice as superseded rather than
rewriting the entry.

Co-Authored-By: Claude <noreply@anthropic.com>
"Sharing your Claude Code state" listed transcripts, credentials,
instructions and hooks, and omitted claude.mcpServers — which shipped
alongside them. Adds it, plus a line for the sibling top-level mcpServers:
block, which is the answer for an instance whose machine has no servers to
borrow. Help text only.

Co-Authored-By: Claude <noreply@anthropic.com>
An audit of all 48 pages against packages/server/src. The corrections, in
rough order of blast radius:

- The transcript home is <dataDir>/claude-home/projects/<enc>, not
  ~/.claude/projects/<enc>. Eight pages said the latter, including two
  giving operators a volume path to persist, and the storage figure.
- A released chat under transcripts: host is still LISTED. config-file.md
  said it leaves the list; a passing test in the shipped code asserts the
  opposite (#693).
- config-file.md said Paddock names the instructions key at startup so
  "you are told where". That notice is level info and the npx launcher
  sets LOG_LEVEL=warn, so on the common path it is filtered out.
- README and NPM-README's docker run snippets omit
  PADDOCK_DANGEROUSLY_ALLOW_OPEN=1 and cannot start: the image binds
  0.0.0.0, auth defaults to none, and the bind guard refuses. NPM-README
  also published on a routable address.
- Dangling citations: ensureKeeperModel and KEEPER_DEFAULT_MODEL do not
  exist (ensureAgentModel / DEFAULT_MODEL); cfg.keeperDriveMode is
  cfg.driveMode; a config example used the pre-0.50 keeperDriveMode key.
- overview.md warned that QueuedMessageStore's key separator is a space
  "unlike the others". It is NUL, like the others. Callout deleted.
- environment.md claimed the Management API has no PADDOCK_* variables of
  its own. PADDOCK_MANAGEMENT_TRUSTED_PROXIES exists and was undocumented.
- "hooks" now means two unrelated things; concepts/ and reference/ hooks
  pages now disambiguate from claude.hooks.
- agent-capabilities said no config changes the toolset. Two keys widen it.
- instance-settings omitted the five lever rows, and the deliberate
  absence of a row for the secret-bearing mcpServers: block.
- self-mcp did not say paddock/paddock_manage are reserved names.

Co-Authored-By: Claude <noreply@anthropic.com>
…ntee page

#702 merged while this branch was open. env:VAR_NAME keeps a declared MCP
server's credential out of the git-tracked config file; under driveMode: batch
it does not keep it out of `ps`, because the engine serialises the whole
definition into a --mcp-config argv element and /proc/<pid>/cmdline is
world-readable. The default driveMode: session passes the record in-process,
where the server gets its env owner-readable — what Claude Code itself does.

#702 documented this on config-file.md. Three other places I had written the
unqualified "tokens stay out of the file" claim now carry the limit too: the
0.62 What's New entry, the new what-Paddock-touches page (which gains a short
section on credentials you hand Paddock), and the CLI --help.

Documented as a property of driveMode: batch, not as a Paddock bug — the fix is
upstream, and #702 ships a characterisation test that will fail if herdctl
learns to pass --mcp-config as a file path.

Co-Authored-By: Claude <noreply@anthropic.com>
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Aug 6, 2026

Copy link
Copy Markdown

Deploying paddock with  Cloudflare Pages  Cloudflare Pages

Latest commit: a6cb606
Status: ✅  Deploy successful!
Preview URL: https://16c0181a.paddock-7u2.pages.dev
Branch Preview URL: https://docs-062-claude-sharing-leve.paddock-7u2.pages.dev

View logs

@edspencer
edspencer merged commit a789260 into main Aug 6, 2026
5 checks passed
@edspencer
edspencer deleted the docs/062-claude-sharing-levers branch August 6, 2026 02:18
@github-actions github-actions Bot mentioned this pull request Aug 6, 2026
edspencer added a commit that referenced this pull request Aug 6, 2026
…les (#707)

The `claude.instructions: own` boot notice names which of the user's
~/.claude instruction files are not being loaded and which key turns them
back on. It was written at `info`, and `cli/paddock.ts` sets
LOG_LEVEL=warn unless `--verbose` — so on `npx @edspencer/paddock`, the
documented install path, the one population the notice exists for never
saw it.

Raising it to `warn` is safe because the notice is already conditional on
`present.length > 0`: it fires only when the user actually has files that
are being withheld. An empty ~/.claude, or `instructions: host`, stays
silent.

Docs: #703 hedged around this in prose (config-file.md's "you will
probably not be told" caution, and getting-started.md's `--verbose`
advice). Those hedges are now stale for this notice only — the other
`info`-level boot notices still need `--verbose`.

Closes #706

Co-authored-by: HomeLab Agent <homelab-infra@valfenda.net>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant