Claude Code Settings
Table of Contents
Summary
This file is the single authoritative source for .claude/settings.json.
It follows the literate programming style: every permission entry is
accompanied by prose naming the operations it enables, the concrete
command variations it covers, and the security reasoning behind the
grant. Do not edit .claude/settings.json directly; regenerate it with
compass build --direct settings. Entries are kept to the minimum
necessary; each wildcard is chosen to cover only the intended surface.
How to regenerate
Via the Build pillar in --direct mode — Emacs only, no cmake/vcpkg, so
it works in a light environment (the skills alias recreates the other
generated half of .claude/):
compass build --direct settings # .claude/settings.json compass build --direct settings skills # recreate all of .claude/
Or via the full-environment CMake target:
cmake --build --preset linux-clang-debug-ninja --target deploy_settings
Both invoke projects/ores.lisp/src/ores-build-settings.el, which tangles this file to
.claude/settings.json. Requires Emacs on PATH. Must be run outside the
sandbox (the ores-babel.el project detection needs a full environment;
the CMake path also needs compiler detection during reconfiguration); use
dangerouslyDisableSandbox: true on the Bash tool call.
Master settings block
The master block assembles the final JSON from noweb references defined
in the sections below. It carries no :tangle directive; the output
path (.claude/settings.json under the repo root) is injected by
projects/ores.lisp/src/ores-build-settings.el via
org-babel-default-header-args:json using the ores/repo-root
variable from projects/ores.lisp/src/ores-babel.el.
Sections are separated by a trailing comma in the reference line; the
last section in each array carries no comma.
{
"autoMemoryEnabled": false,
"permissions": {
"allow": [
<<perm-files>>,
<<perm-build>>,
<<perm-sql>>,
<<perm-compass>>,
<<perm-codegen>>,
<<perm-tests>>,
<<perm-vcs>>,
<<perm-gh-pr>>,
<<perm-web>>,
<<perm-shell>>
]
},
"sandbox": {
<<sandbox-network>>,
<<sandbox-filesystem>>,
<<sandbox-excluded>>
}
}
Top-level settings
autoMemoryEnabled
Set to false to disable Claude Code's built-in harness auto-memory
system, which otherwise writes MEMORY.md and per-topic *.md files
under ~/.claude/projects/<hash>/memory/. ORE Studio uses its own
version-controlled memory system under doc/llm/memory/ (see Project
memory); running the harness system in parallel creates a second,
unreviewed memory source that can contradict or duplicate the org
system. Disabling it ensures all durable LLM memory is in the repo
and tracked by git.
Permissions
Permission strings use glob wildcards (*), not regular expressions.
* matches any sequence of characters including spaces but not /,
so it covers arguments but not sub-paths. A space before * enforces
a word boundary: Bash(make *) matches make -j2 foo but not
make_something. Each subsection documents the surface covered and
the reason the grant is necessary.
File access
Edit(**) and Write(**) grant read/write access to every file in the
project tree without hardcoding an absolute path. Claude Code resolves
permission globs relative to the directory containing .git — the
project root — at startup. This means the same committed
settings.json works across all checkouts regardless of where they
live on disk (/mnt/development/..., /home/user/..., etc.).
** matches zero or more path segments including directory separators,
so Edit(**) covers foo.txt, projects/ores.risk/src/foo.cpp, and
any other path depth. This replaces the previous per-subtree entries
(Edit(projects/**), Edit(doc/**), etc.) with a single grant that
covers the whole tree.
Read(*) is not included here because Claude Code does not require an
explicit allow entry for reads; they are permitted by default unless
the sandbox filesystem deny-list blocks them.
"Edit(**)", "Write(**)"
Build tools
The build system requires make, cmake, and (for non-compilation
deploy targets) emacs in batch mode. All three are invoked with
varying flags and targets depending on the operation.
Bash(make *) is broader than a path-restricted form but narrower
than an unconditional build allow. Any make invocation is a
compilation or deployment action; no make-based attack vector exists
in this project context beyond unintended compilation.
Bash(cmake *) covers both configuration (cmake --preset) and build
(cmake --build) steps. The wildcard is necessary because the preset
name and target name vary.
Bash(emacs -Q --script *) covers the deploy-family targets
(deploy_skills, deploy_settings, deploy_site) which invoke Emacs
in batch mode. The -Q flag disables user configuration; --script
restricts execution to the named file. Only scripts checked into the
repository are passed here.
Bash(sccache *) covers direct invocations of the sccache compiler
cache: starting or stopping the daemon (sccache --start-server,
sccache --stop-server), querying statistics (sccache --show-stats),
and manual cache management (sccache --zero-stats). CMake invokes
sccache transparently as a compiler wrapper (CMAKE_CXX_COMPILER_LAUNCHER);
those subprocess invocations do not require a separate entry, but
direct calls from Claude do.
Common invocations:
make -C build/output/linux-clang-debug-make -j2 ores.utilitycmake --build --preset linux-clang-debug-ninja --target deploy_skillscmake --build --preset linux-clang-debug-ninja --target deploy_settingsemacs -Q --script projects/ores.lisp/src/ores-build-skills.elemacs -Q --script projects/ores.lisp/src/ores-build-settings.el./compass.sh build ores.utility.testssccache --start-serversccache --show-stats
"Bash(make *)", "Bash(cmake *)", "Bash(emacs -Q --script *)", "Bash(sccache *)"
SQL scripts
Four scripts under projects/ores.sql/ manage the local development
database. Each is granted individually rather than via a directory
wildcard (e.g. Bash(projects/ores.sql/* *)) to prevent accidental
execution of other files in that tree.
compass db sql executes SQL against the database.
compass db recreate drops and rebuilds the entire schema.
validate_schemas.sh checks that the live schema matches expectations.
kill_db_connections.sh terminates stale connections before a recreate.
All four require dangerouslyDisableSandbox: true at the Bash tool
level because the sandbox blocks outbound connections to
localhost:5432. The sandbox.network entry below grants localhost
access, which may make the per-call override unnecessary once Claude
Code respects project-level sandbox overrides.
Note: never prepend PGPASSWORD on the command line; these scripts
source .env themselves.
Common invocations:
compass db sql -- -f projects/ores.sql/schema/foo_create.sqlcompass db recreateprojects/ores.sql/utility/validate_schemas.shprojects/ores.sql/utility/kill_db_connections.sh
"Bash(projects/ores.compass/compass.sh db *)", "Bash(projects/ores.sql/utility/validate_schemas.sh *)", "Bash(projects/ores.sql/utility/kill_db_connections.sh *)"
Compass
Compass is the developer toolkit purpose-built to simplify LLM
workflows: orientation (bearings, where, fleet), navigation
(search, list, show), agile authoring (add, story new,
task new), session continuity (journal), PR work (pr checks,
review list/reply/resolve) and environment provisioning (env).
CLAUDE.md's first instruction to every session is ./compass.sh
bearings, and project memory directs the LLM to prefer compass over
raw Unix tools and to use it for all agile artefacts.
A tool we mandate on every session must not pay a permission prompt
per invocation. The grant is deliberately blanket rather than
per-subcommand: compass's mutating surface is repo-local files (doc
scaffolds, .journal.org, .env) and branch creation, all of which
the session can already do unprompted via Edit=/=Write=/=git * — a
read-only subset would add ceremony exactly on the highest-frequency
flows (scaffolding, journaling) without adding safety. Compass is the
trusted, recipe-documented boundary; authorising the entry point
authorises its delegations (git, gh, codegen) through compass only.
All four invocation forms are covered: the root wrapper (what
CLAUDE.md instructs), the component script, each with and without the
./ prefix.
Invocation convention: always call compass using one of these four
relative forms from the project root. Never invoke it via its absolute
path (e.g. /mnt/development/.../compass.sh) — absolute paths do not
match any of the patterns below and will trigger a permission prompt.
When the Bash tool's working directory has drifted into a subdirectory
(e.g. after working in projects/ores.codegen), prepend a cd to the
repo root before calling compass:
cd /mnt/development/Development/OreStudio/ores_dev_brave_hopper && ./compass.sh add capture ...
"Bash(./compass.sh *)", "Bash(compass.sh *)", "Bash(./projects/ores.compass/compass.sh *)", "Bash(projects/ores.compass/compass.sh *)"
Code generation
codegen.sh is the main entry point for C++ and SQL
code generation via ores.codegen (regenerate, generate
subcommands). run_generator.sh drives the C++ code generator (Dogen).
plantuml_er_generate.sh produces PlantUML ER diagrams. generate_doc.sh
is a legacy script being decommissioned — use compass instead.
The grant is per-script rather than per-directory for the same reason as SQL: a directory wildcard would permit running arbitrary scripts in a large codegen tree.
Invocation convention: always call codegen using one of the relative
forms below from the project root — with or without the ./ prefix.
Never use an absolute path; absolute paths do not match the patterns
below and trigger a permission prompt.
Common invocations:
./projects/ores.codegen/codegen.sh regenerate --component refdata-cpp --profile all-cppprojects/ores.codegen/codegen.sh regenerate --component refdata-cpp --profile all-cppprojects/ores.codegen/codegen.sh generate --model path/to/model.json --profile all-cppprojects/ores.codegen/run_generator.shprojects/ores.codegen/plantuml_er_generate.sh -i doc/plans/foo.org
"Bash(./projects/ores.codegen/codegen.sh *)", "Bash(projects/ores.codegen/codegen.sh *)", "Bash(./projects/ores.codegen/generate_doc.sh *)", "Bash(projects/ores.codegen/generate_doc.sh *)", "Bash(./projects/ores.codegen/run_generator.sh *)", "Bash(projects/ores.codegen/run_generator.sh *)", "Bash(./projects/ores.codegen/plantuml_er_generate.sh *)", "Bash(projects/ores.codegen/plantuml_er_generate.sh *)"
Test execution
Tests are run either through CTest (which dispatches to individual
binaries) or by invoking binaries directly for focused runs. Test
binary paths follow the pattern
build/output/<preset>/publish/bin/ores.<component>.tests.
Bash(ctest *) covers all CTest-mediated runs including the rat
target (which runs all registered suites). The direct-binary pattern
Bash(build/output/*/publish/bin/ores.* *) uses two wildcards: the
first matches the preset directory name (e.g. linux-clang-debug-make)
without crossing / boundaries; the second matches the component name
suffix and any arguments (filter tags, verbosity flags).
No wildcard is broad enough to execute arbitrary binaries outside the
publish/bin/ores.* namespace.
Common invocations:
ctest --test-dir build/output/linux-clang-debug-make -R ores.utilitybuild/output/linux-clang-debug-make/publish/bin/ores.utility.testsbuild/output/linux-clang-debug-make/publish/bin/ores.risk.tests "[generators]"
"Bash(ctest *)", "Bash(build/output/*/publish/bin/ores.* *)"
Version control
Bash(git *) covers all git subcommands. This is intentionally broad:
every git operation (read-only introspection, branching, staging,
committing, pushing, rebasing) shares the same prefix. Narrowing by
subcommand would add many entries without meaningfully reducing risk,
since all operations target the local repository or the authorised
remote.
Common invocations:
git add projects/ores.risk/src/domain/foo.cppgit commit -m "[risk] Add foo entity"git push --set-upstream origin feature/foogit rebase main
"Bash(git *)"
GitHub CLI — pull requests
The safe gh pr subcommands are granted individually. Four subcommands
are deliberately excluded and will always prompt for user confirmation:
| Excluded | Reason |
|---|---|
gh pr close |
Closes a PR; discards in-progress work. |
gh pr revert |
Creates a revert PR against a merged commit; external and visible. |
gh pr lock |
Moderation action; unusual enough to warrant a prompt. |
gh pr unlock |
Same as above. |
All other subcommands are either read-only (view, list, status,
checks, diff) or routine workflow actions (create, edit,
comment, review, ready, reopen, update-branch, checkout,
merge). Note: gh pr merge * is intentionally broad — it covers
--squash, --rebase, --admin, and --delete-branch without
prompting. This is an explicit trade-off: Claude Code is trusted to
merge its own reviewed PRs autonomously. The irreversibility of merge is
accepted; user confirmation is reserved for the destructive subcommands
above (close, revert, lock).
These commands require dangerouslyDisableSandbox: true because gh
authenticates via the OS keyring, which is not accessible inside the
sandbox. Source build/scripts/set_ssh_agent.sh beforehand for push/fetch
operations; gh uses its own token, not the SSH agent.
Common invocations:
gh pr create --title "[risk] Add foo" --body "..."gh pr checks 947gh pr view 947 --commentsgh pr edit 947 --body "..."gh api repos/OreStudio/OreStudio/pulls/947/commentsgh api graphql -f query'…'=
"Bash(gh pr view *)", "Bash(gh pr list *)", "Bash(gh pr status *)", "Bash(gh pr checks *)", "Bash(gh pr diff *)", "Bash(gh pr create *)", "Bash(gh pr edit *)", "Bash(gh pr comment *)", "Bash(gh pr review *)", "Bash(gh pr ready *)", "Bash(gh pr reopen *)", "Bash(gh pr update-branch *)", "Bash(gh pr checkout *)", "Bash(gh pr merge *)", "Bash(gh run *)", "Bash(gh api *)"
Web access
WebFetch(domain:*) allows fetching from any domain. The sandbox
network allowlist (see below) is the actual security boundary; the
permission entry controls only whether Claude Code prompts. Domains
not in the network allowlist remain unreachable regardless.
WebSearch enables web search. No domain restriction is applied here;
the search provider is fixed by the Claude Code runtime.
"WebFetch(domain:*)", "WebSearch"
Shell utilities
Read-only and data-processing utilities used in analysis pipelines, build inspection, and document generation. Each covers a standard POSIX tool.
Permission rules evaluate compound commands per subcommand: every
piece of a && b or a | b must match an allow rule or the whole
invocation prompts. In practice almost every compass or git command
arrives wrapped in a pipeline — ./compass.sh list --type recipe |
head, git log --oneline | tail -5 — so an uncovered head or
tail reintroduces a prompt on the highest-frequency flows even
though the primary command is authorised. The set below covers the
pipeline vocabulary those flows actually use.
sed and awk are deliberately not listed: both can execute
arbitrary shell commands (awk 'BEGIN {system(...)}', GNU sed's
e command), so auto-approving them would turn a text-processing
grant into an unprompted arbitrary-execution grant. They prompt on
use; prefer the Read=/=Edit tools for file inspection and
modification. python3 * is required for ad-hoc analysis scripts and
codegen helpers (src/doc_generate.py, etc.). java * is required
for PlantUML, which is invoked as a JAR.
Common invocations:
find . -name "*.org" -newer doc/foo.orggrep -r "workspace_id" projects/ores.workspace/./compass.sh list --type capture | head -50python3 projects/ores.codegen/src/doc_generate.py --helpjava -jar /usr/share/plantuml/plantuml.jar -checkonly foo.pumlwc -l build/output/linux-clang-debug-make/publish/bin/ores.utility.tests
"Bash(find *)", "Bash(grep *)", "Bash(python3 *)", "Bash(java *)", "Bash(echo *)", "Bash(wc *)", "Bash(sort *)", "Bash(uniq *)", "Bash(head *)", "Bash(tail *)", "Bash(cat *)", "Bash(ls *)", "Bash(cut *)", "Bash(tr *)", "Bash(diff *)"
Sandbox overrides
The sandbox restricts filesystem writes and outbound network
connections beyond the defaults. These entries extend the allowlist
at the project level; they are applied in addition to (not instead
of) the global sandbox configuration in ~/.claude/settings.json.
Network
Grants outbound connections to localhost, required for PostgreSQL
(port 5432) access from SQL scripts. Without this entry, psql calls
fail with a connection refused error inside the sandbox and the
scripts must be run with dangerouslyDisableSandbox: true.
mcraveiro.github.io hosts the Dogen documentation and MASD reference
material used when writing knowledge documents and literate template
prose; fetching it during documentation tasks must not prompt.
"network": {
"allowedHosts": ["localhost", "mcraveiro.github.io"]
}
Filesystem
Extends the write allowlist to include the sccache cache directory.
The sandbox otherwise blocks writes to ~/.cache/sccache, causing
cache misses and forcing builds to recompile from scratch or requiring
dangerouslyDisableSandbox: true.
Two entries are required: ~/.cache/sccache authorises the directory
itself, and ~/.cache/sccache/** authorises all files and
subdirectories within it (object cache shards, the stats file, the
server log, etc.). Without the /** glob, sccache receives EPERM
when writing any cache object because the allowlist matches only the
directory path, not its contents.
"filesystem": {
"allowWrite": [
"~/.cache/sccache",
"~/.cache/sccache/**"
]
}
Excluded commands
Commands listed here never attempt to run inside the sandbox; they go straight to the regular permission flow (where the allow rules above auto-approve them). This kills the failure → retry-unsandboxed → prompt loop without widening what is authorised: exclusion changes where a command runs, not whether it is allowed.
Git needs this because linked worktrees resolve their gitdir into the
primary checkout (OreStudio.remote/.git/worktrees/<name>), which sits
outside the sandbox write allowlist — git fetch, add and commit
fail in-sandbox on the index lock and FETCH_HEAD, then prompt on every
unsandboxed retry. Compass needs it for the same reason one level up:
its highest-value verbs (pr create, pr sync, capture promote,
task start, task done) spawn git internally, so a sandboxed
compass run inherits the same gitdir failures. All four compass
invocation forms from the permission grant are mirrored here.
"excludedCommands": [ "./compass.sh *", "compass.sh *", "./projects/ores.compass/compass.sh *", "projects/ores.compass/compass.sh *", "git *" ]
See also
- How do I update Claude Code permissions? — full workflow for adding or fixing an allow-list entry.
- How do I deploy the settings? — redeploy after editing.
- How do I deploy the skills? — parallel deploy target.
- CMake setup — preset names and output layout.
- ores.sql — service table isolation and SQL script conventions.