You are reading this because CONTEXT/.bootstrapped does not exist (the
first-launch gate in AGENTS.md, also named in CONTEXT/core.md). This copy
of OPS has never met its Operator. Your job this session is the bootstrap:
interview the new user, write who they are and how they want work run into
CONTEXT/, and hand them a harness that already knows them. On a fresh copy
the bootstrap IS the session: do not start normal work, and do not treat
USER.md or voice.md as real; they ship as templates you are about to
replace.
The doctrine already ships and stays generic: core.md (always loaded),
how-i-work.md (P1-P15 and the situational rules), model-roles.md, and
project-kata.md. The template sync (harness-update) keeps updating those
files, so bootstrap never edits them, with one exception named in Stage 1
(the kata's Operator overlays). What is missing is the who layer, and it
lives only in files no template sync touches:
CONTEXT/USER.md: who the Operator is and who matters around them.CONTEXT/voice.md: how they write (the voice slot).CONTEXT/standing-orders.md: their rulings, each dated with its why. A ruling overrides the matching default inhow-i-work.mdwithout editing it.- The slots
CONTEXT/work-tracking.md,team.md, andtools.md.
Run it in the harness's own idiom, because you are configuring that harness:
- The structured question tool, multiple-choice first. Every question is
a clickable form with concrete options and a recommended default
(
how-i-work.md§ Intake detail). Typing is the fallback. - Never ask what you can detect. Stage 0 recon answers the stack and environment questions for free.
- Document the why as you write (P1): a non-obvious choice gets its reason next to it, and every standing order carries its why.
- Stages are resumable. The marker records the last stage completed. Stage 1 makes the harness fully usable; Stages 2 and 3 are offered, not forced.
Detect what the machine already knows so you never ask for it. Run these
read-only probes, absorb the results, and use them to pre-fill USER.md and
the recommended defaults in every Stage 1 question. Report a one-line summary
before the first question ("Here's what the box already told me; correct
anything wrong"), so recon is transparent.
- Identity the box already has:
If
git config --get user.name; git config --get user.email git var GIT_AUTHOR_IDENT # an error means every commit fails gh auth status 2>&1 | head
git varerrors, tell the Operator to rungit config --global user.nameanduser.email: deploy fails withgit-identityuntil they are set (DEPLOYMENT.md, step 7), and a missing identity breaks the memory sync and the daily backup. - Installed toolchain (probe presence, install nothing):
for t in docker node python3 pwsh go rustc psql terraform kubectl; do \ command -v "$t" >/dev/null && printf '%s %s\n' "$t" "$($t --version 2>&1 | head -1)"; done
- MCP servers already configured:
claude mcp listif available, and the deferred-tool surface (ToolSearch) for connected servers. Named servers are strong signal for the domain and for thetools.mdslot. - The boot: confirm the core is loaded:
~/.claude/rules/ops-core.mdshould resolve toCONTEXT/core.md(readlink -f). If it does not, tell the Operator to run.claude-config/deploy.shbefore going on: without it, later sessions start without the core. - Existing Claude Code setup: list
~/.claude/skills/and read~/.claude/settings.json. Note the values ofpermissions.defaultMode,skipDangerousModePermissionPrompt,remoteControlAtStartup, andautoCompactEnabled: Round F discloses them and asks about them. Never edit this file: on Linux and macOS it is a symlink into the Operator's tracked linuxploitacious checkout. - Do the pinned models answer on this plan:
Report only: it prints
.claude-config/bin/model-probe.sh --list # what the settings pin; no API call .claude-config/bin/model-probe.sh # one short request per distinct id
ok,FAIL, orUNSUREper pinned id and never edits settings. If an id FAILs, report the CLI error and what that pin serves (CONTEXT/model-roles.md), and point the Operator at "Settings, pins, and the shared Stage-1 file" in that file; do not edit a settings file to work around it. A failure can also mean authentication, network, or CLI trouble, not a missing entitlement.UNSURE(a timeout or a usage limit) says nothing about entitlement. - T3 Code host:
ls -d ~/.t3/runtime/versions/*/t3 2>/dev/null(or aT3CODE_HOMEin the environment). If present, Round G applies. - Repos under
~: a shallow scan for.gitdirs (find ~ -maxdepth 3 -name .git -type d 2>/dev/null | head -40) sketches what the Operator builds.
Recon is inference, not truth (P3): everything inferred here is a default to confirm in Stage 1, never a fact written unverified.
Run a small number of question rounds. Lead every option list with the recon-derived recommendation, and keep to the decisions that change behavior.
Round A: Identity.
- Name (pre-fill from
git config user.name). - Role or title, in their words (offer a couple of recon-inferred guesses).
- Organization type:
Solo / freelance·Small team or startup·Established company·Enterprise·Other. - Primary domain: candidates inferred from repos and MCP servers, plus
Other. The most load-bearing answer: it colors every later default. - People: who gates their decisions, and whether they want a team roster
now (
team.md) or later.
Round B: What they will use the harness for. Multi-select:
Building / automation / integration · Writing and documents ·
Research and analysis · Client or stakeholder deliverables ·
Ops / infrastructure · Data / trading / quant · Other. Their picks set
the emphasis of USER.md.
Round C: Autonomy posture. Explain the trade honestly, then let them choose:
-
Full autonomy: the go is the switch(recommended default): plan hard up front, then run end to end with zero re-prompts, merging green reviewed work without asking. This is whatcore.md§ "Intake, then autonomy" describes. -
Checkpoint mode: pause at each major step for confirmation. -
Confirmation-heavy: confirm before any write, commit, or external action.Record anything other than the default as a dated standing order that names the posture and why, so a later session neither reverts it nor silently applies the core's default over it.
Round D: Prioritization frameworks. The shipped defaults are Theory of
Constraints, Improvement Kata, and the Phoenix Project lens
(how-i-work.md § Framework alignment). Offer: Keep all three ·
Keep some (multi-select) · Swap in my own (capture theirs) ·
Drop the framework overlay. Record any change as a standing order; leave
how-i-work.md itself untouched.
Round E: Output defaults. Confirm or override the default document
format (.docx / .md / other), the conversation register (casual or
formal), and whether a rendered visual page for complex data is offered by
default. Record overrides as standing orders.
Round F: Permission mode (always asked; never skipped or defaulted silently). Before the question, tell the Operator plainly what the Stage-1 settings turned on (README "Opinionated by design" has the full list), using the values recon read:
permissions.defaultMode: "bypassPermissions": every session starts with no permission prompts. Claude Code runs shell commands, file edits and deletes, and network requests without asking; onlydenyrules and OPS's two guard hooks (git guard, secrets guard) stop a call.skipDangerousModePermissionPrompt: true: the one-time confirmation Claude Code shows before entering bypass mode is skipped.remoteControlAtStartup: true: every interactive session connects to Remote Control at start, reachable from the Claude apps signed in to the Operator's own account (no one else gets access).- Auto-compaction is on as a backstop near the end of the window (not part of this choice; the compaction standing order covers it).
Then ask, with these options:
Keep the OPS defaults(the shipped configuration): bypass mode, no launch confirmation, Remote Control at startup. Fits the full-autonomy posture.Normal permission prompts in terminal sessions(no admin rights needed): Claude Code asks before edits and shell commands, and Remote Control waits for/remote-control. Applies to every session launched through theclaude()shell function; IDE extensions and other launchers keep the Stage-1 defaults.Managed normal default, bypass disabled(needs admin rights): set the normal starting default and disable Remote Control at startup for every launch path and user on the machine. Bypass mode cannot be entered, but other explicit CLI or IDE permission-mode choices still apply.
Prompts and the full-autonomy posture pull against each other: with prompts on, a run stops at each one until the Operator answers. If they pick prompts, say so and offer to revisit Round C.
Apply the choice without touching the Stage-1 settings.json (a tracked file
in their linuxploitacious checkout; an edit there dirties it, and its next
git pull --ff-only fails whenever upstream changed the same file):
- Keep: no change.
- Terminal sessions: in the
claude()function thatdeploy.shwrote to~/.zshrc.localand~/.bashrc.local(Windows: theprofile.local.ps1seamdeploy.ps1wrote), replace each--settings '{"ultracode":true}'withShow the Operator the diff before writing it.--settings '{"ultracode":true,"permissions":{"defaultMode":"default"},"remoteControlAtStartup":false}'--settingssits above the user settings file, so these keys win for that session; a re-deploy leaves the edited function alone. When the Operator passes their own--settingsto a launch, the shim adds nothing, so they add--permission-mode defaultto that launch and merge"remoteControlAtStartup":falseinto their own settings JSON as well."acceptEdits"instead of"default"is the middle ground (file edits without asking, unapproved shell commands still ask). - Managed default, bypass disabled: give the Operator this file to install
with admin rights (merge it into an existing file rather than overwrite one) at
/etc/claude-code/managed-settings.json(Linux and WSL),/Library/Application Support/ClaudeCode/managed-settings.json(macOS), orC:\Program Files\ClaudeCode\managed-settings.json(Windows):Managed settings outrank every other settings file and{ "permissions": { "defaultMode": "default", "disableBypassPermissionsMode": "disable" }, "remoteControlAtStartup": false }--settingsJSON.disableBypassPermissionsModealso rejects--dangerously-skip-permissions. The starting default is not a mode lock: an explicit--permission-modeor an IDE's saved mode can still select another non-bypass mode, includingautooracceptEdits. Set those launchers todefaulttoo. Do not run the install yourself: it is a system-wide change the Operator makes.
Existing permission allow rules still apply in normal mode, including broad
shell approvals. Review /permissions with the Operator; changing the default
does not erase those approvals. See permission-mode precedence
and permission rules.
Check it took: in a new shell, launch claude; the footer shows the normal
mode, Remote Control has not connected, and a shell command without an
existing approval asks before it runs. Check IDE launchers separately.
Record the choice in the marker (permissions=keep, permissions=shell, or
permissions=managed) and as a dated row in CONTEXT/standing-orders.md,
so a later session never quietly reverts it.
Round G: T3 Code browser (T3 hosts only; skip when recon found no T3).
T3 Code's headless browser (its page previews and browser tools) needs a
one-time setup on each host: sudo <t3 binary> browser setup, where the
binary is the newest ~/.t3/runtime/versions/<version>/t3. It installs the
browser's system libraries and, on Ubuntu 23.10 and later, an AppArmor profile
scoped to T3's chrome-headless-shell (/etc/apparmor.d/t3-chrome-headless-shell);
it never changes the system-wide user-namespace restriction. Recommend
Enable it now and show the exact command:
t3="$(ls -1d ~/.t3/runtime/versions/*/t3 | sort -V | tail -1)"; sudo "$t3" browser setupOn the Operator's yes, run it if passwordless sudo is available
(sudo -n true); otherwise hand them the command to run. It is a system-wide
change, so it needs that yes. DEPLOYMENT.md § "T3 Code hosts" has the
detail.
On a T3 Code host, note for Round F: T3 sets each thread's permission mode from its own settings, so the shell-function option above does not reach T3 threads; the managed-settings option does.
-
CONTEXT/USER.md, replacing the template: every EXAMPLE block, the banner, and theUSER-TEMPLATE: unfilledcanary line (verify-ops.shcheck 21 fails on a bootstrapped copy that still carries it). Keep the section shape; write only what the Operator gave you or confirmed from recon. Do not invent clients, teammates, or metrics; an honest short file beats a padded one. -
CONTEXT/voice.md, a starter, so a writing task never meets an empty slot before Stage 2. Keep the section shape, fill the three registers with whatever cues Round E and the interview surfaced, mark the rest "not yet captured", and open the changelog with a row "Stage 1 starter; refine in Stage 2". Remove the template banner and the synthetic samples. -
CONTEXT/standing-orders.md: replace the EXAMPLE row with one dated row per ruling from Rounds C through F (the permission choice always gets a row), each with its why. -
CONTEXT/project-kata.md§ Operator overlays: the default LICENSE, which file plays the spec slot, and the default org or cluster name forPROJECTS/<org>/<repo>. This is the one doctrine file bootstrap edits; a later template sync shows it as a CONFLICT to port by hand. -
The slots.
CONTEXT/work-tracking.md: the Operator's real time, ticket, and board tools (which system, how time is logged), replacing the EXAMPLE blocks and deleting any block for a surface they do not use. This is the file thesession-closereconciliation gate reads; leave it accurate or empty, never stale EXAMPLE content posing as a real system.team.mdandtools.md: fill what Round A and recon gave you, or leave the templates (every skill that reads them degrades gracefully). -
Seed the auto-memory pool. Write a few durable "who the Operator is" entries into the cross-project memory pool, routed per
core.md§ "Memory and where knowledge goes", then make sure the pool is git-synced:.claude-config/bin/memory-init(deploy runs it; rerun it if this session's memory dir is not yet a symlink into.claude-memory/). Pointers only, never secret values (secrets-guardblocks them). -
Write the marker. Create
CONTEXT/.bootstrappedrecording the stage, the date, and the Round F choice (see "The marker"). Its presence flips the first-launch gate to normal operation. After this write, the harness is fully usable.
Before you finish, offer to scaffold the Operator's first domain-partner
skill with meta-skill-creator: a co-pilot skill built around their domain
from Round A (the questions it always asks, the context it always loads, the
outputs it always produces). This is how OPS becomes theirs. Offer it; build
it on a yes, or note they can ask anytime. Then offer Stage 2.
Goal: replace the Stage 1 starter voice.md with an evidence-based profile,
so deliverables sound like the Operator instead of a model's house style.
State the privacy boundary first, plainly: all analysis runs locally on
this machine. You read their writing here, extract patterns here, and write
the result to CONTEXT/voice.md here. Nothing is uploaded or shared. Say this
before you ask them to point at anything.
Preferred path: mine a real corpus. Ask them to point at local writing of
their own: a sent-mail export (.mbox, .eml, a folder of saved messages),
exported chat logs, or writing already on the box (READMEs, PR descriptions,
git log --author=<them> --format='%B', docs, past deliverables). Read a
representative sample and fill every section of voice.md: tone, the three
registers with a real example each, words they use and avoid (pulled from the
corpus, not guessed), formatting, the client deliverable brand kit (their real
logo file, colors, fonts, section order, contact block; or an honest "no brand
kit yet; ask before styling deliverables"), email and chat patterns, verbatim
writing samples labeled by register, and the changelog.
Ground every claim in the text (P3): quote real lines; never fabricate a sample. An honest profile from ten real emails beats an invented one.
Fallback: no corpus. Run a calibration exercise: take one neutral paragraph and present three rewrites (terse and direct, warm and casual, formal and structured) as options. Have them pick and react; iterate two or three rounds until the samples read like them. Record the converged samples and stated preferences, and note in the changelog that the profile is preference-based pending a real corpus.
Overwrite CONTEXT/voice.md with the result and bump the marker to
stage=2.
Once the Operator has used the harness for a while, close the loop. Review
what the sessions revealed (corrections they made, defaults they kept
overriding, preferences that showed up in auto-memory) and propose concrete
changes: new or revised standing orders, USER.md updates, and voice.md
where the voice drifted from the captured profile. Present them as a
diff-style list (accept / adjust / skip each); apply what they approve. Bump
the marker to stage=3.
Stage 3 is a proposal, not an ambush: surface it when the current task allows, never in the middle of live work.
CONTEXT/.bootstrapped is a small state file. Its presence gates first
launch; its stage value tells a later session what remains to offer. Write
it as key=value lines:
stage=1
bootstrapped_at=<ISO-8601 date>
permissions=<keep, shell, or managed: the Round F choice>
Bump stage to 2 after voice capture and 3 after the tune pass. Never
delete the marker to "re-run" bootstrap; re-running a stage means invoking
that stage's flow, not tricking the gate.
When Stage 1 is written and the marker is set, tell the Operator plainly that OPS is configured and usable, recap what you captured, and point them at Stage 2. From the next session on, startup runs normally.
A copy that predates this layout (it has about-me.md, brand-voice.md,
working-preferences.md, or boot-digest.md) is not a fresh copy: migrate it
per DEPLOYMENT.md § "Migrating to the core boot" instead of re-running
bootstrap.