adopt-cockpit
Skill4 starsChanged 7 days agoMITView on GitHub
Set up or adopt cockpit for a project, bring a multi-repo product up for AI agents, or start a new product with cockpit. Use whenever the user wants cockpit set up, adopted or extended with another repository, or wants their repositories organised and their stack brought up for agents, even when they name no cockpit command. Routes by what is on disk to cockpit's non-interactive commands, keeps product-repository changes on a branch for review, and never invents configuration values.
- Reads credentials
In this repository4 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- llms.txtllms.txt
- verify-harness-capabilitySkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
21 rules. About 0 are common, 5 are distinctive, and 16 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈5
Distinctive · estimate
This author's own choices. Worth a look.
16
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 10
Use this when a human asks you to set cockpit up, adopt it, or bring their product up for agents.
- Distinctive: line 26
Follow these rules throughout.
- Very specific: line 29
Ask the human before creating a Git remote or hosted repository, running a destructive command (reset, approving removals), running sync …
- Very specific: line 41
Ask the human for the database and live vendor API hosts of every non-local environment (production, staging, shared) for the guards answer.
- Very specific: line 49
Every trust answer the answers file supplies (sibling, environment.install_policies, environment.posture, testing, guards, work.grading) …
- Very specific: line 60
Follow *Install cockpit* in docs/getting-started.md, from the same sources as the guide above: an exact dev dependency of the repository, …
- Distinctive: line 65
Verify without permitting an implicit download:
- Very specific: line 71
Every init below takes --target <tool>: replace <tool> with the target of the agent tool you are running in.
- Very specific: line 75
Run every command from the cockpit root through ./node_modules/@b00dea/cockpit/bin/cockpit.mjs.
- Distinctive: line 86
Look at the directory before asking.
- Very specific: line 141
Choose the agent tools: Ask the person which agent tools the team uses: claudecode (Claude Code), codexcli (Codex CLI), opencode …
- Very specific: line 150
Preview: Run ./node_modules/@b00dea/cockpit/bin/cockpit.mjs init .
- Very specific: line 156
Explore, then ask in one small round: Read the repositories for each outstanding field before asking, ask only for what the files and CLI …
- Very specific: line 246
Clear the readiness gaps: Every init stop, and ./node_modules/@b00dea/cockpit/bin/cockpit.mjs doctor --config cockpit.toml --json, carries …
- Very specific: line 262
If anyone will run Codex in this cockpit, a person must trust its guard hook on each machine, and again whenever sync changes the hook: …
- Very specific: line 306
After accepted initialization, and only with explicit permission to change the product's fixtures or auth setup, read …
- Distinctive: line 321
Use this when a repository has no local setup: it has only ever run in CI, staging or a cluster, so there is no Dockerfile, Compose file or …
- Distinctive: line 326
Read what the repository already states, without running or changing anything: the manifests and lockfiles for the runtime and entrypoint, …
- Very specific: line 371
Read variable names with ./node_modules/@b00dea/cockpit/bin/cockpit.mjs env keys --config cockpit.toml, never resolve values into the …
- Very specific: line 382
Keep the tracked product .env.schema beside the component that owns it.
- Very specific: line 425
Treat Varlock output as secret-tainted even in agent mode: --redact-stdout does not cover Varlock's own errors, which can print source …
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
<!-- Generated by `npm run references` from scripts/adopt-cockpit.skill.md and packages/cockpit/surfaces/skills/procedures/setup.md; edit those, not this file. -->Adopt cockpit
Use this when a human asks you to set cockpit up, adopt it, or bring their product up for agents.
cockpit declares a product's repositories once in cockpit.toml, generates the same agent
instructions, skills, guards and permissions for every harness, and runs the stack against the
live checkouts.
The full guide, with every situation, ships inside the cockpit package
under docs/. Once cockpit is installed (below), read
./node_modules/@b00dea/cockpit/docs/getting-started.md. Until then, read the same page from a
package tarball (package/docs/getting-started.md inside the .tgz), a cockpit source checkout
(docs/getting-started.md) or https://github.com/b0dea/cockpit/blob/main/docs/getting-started.md.
Each step below names its guide section. Guide pages cited after the install step are in that
installed directory.
Safety contract
A clean-looking configuration with invented values in it is the failure cockpit exists to prevent. Follow these rules throughout. Reuse explicit authorization already given for the stated scope; ask when scope is missing or an exact preview still needs acceptance:
- Ask the human before creating a Git remote or hosted repository, running a destructive command
(
reset, approving removals), runningsync --adopt, accepting aninitdigest, or adopting a test framework or dependency outside already authorized product-change scope. A Dockerfile, Compose file or.env.schemathe product needs goes on a new branch in that sibling's checkout, started with no uncommitted changes; show its diff against the starting branch in your report. Nothing is pushed. - Show the exact preview first: the
sync --dry-runlisting, theinitpreview and itspreviewSha256, the answers file, or the defaults digest. Consent binds to those bytes. - Take every value (port, image, command, health check, purpose, name) from a file you read or from the human. When neither has it, name the gap and ask.
- Accept as read only a field
initmarksconfirmedBy = "agent"(aderivedproposal), by marking it"derived". Show every other proposal with the file it came from; it becomes an answer only on the human's word. - Ask the human for the database and live vendor API hosts of every non-local environment
(production, staging, shared) for the
guardsanswer; env templates give variable names only, and once a cockpit exists./node_modules/@b00dea/cockpit/bin/cockpit.mjs env keys --config cockpit.tomllists them. - Offer the human
work.gradingas a real choice withinit's proposal and reason: the grader is optional, andoffis reasonable when tracking matters but grading is not wanted. - "Use sensible defaults" covers
initanswers only, never another change inside a product repository: an AGENTS.md pointer or apackage.jsonchange needs explicit product-change authorization covering its reviewed scope, which can already have been given. Mark every answer you chose as"agent-default"in the answers file's[provenance]table, and end your report with every default you chose, its field and value. - Every trust answer the answers file supplies (
sibling,environment.install_policies,environment.posture,testing,guards,work.grading) lands underunconfirmedwhatever the file says, and the stronger default holds until a person confirms it. End your report by telling the human to confirm each: delete its entry fromunconfirmed, then run./node_modules/@b00dea/cockpit/bin/cockpit.mjs sync --config cockpit.toml --interactivein a terminal outside the agent (the confirm command refuses these).
Install cockpit if it is missing
Done when the exact project-local executable lists the commands.
- Follow Install cockpit in
docs/getting-started.md, from the same sources as the guide above: an exact dev dependency of the repository, with Install from source as the fallback for an unreleased build. Show the human the manifest and lockfile change before installing. - For several repositories, the human may prefer a cockpit directory beside them; that is their call. Leave the product repositories untouched unless the human agrees.
Verify without permitting an implicit download:
./node_modules/@b00dea/cockpit/bin/cockpit.mjs --help- Every
initbelow takes--target <tool>: replace<tool>with the target of the agent tool you are running in. For an instructions-only tool, follow the Capability states section of./node_modules/@b00dea/cockpit/docs/harness-surfaces.md.
Run every command from the cockpit root through ./node_modules/@b00dea/cockpit/bin/cockpit.mjs; if that file is
absent, stop and repair the project-local install. Read flags from
./node_modules/@b00dea/cockpit/bin/cockpit.mjs <command> --help. In Codex's sandbox check, sync --dry-run and
--help run as it stands, unless [browser] is declared; other cockpit commands also need write
access to the state root, the Docker socket, or on macOS /bin/ps, so ask the person to approve
running them outside the sandbox, or to run them in a terminal. Pass --json and read result,
diagnostics[].code and invocation.exitCode. A pending init also exits 0, so read its
result.stage and result.question.
Route by what is on disk
Look at the directory before asking. Several cases can apply; bootstrap first.
| On disk | Do | Guide section |
| Inside an existing product repository (a Git checkout with a language manifest, Dockerfile or Compose file at its root) | A single repository gets an in-repo cockpit by default. If the human wants the cockpit in a folder of its own beside several repositories, put cockpit.root = "dedicated" in the answers file; never choose that for them. | Chapter 1 and The init interview |
| An empty directory, or only documents and decisions | Follow Bootstrap below. With no manifest, init builds a surfaces-only cockpit whose first sibling is the root itself (dir = ".", mount = "none"); the purpose comes from the human. Add each repository later with ./node_modules/@b00dea/cockpit/bin/cockpit.mjs sibling add <slug> --config cockpit.toml --create --purpose "<purpose>" --json and hand the human its result.publish.command (gh repo create). | The init interview |
| One or several repositories with services | From the directory that holds them, follow Bootstrap below: ./node_modules/@b00dea/cockpit/bin/cockpit.mjs init "$(pwd)" --target <tool> --json, then the same command with --accept-preview and --answers, then with --accept-defaults as well. | The init interview |
| Repositories scattered across the disk | Moving them is the human's call. Otherwise declare each with ./node_modules/@b00dea/cockpit/bin/cockpit.mjs sibling add <slug> --config cockpit.toml --from <path> --purpose "<purpose>" --json, then run ./node_modules/@b00dea/cockpit/bin/cockpit.mjs setup --config cockpit.toml --json. | Other situations |
| An existing Compose file | Answer environment.compose_files = ["compose.yml"]. For a Compose file inside a product repository, declare that repository as a sibling and point compose_files at the file in its checkout. Ask the human for the environment.machine floors and the environment.posture (how the product is reached and signed into) that init asks next. | Chapter 2 |
| A service with no local setup | Follow Create a local setup below. | Other situations |
Committed .claude/settings.json, .codex/config.toml or .codex/hooks.json | sync refuses with SURFACE_STATE_CONFLICT. With the human's yes, run ./node_modules/@b00dea/cockpit/bin/cockpit.mjs sync --config cockpit.toml --adopt <path> --json. | Adopt existing agent settings |
| A repository joins or leaves an existing cockpit | Run ./node_modules/@b00dea/cockpit/bin/cockpit.mjs sibling add <slug> --config cockpit.toml or ./node_modules/@b00dea/cockpit/bin/cockpit.mjs sibling remove <slug> --config cockpit.toml, then sync --dry-run, sync and check. | Add or remove a repository |
A repository has dotenv files, environment templates or a .env.schema | Follow Secret handling below. | Other situations |
After bootstrap
Done when ./node_modules/@b00dea/cockpit/bin/cockpit.mjs check --config cockpit.toml --json exits 0, where a
runtime is declared ./node_modules/@b00dea/cockpit/bin/cockpit.mjs preflight --config cockpit.toml --json passes,
and every gap in result.readiness of ./node_modules/@b00dea/cockpit/bin/cockpit.mjs doctor --config cockpit.toml --json
has been cleared or reported to the human.
- Before the first
up, run./node_modules/@b00dea/cockpit/bin/cockpit.mjs runtime measure --config cockpit.toml --image <local-image> --json. It measures the local daemonupwill use, can run for minutes with no progress output, records the result for this machine only and leavescockpit.tomlunchanged, so go straight on toup. The guide's Chapter 2 says which runtimes are recognised. - Daily:
./node_modules/@b00dea/cockpit/bin/cockpit.mjs session --config cockpit.toml -- <agent command>../node_modules/@b00dea/cockpit/bin/cockpit.mjs sleep --config cockpit.tomlreleases this checkout's hold../node_modules/@b00dea/cockpit/bin/cockpit.mjs down --config cockpit.tomlremoves its containers, keeping data volumes, from the local Docker daemon fixed at the start of the run. - Upgrade:
./node_modules/@b00dea/cockpit/bin/cockpit.mjs upgrade --config cockpit.tomldoes the move (--dry-runpreviews). By hand, install the new version, then run./node_modules/@b00dea/cockpit/bin/cockpit.mjs check --config cockpit.toml,./node_modules/@b00dea/cockpit/bin/cockpit.mjs sync --config cockpit.toml --dry-runand./node_modules/@b00dea/cockpit/bin/cockpit.mjs sync --config cockpit.toml. The guard trusts only the cockpit, Node andcockpit.tomlit was generated for, so after an upgrade, a Node switch or acockpit.tomledit it holds tool calls until the human runs./node_modules/@b00dea/cockpit/bin/cockpit.mjs sync --config cockpit.tomlin a terminal. Guide: Upgrade cockpit.
Shipped procedure
These sections are the procedure cockpit installs into every cockpit it bootstraps, copied here by its reference generator so this skill and the installed one cannot disagree.
Bootstrap
init reads the repositories, interviews, writes the generated files and checks the environment;
follow what it reports rather than redoing any of that by hand. Rerunning the same command, with
the same root and --target, resumes where it stopped; a different target refuses with
INIT_TARGET_CHANGED, and a repository or draft that changed underneath it refuses with a code
such as INIT_STATE_STALE or INIT_DRAFT_CHANGED whose fix says what to restore or redo. Inside an
installed cockpit the guard asks before any init that carries --answers or an --accept- flag.
Until step 7 installs cockpit in the cockpit root, rerun init with the same executable that
started it, even where it lives outside this root.
- Choose the agent tools. Ask the person which agent tools the team uses:
claudecode(Claude Code),codexcli(Codex CLI),opencode(OpenCode),cursor(Cursor) orgrokcli(Grok Build). One tool is a complete choice; for several, pass them all, yours first and comma-separated (--target claudecode,opencode); the list needs at least one ofclaudecode,codexcliandopencode, the tools cockpit can guard. init writes it as[surfaces] tools, and sync writes instructions, skills and settings for those tools only. Cursor and Grok Build get files nobody has tested them loading (see./node_modules/@b00dea/cockpit/docs/capability-matrix.md), so propose them only when the team uses them. Done when you hold the--targetvalue. - Preview. Run
./node_modules/@b00dea/cockpit/bin/cockpit.mjs init . --target <tool> --json, adding--registryonly when adopting an existing registry. The preview writes nothing. Readresult.stage,result.questionandresult.interview.outstanding: every field the interview will ask, each with itsproposals(each withprovenance.kindderived,measuredorinferred, and the file it came from) andconfirmedBy. Done when you holdresult.previewSha256and the outstanding fields. - Explore, then ask in one small round. Read the repositories for each outstanding field
before asking, ask only for what the files and CLI output cannot answer. A field with
confirmedBy = "agent"is yours to accept as read (step 4); present every other proposal with its source for confirmation. Always settle these with the person:- The name.
initproposes the cockpit root's directory name forcockpit.name. It scopes the cockpit's Compose projects, state and generated files, so changing it after the first sync means following the Rename a cockpit section of./node_modules/@b00dea/cockpit/docs/getting-started.md(down, edit the name,sync,check). - The root placement, when init runs inside a product repository (a git checkout with a root
language manifest, Dockerfile or standard Compose file) and the preview carries
result.cockpitRoot: a question, its options and a recommended answer. Relay that question to the human, explaining the trade-off in a sentence or two from the root placement choices in./node_modules/@b00dea/cockpit/docs/concepts.md, and write their answer under thecockpit.rootkey:dedicatedcreates a sibling<repo>-cockpitdirectory so generated files stay out of the product's history;in-repois the default when accepting without an answer, except for a directory name that is not a valid sibling slug, which refuses withINIT_COCKPIT_ROOT_REQUIRED. - The test gates. For a runnable product,
initproposestestingstages and gates from the test entry points it finds. Whether each proves anything is your judgement, made on evidence: name the behaviours its tests exercise, break one of them on purpose, run the proposed command and see it go red, then restore the file so the checkout is as you found it. That edit needs no yes, because it is undone within the step. Write the behaviours into the gate'schangestext and keep the red run's output for your report; a gate that stays green on the break proves nothing about that behaviour, so say so. The person confirms which gate agents iterate with and which they run before handing back. A new product with no tests needs the person to choose its test runner first; adopting a test framework in a product repository waits for their explicit yes. Answertesting = "none"only when they decide there are no tests yet;doctorthen reportsTESTING_GATE_UNDECLARED. - The non-local hosts for
guards: the database and live vendor API hosts of every production, staging or shared environment. Env templates give variable names only; each host comes from the person. - How grading runs for
work.grading. Offer the person the choices in the How grading can run section of./node_modules/@b00dea/cockpit/docs/work-and-browser.md, with init's proposal and its reason:independentwith two or more listed tools onPATH, so each grades the other's work;independentas a separate run with one, with a warning where the running tool is detected;checkswith none. The grader is optional:offis reasonable when tracking matters but grading is not wanted. A tool without subagents, or a sandbox that blocks a nested CLI, changes the path and not the rule: list another tool, or let the person choosechecks,selforoff, and never pick something weaker yourself without marking it. - How much the agent decides. Offer the person the three columns of the table in Who
decides in
./node_modules/@b00dea/cockpit/docs/safety-and-autonomy.md: the shipped defaults, a stricter setting, or the Fully agentic setup, which hands every process gate to the agent and keeps every guardrail. The[autonomy]and[work.gates]fields are theirs to write: never write or loosen one yourself. - Environment access. Inspect filenames and declared scripts without opening plaintext
dotenv or credential files. If a repository has dotenv files or templates, follow Secret
handling even when
.env.schemais absent. Reuse an existing Varlock setup; otherwise recommend adopting it and record the decision, scope and any deferred migration in the work log. Existing explicit authorization to adopt Varlock covers its reviewed dependency, schema and command changes; ask only for missing scope or provider access. Done when every outstanding field has the person's answer, a value they confirmed, or a default you chose and will mark.
- The name.
- Write the answers file, TOML keyed by field. Being told to "use sensible defaults" or
"proceed without asking" covers interview answers only. Mark every answer you chose yourself in
the file's
[provenance]table, for example"environment.machine" = "agent-default": init then writes the field underunconfirmedincockpit.tomlwith a comment saying the setup agent chose it, anddoctorreportsDECLARATION_UNCONFIRMEDuntil it is confirmed (step 7). Mark a field withconfirmedBy = "agent"as"derived"instead, with no value needed: init answers it with what it read, refuses one that differs (DOCUMENT_CONFIGURATION_ANSWER_NOT_DERIVED), and records the file it came from. An unmarked answer is recorded as the person's, except a trust decision (sibling,environment.install_policies,environment.posture,testing,guards,work.grading): the file cannot show a person made it, so init writes it underunconfirmedwhatever the file says, and the stronger default holds until a person confirms it (step 7). Done when the file holds every answer and marks each one you chose. - Accept. Show the person the answers file and the preview digest, then rerun with
--accept-preview <previewSha256> --answers <file>. The run stops atconfiguration.defaults: once the person has read the values the draft inresult.question.documentlists under "A person confirms these" (the digest covers only those), rerun adding--accept-defaultswithresult.question.expectedSha256. Each digest binds consent to the bytes the person saw, so take it only from the latest pending run; any other is refused (INIT_PREVIEW_NOT_ACCEPTED,INIT_DEFAULTS_NOT_ACCEPTED). A different value for an answer already recorded refuses withINIT_ANSWER_CONFLICT;--reset-answer <field>previews clearing it. A person at a terminal can run--interactiveinstead and type each digest; an agent session has no terminal, so there it refuses withINIT_TERMINAL_REQUIRED. Done when the run has passedconfiguration.defaults. - Work through the expected stops, rerunning the same accepted command after each:
- Where a runtime is declared, preflight needs a completed first bring-up, so the run stops with
STATE_UNSEEDED(exit 2, stagedraft-observed); the diagnostics beside it name every other gap found without a running stack. Bring the stack up as step 7 of Create a local setup describes. - Preflight passes only once the cockpit repository is committed and clean, so a new one reports
GIT_STATE_UNHEALTHYwith the commands that commit the generated files. A person approves or runs the staging and the commit, not you: the guard asks ongit add <paths>, denies a broadgit add -Athat covers a secrets directory, and the first commit stages the guard's own files. Show themgit status --shortand hand them that fix to run in a terminal. To read Git state in another directory, usegit -C <dir> statusorcd ./<dir> && <command>; a barecd <dir>is refused. Done when the result reportsenvironment-verified, or, for a cockpit that declares no runtime, reportssurfaces-verifiedwithENVIRONMENT_NOT_DECLAREDas information and no bring-up. That stage verifies the surfaces only: step 7'sdoctoris what reports its env schemas.
- Where a runtime is declared, preflight needs a completed first bring-up, so the run stops with
- Clear the readiness gaps. Every
initstop, and./node_modules/@b00dea/cockpit/bin/cockpit.mjs doctor --config cockpit.toml --json, carriesresult.readiness:gapslists each prerequisite a check reported missing, with itslevel(arequiredone is refused by the command that needs it),needs(why cockpit needs it) andfindings(the diagnostic, its message and its fix);noFindinglists the ones no check reported, which is not proof, because a check that could not run reports nothing. Take the gaps one at a time, required first: say what is missing, why cockpit needs it, and the exact change you propose. A change to a product repository follows step 8: committing, installing cockpit, recording a remote, untracking a file or adding a test changes it for everyone who works on it. Whether the existing tests prove anything is yours to judge, as step 3 describes; where a gap needs the person's judgement (which test runner to adopt, where characterization tests for untested code should live), propose with what you read and let them decide.- The
cockpit-installedgap clears first:initran from a temporary copy, so runnpm installin the cockpit root, then ask the person to run./node_modules/@b00dea/cockpit/bin/cockpit.mjs sync --config cockpit.tomlin a terminal so the guard hook runs the installed copy. - If anyone will run Codex in this cockpit, a person must trust its guard hook on each machine,
and again whenever sync changes the hook: Codex silently skips a project hook nobody has
trusted, so every tool call would run unguarded. An agent cannot give that trust. Ask the
person to run
codex -C <cockpit root>in a terminal (notcodex exec), trust the folder if asked, and choose Trust all and continue when Codex shows Hooks need review.doctorreportsCODEX_HOOK_UNTRUSTEDuntil it is done. DECLARATION_UNCONFIRMEDlists the answers no person stated. Confirmports.bases(with the stack up),environment.compose_filesandenvironment.machineby observation, one at a time:./node_modules/@b00dea/cockpit/bin/cockpit.mjs confirm ports.bases --config cockpit.toml --jsonruns the observation that verifies the answer and, when it passes, removes the entry and records what ran. Then run./node_modules/@b00dea/cockpit/bin/cockpit.mjs sync --config cockpit.tomlwhere[autonomy] sync = "agent", or hand it to the person, before confirming the next one. A refusal (CONFIRM_OBSERVATION_FAILED) names what the observation saw: fix that, or the value, and confirm again. Never delete anunconfirmedentry by hand:CONFIRM_PERSON_REQUIREDmarks the answers only a person confirms (the trust decisions,work.gradingamong them,cockpit.name,estate.runnable,environment.test_data), so list them in your report with their values and tell the person to confirm each: delete its entry, then run./node_modules/@b00dea/cockpit/bin/cockpit.mjs sync --config cockpit.toml --interactivein a terminal outside the agent. Until then grading runs asindependentand the guard admits no install policy's commands. Where[autonomy] confirm_answers = "agent", confirmcockpit.name,estate.runnableandenvironment.test_datayourself instead, as in./node_modules/@b00dea/cockpit/bin/cockpit.mjs confirm cockpit.name --config cockpit.toml --json; the record says you decided them. Done whendoctorreports no required gap and every other gap is cleared or reported. Report four things separately, because none implies another: configuration generated (checkpasses), machine ready (doctor, run where it can read this machine, has no required gap), hooks enforced (a person trusted the hook from the checkout the tool loads it from, soCODEX_HOOK_UNTRUSTEDandCODEX_HOOK_SOURCE_MISMATCHare clear) and integrations proven live (the stack or provider was actually exercised, which no passing check shows).
- The
- Put product changes where the person reviews them. A Dockerfile, Compose file or
.env.schemathe product needs goes on a new branch in that sibling's checkout: start the branch only whengit -C <sibling> status --shortprints nothing, write the files there, and put their diff against the starting branch in your report. Nothing is pushed, so the person reviews it before it reaches anyone else. Creating a hosted repository or a remote waits for their yes. Every other product change (an AGENTS.md pointer, apackage.json, a new test framework) needs explicit product-change authorization covering its reviewed scope. Reuse that authorization when already given; ask for uncovered changes. Choosing interview defaults alone does not authorize product changes.- For a dedicated cockpit, offer an instruction pointer for each product repository. If the
product has no AGENTS.md, show the exact proposed file as a draft; if it has one, show the
marked block that would be appended without changing the team's text. After approval, set
instruction_pointer = trueon that sibling's table incockpit.toml; the guard then holds every guarded call until a person runs./node_modules/@b00dea/cockpit/bin/cockpit.mjs sync --config cockpit.tomlin a terminal. Then continue from step 4 of Add or remove a repository at itssetupcommand. An in-repository cockpit already uses the root guide and must not point it at itself. - After accepted initialization, and only with explicit permission to change the product's
fixtures or auth setup, read
references/test-data-and-personas.mdbeside the cockpit-setup skill and treat it as a separate product change. Bootstrap does not discover provider identities or create browser state. - For environment or secret adoption, follow Secret handling after sync has established its owned ignore boundary. Done when each product file is on its branch with its diff in your report, and each other offer is applied or declined.
- For a dedicated cockpit, offer an instruction pointer for each product repository. If the
product has no AGENTS.md, show the exact proposed file as a draft; if it has one, show the
marked block that would be appended without changing the team's text. After approval, set
Report the actual result; every gap still named; every default you chose, with its field and value, so the person can confirm or replace each; your judgement of each test gate, with its red run; and the diff of every product branch.
Create a local setup
Use this when a repository has no local setup: it has only ever run in CI, staging or a cluster, so there is no Dockerfile, Compose file or documented way to start it on a laptop. Cockpit cannot read a setup that does not exist, and a setup it guessed would look complete while holding guesses. So derive each value from what the repository shows, record it as inferred, and let the human confirm it.
- Read what the repository already states, without running or changing anything: the manifests and
lockfiles for the runtime and entrypoint, CI workflows for the services they start, deployment
files for the ports and variable names they inject, and the code for its health endpoint.
The init preview from Bootstrap already proposes several of these under
interview.outstanding; reuse them rather than re-deriving. Done when you hold a list of entrypoint and runtime, ports, environment variable names, backing services with images, and a health endpoint, each with the file it came from. - Record variable names only. Values belong to whoever owns the secret; see Secret handling. Done when no value from an env file, manifest or workflow appears in your notes or output.
- Mark every derived value as
inferredwith its source file and the reason you read it from there. Show the human the whole list and ask them to confirm or correct it. Done when the human has answered for every inferred value; confirm one only on their word. - Turn each unknown into a named gap instead of a value: an undecided decision for data, mounts,
ports and restore, and an explicit vendor posture for every third-party endpoint. Cockpit renders
a subject with no decision as undecided, which keeps the gap visible. Done when each unknown is
named with who can resolve it, and nothing in the declaration was filled in to make it load.
Answer
environment.test_datawith exact booleans forseeded_dataandsigned_in_users. A false answer is retained as a not-declared decision. A true answer is only a requirement: it remains unresolved until product-owned seed operations or browser authentication states are declared, and never proves that data or a login exists. - Decide where the runnable pieces live. A Dockerfile or Compose file in the product is a product
change: write it on a branch in that repository's checkout, as step 8 of Bootstrap describes.
A
compose.ymlat the cockpit root that reaches the checkout through its sibling variable leaves the product untouched. Done when each product file is on its branch with its diff in your report, or no product file was written. - Finish the configuration with the init flow in Bootstrap. On an existing cockpit, an edit to
cockpit.tomlmakes the guard hold every guarded call until it is synced. When the hold says the edit does not widen what agents may do, run./node_modules/@b00dea/cockpit/bin/cockpit.mjs sync --config cockpit.tomlyourself where[autonomy] sync = "agent"; when it names fields that widen, a person runs it in a terminal. Then run./node_modules/@b00dea/cockpit/bin/cockpit.mjs check --config cockpit.toml --json. Done when the check exits 0. - Where a runtime is declared, measure it with
./node_modules/@b00dea/cockpit/bin/cockpit.mjs runtime measure --config cockpit.toml --image <local-image>, using an image already on this machine because the probe never pulls; with none, ask the person which to use. It measures the local daemonupwill use (the contextDOCKER_CONTEXTnames, or else the active one), can run for minutes without output, records the result for this machine only and leavescockpit.tomlunchanged, so nosyncis needed. When Docker is missing or not running, it anduprefuse withRUNTIME_UNAVAILABLE: ask the person to start or install it. Then start the stack with./node_modules/@b00dea/cockpit/bin/cockpit.mjs up --config cockpit.toml. Report the actual result. Done when the stack reports healthy, or you have named what stopped it.
Secret handling
During adoption, inspect environment filenames and manifest commands before choosing a secret-access
path. A missing .env.schema is a decision to resolve, not a reason to skip this section. Recommend
Varlock when plaintext dotenv files or templates exist; record adoption or the reason it is deferred.
Read variable names with ./node_modules/@b00dea/cockpit/bin/cockpit.mjs env keys --config cockpit.toml, never resolve values into
the agent's context. When you need a schema's text, use a reference printed by env keys and run
./node_modules/@b00dea/cockpit/bin/cockpit.mjs env schema --config cockpit.toml --path <reference>; a schema must
hold no secret values. Native rules may refuse direct reads of these files, so do not work around a
refusal. To change a schema, write a draft with your normal tools, as a plain file away from
environment files and secrets, then run
./node_modules/@b00dea/cockpit/bin/cockpit.mjs env schema --config cockpit.toml --path <reference> --replace-from <draft>
on its own. Claude Code's native rules refuse Edit and Write of this name (measured on 2.1.318 on
2026-11-05). The result is not validated until it is committed, and ENV_SCHEMA_UNCOMMITTED says so;
committing is the guarded checkpoint. A person's terminal has no such limit.
Keep the tracked product .env.schema beside the component that owns it. Store only encrypted
Varlock resolver expressions or external-provider references under
env/.secrets/<cockpit-project>/<component>; the generated ignore block in the cockpit's .gitignore
must be current, the directory mode 0700, and resolver files mode 0600 before use. Ignoring, encryption and redaction
do not prevent same-user code from reading a resolved value. The agent receives schema and redacted
status, never a plaintext source. ./node_modules/@b00dea/cockpit/bin/cockpit.mjs doctor --config cockpit.toml and preflight run varlock load, which runs a
schema's resolvers, including an exec() command, with the caller's environment, and the guard does
not deny editing a schema. Declared testing commands also run edited code, and cockpit is not a
sandbox. Tell the person to review schema changes as they review code, and to run doctor with a
provider sign-in only on schemas they trust. This was reasoned from Varlock's documented resolver
behaviour plus a failing exec() measured with a synthetic schema.
Reuse the product's declared command or script. Resolve both paths to absolute paths from their owning
roots so the command is independent of its working directory; repeated Varlock paths are applied in
order, so the later central path takes precedence. For status the locked executable is invoked as
varlock load --path <absolute-component-schema-root> --path
<absolute-cockpit-root>/env/.secrets/<cockpit-project>/<component> --agent --format json-full
--summary-stderr. For a trusted product process it is invoked as varlock run --path
<absolute-component-schema-root> --path <absolute-cockpit-root>/env/.secrets/<cockpit-project>/<component>
--inject vars --redact-stdout -- <exact command>, inside the declared command whose output is piped:
Varlock refuses that flag on an interactive terminal, so a person in a terminal runs the same run
without it. The angle brackets describe product-resolved inputs, not literal commands. Resolve the executable and version
from the product manifest and lock; runtime commands never fetch with npx. If the product has not
adopted Varlock, adding and locking it needs product-change authorization; reuse explicit authorization
already given for this adoption rather than asking again. varlock init,
provider login, encryption and secret migration stay with a person; preview their file and
provider scope instead of running them automatically. Warn them that Varlock evaluates env files, so
a copied value holding $(...) runs a command on load, even in double quotes: they single-quote each
migrated value, as ./node_modules/@b00dea/cockpit/docs/environment.md describes.
Set VARLOCK_TELEMETRY_DISABLED=true in each declared Varlock command's environment, including
status and trusted product processes. Cockpit sets it for its own schema probes. This disables
Varlock telemetry without changing the person's global configuration; output redaction is a
separate setting and remains required in every command an agent runs.
Preflight and doctor already check every committed .env.schema a sibling tracks, a sibling's root
schema and the cockpit root's own, with the central path when it exists; a failing or unavailable row names the
keys. An unavailable row can mean a secret provider is signed out or unreachable: a person signs in
and reruns. To diagnose, a person runs VARLOCK_TELEMETRY_DISABLED=true varlock load --path
<schema-directory> --path <central-directory>. Agents use cockpit preflight for key-only status, or
./node_modules/@b00dea/cockpit/bin/cockpit.mjs doctor --config cockpit.toml on a cockpit that declares no runtime, where preflight refuses; raw Varlock output is
not safe to read.
Treat Varlock output as secret-tainted even in agent mode: --redact-stdout does not cover Varlock's
own errors, which can print source lines and a failing resolver's command and stderr. Keep raw
diagnostics with the person and use cockpit's schema probes for failures you see. Report variable names, validation state,
exit status and provenance only. Never copy raw resolved values, stdout or stderr into work-order
records. Varlock's credential proxy is preview software and same-user code is not confined here;
report secure agent secret use as unavailable unless a sandbox that has been tested proves it.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

