Repository navigation
Design Principles Continued
This page gives the design principles 10 to 18 of dotclaude 1.0.0. Read it after Design, which gives principles 1 to 9. Each principle gives what it is, why it holds, and how the code applies it.
What: The asks slice asks before a call that discards work.
It also asks before a call that adds a skipped test or a lint suppression.
It asks before a call that changes a protected file.
A read never asks.
Why: Each ask stops the work and takes the time of the user. An ask for a read trains the user to approve without a reading. This is an inference.
How in the code:
- The rule is in the header of
src/plugins/dotclaude/slices/asks/slice.ts. -
src/plugins/dotclaude/slices/asks/limits.tslists the protected paths. Examples are the lint config, the runner config, the CI paths, and the hook paths.
What: The auto mode classifier allows each safe command.
Risky but recoverable work needs the user.
Each destructive action is forbidden, also when the user asks for it.
The user can still run such a command with a ! command.
Why: The user chose this on 2026-10-12 (change.md).
How in the code:
- Setup writes the
autoModepart to the user settings only. Claude Code reads it only there (src/plugins/dotclaude/slices/setup/domain/automode.ts). - The forbidden actions are in the
autoMode.hard_denylist ofsrc/plugins/dotclaude/slices/setup/texts.ts/automode.json. - When the floor stops an action, the agent does not try another way.
The rule is in
src/plugins/dotclaude/slices/prompt/texts.ts/blocks.md.
What: Each decision that facts settle goes to Jev by default. A small Claude model answers when Jev gives no answer. Approvals and preferences stay with the user.
Why: The user chose this on 2026-10-12 (change.md).
How in the code:
-
src/plugins/dotclaude/slices/decide/adapters/jev.tsandadapters/fallback.tsimplement one provider port. The port is inports.ts. -
ports.tsnames each reason that Jev gives no answer. The reasons areno-key,invalid-key,no-balance,usage, andfailed. - A question with one option, or with a few choices, is not sent to Jev (
tests/dotclaude/decide/ask.test.ts). -
JEV_TIMEOUT_MSis45_000insrc/plugins/dotclaude/slices/decide/limits.ts.
What: The spec workflow is part of the core plugin.
The lanes of a change come from an append-only events.jsonl.
The log has one line for each change.
Why: One fact is in one place.
A change is a one-line diff.
Two branches merge with no conflict (change.md).
How in the code:
-
src/kernel/spec-store.tsholds the types of the store. Thespecslice, the status line, and the handoff read them. - Only the
specslice writes the store. - The commands are on Spec Store.
What: Each file format has a schema number.
A reader stops with a message on a number that it does not know.
It does not convert an older file.
Why: 1.0.0 has no migration from an older version and no shim (change.md).
Code that reads an old layout is code to keep.
How in the code:
-
SPEC_SCHEMAinsrc/kernel/spec-store.tsis the number that the reader accepts. -
tools/generate/stray.tsfails on each file inplugins/that the generator did not write. During the rebuild, the listtools/rebuild-pending.txtnamed the files of the previous release that were still inplugins/. P16 ported the last of them and deleted the list.
What: Code uses arrow functions. Plain data and pure functions are the default. A class holds state across calls. An interface names a port.
Why: A pure function needs no stub in a test (design.md).
How in the code:
- Biome sets
useArrowFunctiontoerrorinbiome.json. The GritQL ruletools/lint/arrow-functions.gritcoversfunctiondeclarations. -
src/kernel/ports.tsholds the port interfaces.
What: dotclaude uses the worktrees of Claude Code, such as isolation: worktree.
It also uses the garbage collection of Claude Code.
dotclaude makes no worktree with git worktree add.
Why: Claude Code already does this work.
So dotclaude keeps no cleanup code (change.md).
How in the code:
- The
implementeragent setsisolation: worktree(src/plugins/dotclaude/slices/agents/agents/implementer.md). - The guard matches
git gc --prune=now(src/plugins/dotclaude/slices/guard/domain/matchers/git.ts).
What: A subagent fits one run. Few runs go at once, and a reviewer is read-only.
Why: These rules come from the lessons of the Bun port to Rust (https://bun.com/blog/bun-in-rust). The scale is that of a subscription.
How in the code:
- dotclaude has six agents:
debugger,implementer,investigator,planner,researcher, andreviewer. Each agent file has a fixed model and effort. - Each agent file holds the
maxTurnsofMAX_TURNS(src/plugins/dotclaude/slices/agents/limits.ts). The values are 61 fordebuggerandimplementer. They are 41 forplanner,researcher, andreviewer. They are 31 forinvestigator. -
reviewersetsdisallowedTools: Edit, Write, NotebookEdit, Agent. - Not in the code: the rule that a reviewer reads only the diff of a package. Also not in the code: the rule that a subagent cannot run a git command that changes shared state.
What: dotclaude writes its own files to .dotclaude/.
The layout is based on .claude/.
It keeps .claude/ for the files that Claude Code reads.
Why: Claude Code reads .claude/.
So dotclaude's own files would confuse that reading (change.md).
How in the code:
-
src/kernel/paths.tssetsDOTCLAUDE_DIRto.dotclaude. -
DOTCLAUDE_LOCAL_PATHSin the same file lists the paths that git must not track.
- Start
- How dotclaude Works
- Add-On Plugins
- How Claude Code Works
- Reference
- Rationale
- Evidence
- Development
- Archive