agentleFS
b0deab0dea/cockpit/skills/adopt-cockpit/SKILL.md

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

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
  1. Very specific:

    Use this when a human asks you to set cockpit up, adopt it, or bring their product up for agents.

    line 10
  2. Distinctive:

    Follow these rules throughout.

    line 26
  3. Very specific:

    Ask the human before creating a Git remote or hosted repository, running a destructive command (reset, approving removals), running sync …

    line 29
  4. Very specific:

    Ask the human for the database and live vendor API hosts of every non-local environment (production, staging, shared) for the guards answer.

    line 41
  5. Very specific:

    Every trust answer the answers file supplies (sibling, environment.install_policies, environment.posture, testing, guards, work.grading) …

    line 49
  6. Very specific:

    Follow *Install cockpit* in docs/getting-started.md, from the same sources as the guide above: an exact dev dependency of the repository, …

    line 60
  7. Distinctive:

    Verify without permitting an implicit download:

    line 65
  8. Very specific:

    Every init below takes --target <tool>: replace <tool> with the target of the agent tool you are running in.

    line 71
  9. Very specific:

    Run every command from the cockpit root through ./node_modules/@b00dea/cockpit/bin/cockpit.mjs.

    line 75
  10. Distinctive:

    Look at the directory before asking.

    line 86
  11. Very specific:

    Choose the agent tools: Ask the person which agent tools the team uses: claudecode (Claude Code), codexcli (Codex CLI), opencode …

    line 141
  12. Very specific:

    Preview: Run ./node_modules/@b00dea/cockpit/bin/cockpit.mjs init .

    line 150
  13. Very specific:

    Explore, then ask in one small round: Read the repositories for each outstanding field before asking, ask only for what the files and CLI …

    line 156
  14. Very specific:

    Clear the readiness gaps: Every init stop, and ./node_modules/@b00dea/cockpit/bin/cockpit.mjs doctor --config cockpit.toml --json, carries …

    line 246
  15. Very specific:

    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: …

    line 262
  16. Very specific:

    After accepted initialization, and only with explicit permission to change the product's fixtures or auth setup, read …

    line 306
  17. Distinctive:

    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 …

    line 321
  18. Distinctive:

    Read what the repository already states, without running or changing anything: the manifests and lockfiles for the runtime and entrypoint, …

    line 326
  19. Very specific:

    Read variable names with ./node_modules/@b00dea/cockpit/bin/cockpit.mjs env keys --config cockpit.toml, never resolve values into the …

    line 371
  20. Very specific:

    Keep the tracked product .env.schema beside the component that owns it.

    line 382
  21. Very specific:

    Treat Varlock output as secret-tainted even in agent mode: --redact-stdout does not cover Varlock's own errors, which can print source …

    line 425

≈ “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.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md
<!-- 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:

  1. Ask the human before creating a Git remote or hosted repository, running a destructive command (reset, approving removals), running sync --adopt, accepting an init digest, or adopting a test framework or dependency outside already authorized product-change scope. A Dockerfile, Compose file or .env.schema the 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.
  2. Show the exact preview first: the sync --dry-run listing, the init preview and its previewSha256, the answers file, or the defaults digest. Consent binds to those bytes.
  3. 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.
  4. Accept as read only a field init marks confirmedBy = "agent" (a derived proposal), by marking it "derived". Show every other proposal with the file it came from; it becomes an answer only on the human's word.
  5. Ask the human for the database and live vendor API hosts of every non-local environment (production, staging, shared) for the guards answer; env templates give variable names only, and once a cockpit exists ./node_modules/@b00dea/cockpit/bin/cockpit.mjs env keys --config cockpit.toml lists them.
  6. Offer the human work.grading as a real choice with init's proposal and reason: the grader is optional, and off is reasonable when tracking matters but grading is not wanted.
  7. "Use sensible defaults" covers init answers only, never another change inside a product repository: an AGENTS.md pointer or a package.json change 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.
  8. Every trust answer the answers file supplies (sibling, environment.install_policies, environment.posture, testing, guards, work.grading) lands under unconfirmed whatever 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 from unconfirmed, then run ./node_modules/@b00dea/cockpit/bin/cockpit.mjs sync --config cockpit.toml --interactive in 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.

  1. 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.
  2. 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.
  3. Verify without permitting an implicit download:

    ./node_modules/@b00dea/cockpit/bin/cockpit.mjs --help
  4. Every init below 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 diskDoGuide 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 decisionsFollow 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 servicesFrom 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 diskMoving 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 fileAnswer 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 setupFollow Create a local setup below.Other situations
Committed .claude/settings.json, .codex/config.toml or .codex/hooks.jsonsync 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 cockpitRun ./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.schemaFollow 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 daemon up will use, can run for minutes with no progress output, records the result for this machine only and leaves cockpit.toml unchanged, so go straight on to up. 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.toml releases this checkout's hold. ./node_modules/@b00dea/cockpit/bin/cockpit.mjs down --config cockpit.toml removes 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.toml does the move (--dry-run previews). 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-run and ./node_modules/@b00dea/cockpit/bin/cockpit.mjs sync --config cockpit.toml. The guard trusts only the cockpit, Node and cockpit.toml it was generated for, so after an upgrade, a Node switch or a cockpit.toml edit it holds tool calls until the human runs ./node_modules/@b00dea/cockpit/bin/cockpit.mjs sync --config cockpit.toml in 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.

  1. Choose the agent tools. Ask the person which agent tools the team uses: claudecode (Claude Code), codexcli (Codex CLI), opencode (OpenCode), cursor (Cursor) or grokcli (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 of claudecode, codexcli and opencode, 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 --target value.
  2. Preview. Run ./node_modules/@b00dea/cockpit/bin/cockpit.mjs init . --target <tool> --json, adding --registry only when adopting an existing registry. The preview writes nothing. Read result.stage, result.question and result.interview.outstanding: every field the interview will ask, each with its proposals (each with provenance.kind derived, measured or inferred, and the file it came from) and confirmedBy. Done when you hold result.previewSha256 and the outstanding fields.
  3. 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. init proposes the cockpit root's directory name for cockpit.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 the cockpit.root key: dedicated creates a sibling <repo>-cockpit directory so generated files stay out of the product's history; in-repo is the default when accepting without an answer, except for a directory name that is not a valid sibling slug, which refuses with INIT_COCKPIT_ROOT_REQUIRED.
    • The test gates. For a runnable product, init proposes testing stages 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's changes text 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. Answer testing = "none" only when they decide there are no tests yet; doctor then reports TESTING_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: independent with two or more listed tools on PATH, so each grades the other's work; independent as a separate run with one, with a warning where the running tool is detected; checks with none. The grader is optional: off is 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 choose checks, self or off, 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.schema is 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.
  4. 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 under unconfirmed in cockpit.toml with a comment saying the setup agent chose it, and doctor reports DECLARATION_UNCONFIRMED until it is confirmed (step 7). Mark a field with confirmedBy = "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 under unconfirmed whatever 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.
  5. Accept. Show the person the answers file and the preview digest, then rerun with --accept-preview <previewSha256> --answers <file>. The run stops at configuration.defaults: once the person has read the values the draft in result.question.document lists under "A person confirms these" (the digest covers only those), rerun adding --accept-defaults with result.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 with INIT_ANSWER_CONFLICT; --reset-answer <field> previews clearing it. A person at a terminal can run --interactive instead and type each digest; an agent session has no terminal, so there it refuses with INIT_TERMINAL_REQUIRED. Done when the run has passed configuration.defaults.
  6. 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, stage draft-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_UNHEALTHY with the commands that commit the generated files. A person approves or runs the staging and the commit, not you: the guard asks on git add <paths>, denies a broad git add -A that covers a secrets directory, and the first commit stages the guard's own files. Show them git status --short and hand them that fix to run in a terminal. To read Git state in another directory, use git -C <dir> status or cd ./<dir> && <command>; a bare cd <dir> is refused. Done when the result reports environment-verified, or, for a cockpit that declares no runtime, reports surfaces-verified with ENVIRONMENT_NOT_DECLARED as information and no bring-up. That stage verifies the surfaces only: step 7's doctor is what reports its env schemas.
  7. Clear the readiness gaps. Every init stop, and ./node_modules/@b00dea/cockpit/bin/cockpit.mjs doctor --config cockpit.toml --json, carries result.readiness: gaps lists each prerequisite a check reported missing, with its level (a required one is refused by the command that needs it), needs (why cockpit needs it) and findings (the diagnostic, its message and its fix); noFinding lists 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-installed gap clears first: init ran from a temporary copy, so run npm install in the cockpit root, then ask the person to run ./node_modules/@b00dea/cockpit/bin/cockpit.mjs sync --config cockpit.toml in 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 (not codex exec), trust the folder if asked, and choose Trust all and continue when Codex shows Hooks need review. doctor reports CODEX_HOOK_UNTRUSTED until it is done.
    • DECLARATION_UNCONFIRMED lists the answers no person stated. Confirm ports.bases (with the stack up), environment.compose_files and environment.machine by observation, one at a time: ./node_modules/@b00dea/cockpit/bin/cockpit.mjs confirm ports.bases --config cockpit.toml --json runs 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.toml where [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 an unconfirmed entry by hand: CONFIRM_PERSON_REQUIRED marks the answers only a person confirms (the trust decisions, work.grading among 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 --interactive in a terminal outside the agent. Until then grading runs as independent and the guard admits no install policy's commands. Where [autonomy] confirm_answers = "agent", confirm cockpit.name, estate.runnable and environment.test_data yourself instead, as in ./node_modules/@b00dea/cockpit/bin/cockpit.mjs confirm cockpit.name --config cockpit.toml --json; the record says you decided them. Done when doctor reports no required gap and every other gap is cleared or reported. Report four things separately, because none implies another: configuration generated (check passes), 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, so CODEX_HOOK_UNTRUSTED and CODEX_HOOK_SOURCE_MISMATCH are clear) and integrations proven live (the stack or provider was actually exercised, which no passing check shows).
  8. Put product changes where the person reviews them. A Dockerfile, Compose file or .env.schema the product needs goes on a new branch in that sibling's checkout: start the branch only when git -C <sibling> status --short prints 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, a package.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 = true on that sibling's table in cockpit.toml; the guard then holds every guarded call until a person runs ./node_modules/@b00dea/cockpit/bin/cockpit.mjs sync --config cockpit.toml in a terminal. Then continue from step 4 of Add or remove a repository at its setup command. 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.md beside 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.

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.

  1. 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.
  2. 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.
  3. Mark every derived value as inferred with 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.
  4. 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_data with exact booleans for seeded_data and signed_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.
  5. 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.yml at 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.
  6. Finish the configuration with the init flow in Bootstrap. On an existing cockpit, an edit to cockpit.toml makes 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.toml yourself 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.
  7. 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 daemon up will use (the context DOCKER_CONTEXT names, or else the active one), can run for minutes without output, records the result for this machine only and leaves cockpit.toml unchanged, so no sync is needed. When Docker is missing or not running, it and up refuse with RUNTIME_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.

Download now (ZIP)

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
What did you use it for? e.g. Reviewing pull requests in a Rails app

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.