How do I deploy the settings?
Table of Contents
Two harnesses run agents in this checkout, and each has its own generated
settings. The authoritative source for .claude/settings.json is
Claude Code Settings (doc/llm/claude_code_settings.org); for the
DSH sandbox rules it is DSH Settings (doc/llm/dsh_settings.org).
Never edit the generated files directly. For CMake setup and preset names see
CMake setup.
1. Question
How do I regenerate the agent settings from their literate org sources?
2. Answer
compass build --direct settings runs Emacs in batch mode to tangle each
surface's document, and calls Emacs directly (no cmake, no vcpkg), so it works
in a light environment. The settings alias deploys both surfaces; --claude
and --dsh narrow it to one:
./compass.sh build --direct settings # both surfaces ./compass.sh build --direct settings --claude # .claude/settings.json only ./compass.sh build --direct settings --dsh # .dsh/, copied into ~/.dsh
A surface flag with any other target is refused rather than ignored, because
build ores.storage.tests --dsh would otherwise report a successful build of
something the caller did not ask for.
Expected output for --claude:
Tangled 7 code blocks from claude_code_settings.org Settings deployed to …/.claude/settings.json
And for --dsh, which tangles into the checkout and then copies the result to
~/.dsh, the directory the harness reads:
Tangled 2 code blocks from dsh_settings.org DSH settings tangled to …/.dsh Installed …/.dsh/sandbox-writable-paths Installed …/.dsh/bin/dsh-bwrap-writable-ores.sh The home patch selects the runner: …/.dsh/cordis.patch.yml
The two halves place their output differently. The Claude half derives its
tangle target from ores/repo-root (defined in
projects/ores.lisp/ores-babel.el), so no path appears in its document. The
DSH half declares its targets on the master blocks of its own document,
relative to that document, because org resolves a relative :tangle against
the file it is reading rather than against the working directory.
Both halves must run outside the sandbox. The Claude half needs a full
environment for the ores-babel.el project detection; the DSH half writes
~/.dsh, which the sandbox deliberately does not grant, so that the rules
cannot rewrite the sandbox that reads them. Use dangerouslyDisableSandbox:
true on the Bash tool call.
In a full environment the equivalent CMake targets (deploy_settings and
deploy_dsh_settings, both dependencies of deploy_org) run the same
scripts; prefer the compass command above.
2.1. Prerequisites
- Emacs on
PATH. (No cmake configure step is required for--direct.)
2.2. Verify
python3 -m json.tool .claude/settings.json
The output should be valid JSON with a permissions.allow array and a
sandbox object. The number of allow entries is small by design (25 as
of the initial version); if the count grows unexpectedly the source
file should be audited.
For the DSH half, read the live rules and compare them with what the document generated:
cat ~/.dsh/sandbox-writable-paths diff .dsh/sandbox-writable-paths ~/.dsh/sandbox-writable-paths
The diff is empty when the deploy is current. A difference means the host is
running rules the document no longer states, which is worth resolving before
trusting either.
3. Script
projects/ores.lisp/src/ores-build-settings.el is the Emacs script the target invokes. It:
- Loads
projects/ores.lisp/ores-babel.elto makeores/repo-rootavailable. - Sets
org-babel-default-header-args:jsonwith the absolute tangle target path derived fromores/repo-root, so the org file itself carries no path. - Calls
org-babel-tangle-fileondoc/llm/claude_code_settings.org, which assembles the JSON via noweb-referenced permission blocks.
compass build --direct settings runs this script directly via Emacs.
The equivalent deploy_settings CMake target (used for full-environment
builds) lives in CMakeLists.txt near
add_custom_target(deploy_settings ...) and invokes the same script.
The DSH half has its own script,
projects/ores.lisp/src/ores-build-dsh-settings.el, and the same shape: it
makes ores/repo-root available, tangles doc/llm/dsh_settings.org, then
copies the two generated files into ~/.dsh and marks the runner
executable. The copy is the point — a symbolic link would sit in the checkout,
which a confined command can write, so the sandbox could widen itself. The
script reports whether ~/.dsh/cordis.patch.yml selects the runner rather than
writing that file, because the harness manages part of it. Its CMake target is
add_custom_target(deploy_dsh_settings ...).
4. Tested by
Manual. Run the target and verify .claude/settings.json is valid
JSON. Tested 2026-05-22 against preset linux-clang-debug-ninja;
CMake reconfiguration was not required on a warm build.
5. See also
- Claude Code Settings — the literate source; edit permissions here.
- DSH Settings — the literate source for the DSH sandbox rules; edit grants here.
- How do I deploy the skills? — parallel target for Claude Code skills.
- CMake setup — preset names and output layout.