@b00dea/cockpit 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +375 -0
- package/LICENSE +21 -0
- package/README.md +22 -2
- package/bin/cockpit.mjs +33 -0
- package/cockpit.schema.json +2574 -0
- package/dist/autonomy.d.ts +44 -0
- package/dist/autonomy.js +156 -0
- package/dist/bounded-read.d.ts +14 -0
- package/dist/bounded-read.js +42 -0
- package/dist/browser/commands.d.ts +62 -0
- package/dist/browser/commands.js +349 -0
- package/dist/browser/package-paths.d.ts +1 -0
- package/dist/browser/package-paths.js +6 -0
- package/dist/browser/proxy.d.ts +22 -0
- package/dist/browser/proxy.js +37 -0
- package/dist/browser/runtime.d.ts +117 -0
- package/dist/browser/runtime.js +183 -0
- package/dist/browser/surfaces.d.ts +141 -0
- package/dist/browser/surfaces.js +556 -0
- package/dist/browser/ui-gate.d.ts +15 -0
- package/dist/browser/ui-gate.js +18 -0
- package/dist/cli-guard.d.ts +5 -0
- package/dist/cli-guard.js +71 -0
- package/dist/cli-main.d.ts +139 -0
- package/dist/cli-main.js +1405 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +16 -0
- package/dist/command-table.d.ts +113 -0
- package/dist/command-table.js +512 -0
- package/dist/config/load.d.ts +171 -0
- package/dist/config/load.js +345 -0
- package/dist/config/sibling-toml.d.ts +48 -0
- package/dist/config/sibling-toml.js +160 -0
- package/dist/config/surface-tools-toml.d.ts +9 -0
- package/dist/config/surface-tools-toml.js +37 -0
- package/dist/config/verified-write.d.ts +43 -0
- package/dist/config/verified-write.js +89 -0
- package/dist/diagnostics.d.ts +26 -0
- package/dist/diagnostics.js +335 -0
- package/dist/emit.d.ts +22 -0
- package/dist/emit.js +43 -0
- package/dist/entrypoint-kinds.d.ts +3 -0
- package/dist/entrypoint-kinds.js +11 -0
- package/dist/environment/application/destructive.d.ts +6 -0
- package/dist/environment/application/destructive.js +425 -0
- package/dist/environment/application/doctor.d.ts +89 -0
- package/dist/environment/application/doctor.js +235 -0
- package/dist/environment/application/guard.d.ts +43 -0
- package/dist/environment/application/guard.js +622 -0
- package/dist/environment/application/health.d.ts +134 -0
- package/dist/environment/application/health.js +379 -0
- package/dist/environment/application/lifecycle-context.d.ts +228 -0
- package/dist/environment/application/lifecycle-context.js +154 -0
- package/dist/environment/application/lifecycle-state.d.ts +25 -0
- package/dist/environment/application/lifecycle-state.js +201 -0
- package/dist/environment/application/lifecycle.d.ts +17 -0
- package/dist/environment/application/lifecycle.js +729 -0
- package/dist/environment/application/logs.d.ts +45 -0
- package/dist/environment/application/logs.js +127 -0
- package/dist/environment/application/setup.d.ts +129 -0
- package/dist/environment/application/setup.js +741 -0
- package/dist/environment/application/shared.d.ts +11 -0
- package/dist/environment/application/shared.js +61 -0
- package/dist/environment/claims.d.ts +389 -0
- package/dist/environment/claims.js +1709 -0
- package/dist/environment/codex-hook-trust.d.ts +11 -0
- package/dist/environment/codex-hook-trust.js +185 -0
- package/dist/environment/compose-environment.d.ts +1 -0
- package/dist/environment/compose-environment.js +6 -0
- package/dist/environment/compose-ownership.d.ts +21 -0
- package/dist/environment/compose-ownership.js +117 -0
- package/dist/environment/compose-topology.d.ts +117 -0
- package/dist/environment/compose-topology.js +413 -0
- package/dist/environment/contract.d.ts +489 -0
- package/dist/environment/contract.js +761 -0
- package/dist/environment/declaration.d.ts +14 -0
- package/dist/environment/declaration.js +39 -0
- package/dist/environment/destructive-composition.d.ts +29 -0
- package/dist/environment/destructive-composition.js +333 -0
- package/dist/environment/docker-daemon.d.ts +30 -0
- package/dist/environment/docker-daemon.js +78 -0
- package/dist/environment/docker-endpoint.d.ts +10 -0
- package/dist/environment/docker-endpoint.js +19 -0
- package/dist/environment/env-schema-observation.d.ts +46 -0
- package/dist/environment/env-schema-observation.js +241 -0
- package/dist/environment/evidence.d.ts +136 -0
- package/dist/environment/evidence.js +437 -0
- package/dist/environment/executable.d.ts +26 -0
- package/dist/environment/executable.js +167 -0
- package/dist/environment/generated-application/authorities.d.ts +5 -0
- package/dist/environment/generated-application/authorities.js +61 -0
- package/dist/environment/generated-application/bootstrap-skill.d.ts +16 -0
- package/dist/environment/generated-application/bootstrap-skill.js +328 -0
- package/dist/environment/generated-application/check.d.ts +13 -0
- package/dist/environment/generated-application/check.js +189 -0
- package/dist/environment/generated-application/custom-surface.d.ts +26 -0
- package/dist/environment/generated-application/custom-surface.js +289 -0
- package/dist/environment/generated-application/prepare.d.ts +29 -0
- package/dist/environment/generated-application/prepare.js +276 -0
- package/dist/environment/generated-application/publication.d.ts +33 -0
- package/dist/environment/generated-application/publication.js +547 -0
- package/dist/environment/generated-application/shared.d.ts +484 -0
- package/dist/environment/generated-application/shared.js +349 -0
- package/dist/environment/generated-application/surface-observation.d.ts +4 -0
- package/dist/environment/generated-application/surface-observation.js +69 -0
- package/dist/environment/generated-application/surface-outputs.d.ts +71 -0
- package/dist/environment/generated-application/surface-outputs.js +389 -0
- package/dist/environment/generated-application/surfaces.d.ts +3 -0
- package/dist/environment/generated-application/surfaces.js +699 -0
- package/dist/environment/generated-application/sync.d.ts +6 -0
- package/dist/environment/generated-application/sync.js +109 -0
- package/dist/environment/git-observation.d.ts +183 -0
- package/dist/environment/git-observation.js +544 -0
- package/dist/environment/health-composition.d.ts +11 -0
- package/dist/environment/health-composition.js +628 -0
- package/dist/environment/host-observation.d.ts +56 -0
- package/dist/environment/host-observation.js +52 -0
- package/dist/environment/identity.d.ts +48 -0
- package/dist/environment/identity.js +85 -0
- package/dist/environment/init-application.d.ts +308 -0
- package/dist/environment/init-application.js +697 -0
- package/dist/environment/install-policy-observation.d.ts +71 -0
- package/dist/environment/install-policy-observation.js +284 -0
- package/dist/environment/install-policy.d.ts +48 -0
- package/dist/environment/install-policy.js +96 -0
- package/dist/environment/instance.d.ts +33 -0
- package/dist/environment/instance.js +122 -0
- package/dist/environment/instruction-pointer.d.ts +19 -0
- package/dist/environment/instruction-pointer.js +144 -0
- package/dist/environment/lifecycle-composition.d.ts +29 -0
- package/dist/environment/lifecycle-composition.js +675 -0
- package/dist/environment/lifecycle-stage.d.ts +115 -0
- package/dist/environment/lifecycle-stage.js +398 -0
- package/dist/environment/lifecycle.d.ts +75 -0
- package/dist/environment/lifecycle.js +354 -0
- package/dist/environment/logs.d.ts +132 -0
- package/dist/environment/logs.js +519 -0
- package/dist/environment/observations.d.ts +46 -0
- package/dist/environment/observations.js +344 -0
- package/dist/environment/operator-application.d.ts +50 -0
- package/dist/environment/operator-application.js +155 -0
- package/dist/environment/ports.d.ts +182 -0
- package/dist/environment/ports.js +1205 -0
- package/dist/environment/posture-observation.d.ts +68 -0
- package/dist/environment/posture-observation.js +253 -0
- package/dist/environment/read-composition.d.ts +27 -0
- package/dist/environment/read-composition.js +352 -0
- package/dist/environment/readiness-composition.d.ts +38 -0
- package/dist/environment/readiness-composition.js +130 -0
- package/dist/environment/reclaim.d.ts +333 -0
- package/dist/environment/reclaim.js +1835 -0
- package/dist/environment/repository-identity.d.ts +13 -0
- package/dist/environment/repository-identity.js +108 -0
- package/dist/environment/runtime-measurement-record.d.ts +38 -0
- package/dist/environment/runtime-measurement-record.js +111 -0
- package/dist/environment/runtime-measurement.d.ts +27 -0
- package/dist/environment/runtime-measurement.js +224 -0
- package/dist/environment/runtime-probe-residue.d.ts +43 -0
- package/dist/environment/runtime-probe-residue.js +148 -0
- package/dist/environment/runtime-probe.d.ts +72 -0
- package/dist/environment/runtime-probe.js +725 -0
- package/dist/environment/runtime.d.ts +505 -0
- package/dist/environment/runtime.js +2335 -0
- package/dist/environment/seed.d.ts +16 -0
- package/dist/environment/seed.js +43 -0
- package/dist/environment/selftest-application.d.ts +86 -0
- package/dist/environment/selftest-application.js +713 -0
- package/dist/environment/sensitive.d.ts +3 -0
- package/dist/environment/sensitive.js +48 -0
- package/dist/environment/setup-observation.d.ts +62 -0
- package/dist/environment/setup-observation.js +1473 -0
- package/dist/environment/setup.d.ts +43 -0
- package/dist/environment/setup.js +176 -0
- package/dist/environment/sibling-instructions.d.ts +33 -0
- package/dist/environment/sibling-instructions.js +224 -0
- package/dist/environment/sibling-registration.d.ts +45 -0
- package/dist/environment/sibling-registration.js +538 -0
- package/dist/environment/state.d.ts +371 -0
- package/dist/environment/state.js +2013 -0
- package/dist/environment/templates.d.ts +140 -0
- package/dist/environment/templates.js +685 -0
- package/dist/environment/tool-registration.d.ts +9 -0
- package/dist/environment/tool-registration.js +96 -0
- package/dist/environment/upgrade-application.d.ts +19 -0
- package/dist/environment/upgrade-application.js +175 -0
- package/dist/environment-exec/execute.d.ts +102 -0
- package/dist/environment-exec/execute.js +1175 -0
- package/dist/environment-exec/libexec-program.d.ts +6 -0
- package/dist/environment-exec/libexec-program.js +22 -0
- package/dist/environment-exec/verified-digest.d.ts +4 -0
- package/dist/environment-exec/verified-digest.js +16 -0
- package/dist/exact-keys.d.ts +7 -0
- package/dist/exact-keys.js +15 -0
- package/dist/fix-catalogue.d.ts +32 -0
- package/dist/fix-catalogue.js +60 -0
- package/dist/freshness.d.ts +29 -0
- package/dist/freshness.js +75 -0
- package/dist/generated-environment/adopt.d.ts +16 -0
- package/dist/generated-environment/adopt.js +275 -0
- package/dist/generated-environment/command.d.ts +47 -0
- package/dist/generated-environment/command.js +75 -0
- package/dist/generated-environment/transaction.d.ts +186 -0
- package/dist/generated-environment/transaction.js +1770 -0
- package/dist/grading/evaluate.d.ts +71 -0
- package/dist/grading/evaluate.js +403 -0
- package/dist/grading/grade.d.ts +33 -0
- package/dist/grading/grade.js +57 -0
- package/dist/guards/evaluator.d.ts +113 -0
- package/dist/guards/evaluator.js +1226 -0
- package/dist/guards/harness-adapter.d.ts +17 -0
- package/dist/guards/harness-adapter.js +57 -0
- package/dist/guards/host.d.ts +8 -0
- package/dist/guards/host.js +10 -0
- package/dist/guards/invocation-parser.d.ts +66 -0
- package/dist/guards/invocation-parser.js +595 -0
- package/dist/guards/local-identity.d.ts +40 -0
- package/dist/guards/local-identity.js +123 -0
- package/dist/guards/policy-pin.d.ts +13 -0
- package/dist/guards/policy-pin.js +175 -0
- package/dist/guards/protected-locations.d.ts +62 -0
- package/dist/guards/protected-locations.js +461 -0
- package/dist/guards/read-only.d.ts +37 -0
- package/dist/guards/read-only.js +315 -0
- package/dist/init/command.d.ts +40 -0
- package/dist/init/command.js +310 -0
- package/dist/init/derive.d.ts +51 -0
- package/dist/init/derive.js +715 -0
- package/dist/init/draft.d.ts +138 -0
- package/dist/init/draft.js +1205 -0
- package/dist/init/render.d.ts +35 -0
- package/dist/init/render.js +82 -0
- package/dist/init/scaffold.d.ts +53 -0
- package/dist/init/scaffold.js +121 -0
- package/dist/invocation.d.ts +13 -0
- package/dist/invocation.js +20 -0
- package/dist/package-metadata.d.ts +9 -0
- package/dist/package-metadata.js +19 -0
- package/dist/readiness.d.ts +53 -0
- package/dist/readiness.js +88 -0
- package/dist/references/named.d.ts +24 -0
- package/dist/references/named.js +27 -0
- package/dist/refusal.d.ts +15 -0
- package/dist/refusal.js +7 -0
- package/dist/registry-derivation.d.ts +31 -0
- package/dist/registry-derivation.js +32 -0
- package/dist/registry-resolve/command.d.ts +47 -0
- package/dist/registry-resolve/command.js +226 -0
- package/dist/registry-resolve/registry.d.ts +68 -0
- package/dist/registry-resolve/registry.js +292 -0
- package/dist/registry-resolve/render-shell.d.ts +18 -0
- package/dist/registry-resolve/render-shell.js +36 -0
- package/dist/repair.d.ts +29 -0
- package/dist/repair.js +8 -0
- package/dist/schema-json.d.ts +1 -0
- package/dist/schema-json.js +177 -0
- package/dist/schema.d.ts +1322 -0
- package/dist/schema.js +934 -0
- package/dist/setup/command.d.ts +4 -0
- package/dist/setup/command.js +4 -0
- package/dist/sha256.d.ts +1 -0
- package/dist/sha256.js +4 -0
- package/dist/surfaces/adoption.d.ts +41 -0
- package/dist/surfaces/adoption.js +217 -0
- package/dist/surfaces/consumer-instructions.d.ts +20 -0
- package/dist/surfaces/consumer-instructions.js +43 -0
- package/dist/surfaces/contract.d.ts +42 -0
- package/dist/surfaces/contract.js +169 -0
- package/dist/surfaces/core-declarations.d.ts +24 -0
- package/dist/surfaces/core-declarations.js +79 -0
- package/dist/surfaces/development-markers.d.ts +1 -0
- package/dist/surfaces/development-markers.js +18 -0
- package/dist/surfaces/generator-adapter.d.ts +71 -0
- package/dist/surfaces/generator-adapter.js +809 -0
- package/dist/surfaces/harness-registry.d.ts +180 -0
- package/dist/surfaces/harness-registry.js +117 -0
- package/dist/surfaces/mcp.d.ts +95 -0
- package/dist/surfaces/mcp.js +186 -0
- package/dist/surfaces/merge.d.ts +30 -0
- package/dist/surfaces/merge.js +105 -0
- package/dist/surfaces/ownership.d.ts +190 -0
- package/dist/surfaces/ownership.js +795 -0
- package/dist/surfaces/projection.d.ts +136 -0
- package/dist/surfaces/projection.js +681 -0
- package/dist/surfaces/render.d.ts +118 -0
- package/dist/surfaces/render.js +633 -0
- package/dist/surfaces/restrictions.d.ts +130 -0
- package/dist/surfaces/restrictions.js +447 -0
- package/dist/surfaces/selftest.d.ts +162 -0
- package/dist/surfaces/selftest.js +393 -0
- package/dist/surfaces/skill-contract.d.ts +85 -0
- package/dist/surfaces/skill-contract.js +449 -0
- package/dist/surfaces/sync.d.ts +57 -0
- package/dist/surfaces/sync.js +164 -0
- package/dist/team-metadata.d.ts +41 -0
- package/dist/team-metadata.js +512 -0
- package/dist/testing/gates.d.ts +91 -0
- package/dist/testing/gates.js +182 -0
- package/dist/testing/hooks.d.ts +59 -0
- package/dist/testing/hooks.js +139 -0
- package/dist/testing/verdict.d.ts +29 -0
- package/dist/testing/verdict.js +62 -0
- package/dist/work-orders/application.d.ts +99 -0
- package/dist/work-orders/application.js +383 -0
- package/dist/work-orders/composition.d.ts +124 -0
- package/dist/work-orders/composition.js +1010 -0
- package/dist/work-orders/contract.d.ts +61 -0
- package/dist/work-orders/contract.js +122 -0
- package/dist/work-orders/store.d.ts +158 -0
- package/dist/work-orders/store.js +197 -0
- package/docs/README.md +65 -0
- package/docs/architecture.md +136 -0
- package/docs/capability-matrix.md +50 -0
- package/docs/cli-reference.md +599 -0
- package/docs/command-list.md +51 -0
- package/docs/compose-patterns.md +99 -0
- package/docs/concepts.md +171 -0
- package/docs/configuration-essentials.md +172 -0
- package/docs/configuration-reference.md +621 -0
- package/docs/environment.md +760 -0
- package/docs/extending.md +43 -0
- package/docs/faq.md +111 -0
- package/docs/getting-started.md +608 -0
- package/docs/harness-surfaces.md +433 -0
- package/docs/joining-a-team.md +76 -0
- package/docs/release-policy.md +49 -0
- package/docs/safety-and-autonomy.md +419 -0
- package/docs/troubleshooting.md +361 -0
- package/docs/tutorial.md +170 -0
- package/docs/work-and-browser.md +254 -0
- package/libexec/browser-operation.cjs +186 -0
- package/libexec/fence-marker.cjs +101 -0
- package/libexec/fence-marker.d.cts +24 -0
- package/libexec/fenced-group-runner.cjs +77 -0
- package/libexec/fenced-supervisor.cjs +137 -0
- package/libexec/generated-filesystem.cjs +731 -0
- package/libexec/install-filesystem.cjs +225 -0
- package/libexec/rulesync-generator.NOTICE.md +1112 -0
- package/libexec/rulesync-generator.cjs +743 -0
- package/libexec/surface-generator-worker.cjs +266 -0
- package/libexec/surface-output-reader.cjs +99 -0
- package/libexec/surface-scratch-cleanup.cjs +14 -0
- package/libexec/validate-harness-evidence.d.mts +183 -0
- package/libexec/validate-harness-evidence.mjs +1312 -0
- package/package.json +74 -4
- package/surfaces/README.md +33 -0
- package/surfaces/agents/evaluator.agent.md +76 -0
- package/surfaces/guards/bash-guard.sh +48 -0
- package/surfaces/guards/claude.adapter.json +25 -0
- package/surfaces/guards/codex.adapter.json +24 -0
- package/surfaces/guards/opencode.adapter.json +25 -0
- package/surfaces/references/browser.md +63 -0
- package/surfaces/references/test-data-and-personas.md +84 -0
- package/surfaces/references/testing-tiers.md +11 -0
- package/surfaces/skills/cockpit-browser.skill.md +54 -0
- package/surfaces/skills/cockpit-explain.skill.md +32 -0
- package/surfaces/skills/cockpit-fix.skill.md +37 -0
- package/surfaces/skills/cockpit-setup.skill.md +39 -0
- package/surfaces/skills/cockpit-work.skill.md +34 -0
- package/surfaces/skills/collection.json +5 -0
- package/surfaces/skills/procedures/explain.md +61 -0
- package/surfaces/skills/procedures/fix.md +81 -0
- package/surfaces/skills/procedures/setup.md +379 -0
- package/surfaces/skills/procedures/work.md +105 -0
|
@@ -0,0 +1,608 @@
|
|
|
1
|
+
# Getting started
|
|
2
|
+
|
|
3
|
+
By the end of chapter 1, one repository has a reviewed `cockpit.toml`, every agent tool you listed
|
|
4
|
+
loads the same instructions and skills, the guard refuses a push to `main` in each of them (in Codex
|
|
5
|
+
once a person trusts its hook), and `cockpit check` fails the moment a generated file drifts. That
|
|
6
|
+
needs one repository, Node.js and Git; no Docker. Chapter 2 adds more repositories and a Compose
|
|
7
|
+
stack each agent can bring up on its own ports.
|
|
8
|
+
|
|
9
|
+
This guide is for developers and for the AI agents they ask to do the setup. To watch cockpit work on
|
|
10
|
+
a throwaway example first, follow the [tutorial](tutorial.md).
|
|
11
|
+
|
|
12
|
+
| Your situation | Go to |
|
|
13
|
+
|---|---|
|
|
14
|
+
| One repository, one agent tool, no Docker | [Chapter 1](#chapter-1-one-repository-one-tool-no-docker) |
|
|
15
|
+
| You want an agent to do the setup | [Set up with an agent](#set-up-with-an-agent) |
|
|
16
|
+
| Several repositories, or a stack to run | [Chapter 2](#chapter-2-several-repositories-and-a-compose-stack) |
|
|
17
|
+
| A setup you already run with scripts or a shell registry | [Adopt an existing setup](#adopt-an-existing-setup) |
|
|
18
|
+
| A teammate's cockpit you are joining | [Joining a team's cockpit](joining-a-team.md) |
|
|
19
|
+
|
|
20
|
+
## Chapter 1: one repository, one tool, no Docker
|
|
21
|
+
|
|
22
|
+
You need a Node.js release listed in the
|
|
23
|
+
[`engines` field in the package manifest](https://github.com/b0dea/cockpit/blob/main/packages/cockpit/package.json), Git, and macOS or
|
|
24
|
+
Linux. Commands that run a stack also need Docker Compose ([chapter 2](#chapter-2-several-repositories-and-a-compose-stack)).
|
|
25
|
+
|
|
26
|
+
### Install cockpit
|
|
27
|
+
|
|
28
|
+
Install cockpit as an exact dev dependency of the repository and start `init`:
|
|
29
|
+
|
|
30
|
+
```sh
|
|
31
|
+
npm install --save-dev --save-exact @b00dea/cockpit
|
|
32
|
+
npx --no cockpit init . --target claudecode
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Replace `claudecode` with `codexcli` or `opencode` for those tools, or list several, yours first
|
|
36
|
+
(`--target claudecode,opencode`). `init` records them as `[surfaces] tools` and installs the
|
|
37
|
+
`cockpit-setup` skill for each listed tool. The default tools are `claudecode`, `codexcli` and
|
|
38
|
+
`opencode`; `cursor` and `grokcli` are written only when listed, and nobody has confirmed they load
|
|
39
|
+
the files ([capability matrix](capability-matrix.md)). Change the list later with
|
|
40
|
+
`cockpit tool add|remove <tool>`.
|
|
41
|
+
|
|
42
|
+
A single product repository gets an in-repo cockpit: `cockpit.toml`, the instructions and the guard
|
|
43
|
+
live in the repository itself, with `siblings_root = "."`. `init` previews every file before it
|
|
44
|
+
writes anything and accepts only the exact digest of that preview. Then it asks, one field at a
|
|
45
|
+
time, for each fact it cannot read from the repository: commands, health checks, ports and the
|
|
46
|
+
database and vendor hosts the guard must keep agents away from. Each accepted answer records where
|
|
47
|
+
it came from, and `init` writes a commented `[work.gates]` and `[autonomy]` block showing how to add
|
|
48
|
+
human gates. The details are under [The init interview](#the-init-interview).
|
|
49
|
+
|
|
50
|
+
### Generate, check and commit
|
|
51
|
+
|
|
52
|
+
```sh
|
|
53
|
+
npx --no cockpit sync --config ./cockpit.toml --dry-run
|
|
54
|
+
npx --no cockpit sync --config ./cockpit.toml
|
|
55
|
+
npx --no cockpit check --config ./cockpit.toml
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
`sync` writes the generated files, and `check` reports any that no longer match:
|
|
59
|
+
|
|
60
|
+
- `sync --dry-run` lists every write and removal. Read it.
|
|
61
|
+
- `sync` publishes all generated files as one recoverable transaction. It refuses to remove a stale
|
|
62
|
+
generated file unless `[autonomy] stale_delete` lets it, or a person approves exactly that removal
|
|
63
|
+
with `sync --interactive`.
|
|
64
|
+
- `check` confirms nothing has drifted and never changes a file.
|
|
65
|
+
|
|
66
|
+
Review the output and commit it. From then on an agent started in the repository loads the same
|
|
67
|
+
instructions and skills in every listed tool, and the guard refuses a push to a protected branch, a
|
|
68
|
+
read of a declared secret file and commands against a declared production host. Run
|
|
69
|
+
`npx --no cockpit doctor --config ./cockpit.toml` for what is still missing: it reports each gap
|
|
70
|
+
with why cockpit needs it. If anyone uses Codex, a person must trust its guard hook once per
|
|
71
|
+
machine; `doctor` says so until it is done. Add `npx --no cockpit check --config cockpit.toml` to CI, or use the
|
|
72
|
+
[`cockpit-check` action](harness-surfaces.md).
|
|
73
|
+
|
|
74
|
+
Run every command from the cockpit directory with a path that fails when the dependency is missing
|
|
75
|
+
and never downloads a package: run it as `./node_modules/.bin/cockpit` or through `npx --no`. Once `init`
|
|
76
|
+
has written the `cockpit:*` package scripts, use them. The package ships these guides under
|
|
77
|
+
`./node_modules/@b00dea/cockpit/docs/`, so skills and fix hints cite them offline.
|
|
78
|
+
|
|
79
|
+
## Set up with an agent
|
|
80
|
+
|
|
81
|
+
Tell the agent: *set up cockpit for this project, following `docs/getting-started.md`*. It can read
|
|
82
|
+
this page from the installed package (`./node_modules/@b00dea/cockpit/docs/getting-started.md`), a
|
|
83
|
+
source checkout, or <https://github.com/b0dea/cockpit/blob/main/docs/getting-started.md>. The
|
|
84
|
+
`adopt-cockpit` skill (`npx skills add b0dea/cockpit --skill adopt-cockpit`) routes an agent to
|
|
85
|
+
this page. After `init`, every listed tool also has the `cockpit-setup` skill, which carries the
|
|
86
|
+
same procedure.
|
|
87
|
+
|
|
88
|
+
### Safety contract
|
|
89
|
+
|
|
90
|
+
A clean-looking configuration with invented values in it is the failure cockpit exists to prevent.
|
|
91
|
+
The agent follows these rules for the whole setup:
|
|
92
|
+
|
|
93
|
+
1. **Ask the human first, and wait for a yes,** before writing into a product repository (a
|
|
94
|
+
Dockerfile, Compose file, `.env.schema` or anything else in a sibling checkout), creating a Git
|
|
95
|
+
remote or hosted repository, running a destructive command (`down`, `reset`, `sync --interactive`
|
|
96
|
+
removals, deleting files), running `cockpit sync --adopt`, or accepting an `init` digest. A person
|
|
97
|
+
approves or runs staging and the commit of the cockpit: the agent hands them the command.
|
|
98
|
+
2. **Show the exact preview before asking:** the `sync --dry-run` listing, the `init` preview with its
|
|
99
|
+
`previewSha256`, the answers file or the defaults digest. Consent binds to those bytes, and a
|
|
100
|
+
digest from anything but the latest pending run is refused.
|
|
101
|
+
3. **Never invent a configuration value.** A port, image, command, health check, purpose or name
|
|
102
|
+
comes from a file the agent read or from the human; otherwise it leaves a named gap and asks.
|
|
103
|
+
4. **Inferred values need confirmation.** `init` proposes values with `provenance.kind = "inferred"`
|
|
104
|
+
and the file each came from; they become answers only on the human's word.
|
|
105
|
+
5. **Ask for every non-local host.** The `guards` answer lists the database and live vendor API hosts
|
|
106
|
+
of production, staging and shared environments. Variable names come from env templates, never
|
|
107
|
+
values; each host comes from the human.
|
|
108
|
+
6. **Defaults never reach into a product repository.** "Use sensible defaults" covers `init` answers
|
|
109
|
+
only. A pointer in a sibling's **AGENTS.md**, a Compose file or a `package.json` still needs an
|
|
110
|
+
explicit yes to that exact change. Every answer the agent chose itself is marked `"agent-default"`
|
|
111
|
+
(below), and its report ends with each default, its field and its value.
|
|
112
|
+
|
|
113
|
+
These rules are instructions, not enforcement. The guard cockpit installs later blocks some commands;
|
|
114
|
+
see [Safety and autonomy](safety-and-autonomy.md).
|
|
115
|
+
|
|
116
|
+
### Read a cockpit result
|
|
117
|
+
|
|
118
|
+
- Pass `--json` to every command except `session`. Each prints one JSON document with `result`,
|
|
119
|
+
`diagnostics` (each with a `severity` and a `code`) and `invocation.exitCode`.
|
|
120
|
+
- A refusal exits nonzero and names its diagnostic; look the code up in
|
|
121
|
+
[Troubleshooting](troubleshooting.md). Take flags from `cockpit <command> --help` or the
|
|
122
|
+
[CLI reference](cli-reference.md), not from memory.
|
|
123
|
+
- `init` exits 0 when it stops at a question. Read `result.stage`, `result.question` and
|
|
124
|
+
`result.interview.outstanding` for the pending decision.
|
|
125
|
+
|
|
126
|
+
### Mark the answers you chose
|
|
127
|
+
|
|
128
|
+
When the human delegates a decision ("pick sensible defaults"), say so per field in the answers file
|
|
129
|
+
so the value is never recorded as theirs:
|
|
130
|
+
|
|
131
|
+
```toml
|
|
132
|
+
[provenance]
|
|
133
|
+
"environment.machine" = "agent-default"
|
|
134
|
+
guards = "agent-default"
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Each such field is written under `unconfirmed` at the top of `cockpit.toml`, listed in
|
|
138
|
+
`result.unconfirmed`, and reported by `doctor` as `DECLARATION_UNCONFIRMED` until a person confirms
|
|
139
|
+
the value, deletes its `unconfirmed` entry and runs `cockpit sync`. An `environment.machine` floor
|
|
140
|
+
the file does not attribute is recorded as unattributed, because cockpit never proposes one.
|
|
141
|
+
|
|
142
|
+
### Walk through readiness
|
|
143
|
+
|
|
144
|
+
Every `init` stop and `cockpit doctor --config cockpit.toml --json` carry `result.readiness`: the
|
|
145
|
+
prerequisites cockpit depends on, grouped from the diagnostics that run reported. Each entry in `gaps`
|
|
146
|
+
has an `id`, a `level` (a `required` gap is refused by the command that needs it; a `recommended` one
|
|
147
|
+
warns), `needs` (why cockpit needs it) and `findings` (each diagnostic with its message and fix).
|
|
148
|
+
`noFinding` lists the prerequisites no check reported; a check that could not run reports nothing, so
|
|
149
|
+
it is not proof. Take the gaps one at a time, required first: what is missing, why, and the exact change
|
|
150
|
+
you propose. Judgement calls (which test runner to adopt, whether the existing tests prove anything)
|
|
151
|
+
are the human's. The cockpit directory must be a Git working tree, committed and clean, before
|
|
152
|
+
`preflight` passes; a new one reports `GIT_STATE_UNHEALTHY` until a person stages and commits it.
|
|
153
|
+
|
|
154
|
+
## The init interview
|
|
155
|
+
|
|
156
|
+
`init` reads the repositories under the directory and asks for every fact it cannot read from them.
|
|
157
|
+
Preview first, then accept in a terminal:
|
|
158
|
+
|
|
159
|
+
```sh
|
|
160
|
+
./node_modules/.bin/cockpit init "$(pwd)" --target <tool> --json
|
|
161
|
+
./node_modules/.bin/cockpit init "$(pwd)" --target <tool> --interactive
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
The preview writes nothing. It returns the files it would install, a `previewSha256` digest and the
|
|
165
|
+
next step; `--interactive` asks you to type that digest. Re-running the same command resumes where it
|
|
166
|
+
stopped, and a changed repository invalidates earlier answers instead of reusing them. What you get
|
|
167
|
+
depends on what it finds:
|
|
168
|
+
|
|
169
|
+
- **A product repository** (a Git checkout with a language manifest, Dockerfile or Compose file) gets
|
|
170
|
+
an in-repo cockpit and declares only that repository. To put the cockpit in a folder of its own
|
|
171
|
+
beside the repositories, answer `cockpit.root = "dedicated"`
|
|
172
|
+
([Where the cockpit lives](concepts.md#where-the-cockpit-lives)). Add other repositories afterwards
|
|
173
|
+
with [`sibling add`](#add-or-remove-a-repository); naming them in the answers file is refused with
|
|
174
|
+
`DOCUMENT_ESTATE_TOPOLOGY_MISMATCH`.
|
|
175
|
+
- **Nothing runnable** (an empty directory, or a repository of documents) gets a configuration with
|
|
176
|
+
no `[environment]`; runtime commands refuse with `ENVIRONMENT_NOT_DECLARED`, which is the expected
|
|
177
|
+
result, not a failure. `init` proposes the root itself as the first sibling (`dir = "."`,
|
|
178
|
+
`mount = "none"`).
|
|
179
|
+
- **A declared runtime** adds questions about the machine floor and posture the product needs.
|
|
180
|
+
|
|
181
|
+
Proposals come only from exact sources: a Dockerfile's `EXPOSE`, `CMD` and `ENTRYPOINT`, a
|
|
182
|
+
`package.json` `start`, `serve` or `dev` script, the `node` toolchain a lockfile names, each
|
|
183
|
+
repository's `origin` remote (a URL carrying credentials is skipped, never shown), variable names
|
|
184
|
+
(never values) in env templates such as `.env.example`, an existing Compose file, the `services:` of
|
|
185
|
+
GitHub workflows, and test entry points such as a Makefile `test` target, a `package.json` test script
|
|
186
|
+
or `go.mod`. A name that suggests a database or vendor endpoint, such as `DATABASE_URL`, becomes a
|
|
187
|
+
`guards` question about its host. Sources `init` could not use are listed in
|
|
188
|
+
`interview.inferenceSkipped`.
|
|
189
|
+
|
|
190
|
+
### Without a terminal
|
|
191
|
+
|
|
192
|
+
An agent or CI job has no terminal, so `--interactive` refuses with `INIT_TERMINAL_REQUIRED`. Pass
|
|
193
|
+
consent and answers as arguments instead; there is no blanket `--yes`.
|
|
194
|
+
|
|
195
|
+
1. Run the `--json` preview. It returns the `previewSha256` and, under `interview.outstanding`, every
|
|
196
|
+
field the interview will still ask, in order, each with a `why` and the values `init` could propose.
|
|
197
|
+
2. Write the answers as TOML keyed by field, and show them to the human with the digest.
|
|
198
|
+
3. Rerun with `--accept-preview <previewSha256>` and `--answers <file>`. The run stops at the first
|
|
199
|
+
unanswered field, or at `configuration.defaults`, where `result.question.document` is the review
|
|
200
|
+
draft (an array of lines) and `result.question.expectedSha256` covers its values. The human reads
|
|
201
|
+
the draft before accepting that digest.
|
|
202
|
+
4. Rerun with `--accept-defaults <expectedSha256>` as well. A digest that is not the pending one is
|
|
203
|
+
refused (`INIT_PREVIEW_NOT_ACCEPTED`, `INIT_DEFAULTS_NOT_ACCEPTED`).
|
|
204
|
+
|
|
205
|
+
```sh
|
|
206
|
+
./node_modules/.bin/cockpit init "$(pwd)" --target <tool> --accept-preview <previewSha256> --answers ./answers.toml --json
|
|
207
|
+
./node_modules/.bin/cockpit init "$(pwd)" --target <tool> --accept-preview <previewSha256> --answers ./answers.toml --accept-defaults <expectedSha256> --json
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
For a directory with one library and nothing runnable, the whole answers file is:
|
|
211
|
+
|
|
212
|
+
```toml
|
|
213
|
+
[cockpit]
|
|
214
|
+
name = "library"
|
|
215
|
+
|
|
216
|
+
[[sibling]]
|
|
217
|
+
slug = "library"
|
|
218
|
+
dir = "library"
|
|
219
|
+
mount = "always"
|
|
220
|
+
acquire = "none"
|
|
221
|
+
var = "LIBRARY_DIR"
|
|
222
|
+
purpose = "Shared library"
|
|
223
|
+
|
|
224
|
+
[ports]
|
|
225
|
+
bases = {}
|
|
226
|
+
|
|
227
|
+
[guards]
|
|
228
|
+
hosted_db_hosts = []
|
|
229
|
+
vendor_endpoint_hosts = []
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
| Field | Answer |
|
|
233
|
+
|---|---|
|
|
234
|
+
| `cockpit.root` | `"dedicated"` or `"in-repo"`; asked only where both are possible, and a digest flag takes `"in-repo"` |
|
|
235
|
+
| `cockpit.name` | always asked; the root directory's name is proposed. It scopes Compose projects, state and generated files ([Rename a cockpit](#rename-a-cockpit)) |
|
|
236
|
+
| `sibling` | one `[[sibling]]` table per repository |
|
|
237
|
+
| `estate.runnable` | one table per repository whose run command was unknown, keyed by its slug |
|
|
238
|
+
| `ports.bases` | the host-published base port map; `{}` means none |
|
|
239
|
+
| `environment.install_policies` | the build and test commands per toolchain and lockfile; `[]` for none |
|
|
240
|
+
| `environment.test_data` | exactly the boolean keys `seeded_data` and `signed_in_users`; `false` states it is not needed |
|
|
241
|
+
| `environment.compose_files` | the Compose files that run the product, relative to the cockpit root |
|
|
242
|
+
| `environment.machine` | the runtime floor: `runtime_memory_mb`, `runtime_cpus`, `free_disk_mb`, `cold_start_seconds`; never proposed |
|
|
243
|
+
| `environment.posture` | `addressing`, `authentication` and `posture_requirements` ([Declare environment postures](environment.md#declare-environment-postures)) |
|
|
244
|
+
| `testing` | the product's `[testing]` stages and gates; `"none"` records that it has no tests yet, so no work can be graded PASS and `doctor` warns (`TESTING_GATE_UNDECLARED`) |
|
|
245
|
+
| `guards` | `hosted_db_hosts` and `vendor_endpoint_hosts` of every non-local environment; `[]` for both records that none exists |
|
|
246
|
+
| `provenance` | optional; `"human"` (the default) or `"agent-default"` per field |
|
|
247
|
+
|
|
248
|
+
A key that names no field is refused. Recorded answers are kept, so the same file can be passed on every
|
|
249
|
+
run; a different value for a recorded field is refused (`INIT_ANSWER_CONFLICT`) before anything is
|
|
250
|
+
published. Preview resetting one, and every later dependent answer, with
|
|
251
|
+
`cockpit init <root> --target <tool> --reset-answer <field> --json`, then repeat with
|
|
252
|
+
`--accept-reset <previewSha256>`. Once `cockpit.toml` is written, recorded answers can no longer be reset:
|
|
253
|
+
edit the value in `cockpit.toml` and rerun `init` with `--accept-preview`.
|
|
254
|
+
|
|
255
|
+
## Chapter 2: several repositories and a Compose stack
|
|
256
|
+
|
|
257
|
+
cockpit runs your own Compose files; it does not generate them. Add each further repository with
|
|
258
|
+
[`sibling add`](#add-or-remove-a-repository), and put the cockpit in a folder beside them
|
|
259
|
+
(`cockpit.root = "dedicated"`, `siblings_root = ".."`) when it should own several neutrally.
|
|
260
|
+
|
|
261
|
+
**Compose.** Declare `environment.compose_files` with the files that run the product, inside the
|
|
262
|
+
cockpit root:
|
|
263
|
+
|
|
264
|
+
```toml
|
|
265
|
+
[environment]
|
|
266
|
+
install_policies = []
|
|
267
|
+
compose_files = ["compose.yml"]
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
| Compose files | Layout |
|
|
271
|
+
|---|---|
|
|
272
|
+
| One, inside a product repository checked out under the cockpit root (`siblings_root = "."`) | Declare the repository as a sibling and point at its file in place, as in `compose_files = ["shop/compose.yml"]`. Relative paths such as `build: ./api` resolve against `shop/`, so the file needs no change. |
|
|
273
|
+
| In two or more repositories, or outside the cockpit root | A `compose.yml` of your own at the cockpit root that reaches each checkout through its sibling variable (`build: ${SHOP_DIR}/api`) and publishes ports from `[ports.bases]` variables. A Compose `include` of the product's file is refused. |
|
|
274
|
+
| None yet | `cockpit init . --scaffold-compose <app dir> --port <port>` writes one plain `compose.yml` once, which the product then owns ([Scaffold a Compose file](environment.md#scaffold-a-compose-file)). |
|
|
275
|
+
|
|
276
|
+
`check` reads the topology with `docker compose config`: every published host port must come from a
|
|
277
|
+
`[ports.bases]` variable, and a service without a healthcheck warns. The rules are in
|
|
278
|
+
[Environment lifecycle](environment.md#environment-modes); a working layout is
|
|
279
|
+
[examples/compose-first](https://github.com/b0dea/cockpit/blob/main/examples/compose-first/README.md). Changing a product's Compose file is a
|
|
280
|
+
product change: ask first.
|
|
281
|
+
|
|
282
|
+
**Data.** `seed` and `resettable_volumes` fill and wipe the stack's data
|
|
283
|
+
([Demo data, test users and roles](environment.md#demo-data-test-users-and-roles)). `cockpit reset` previews the change and needs a person
|
|
284
|
+
to approve it unless `[autonomy] reset` says otherwise.
|
|
285
|
+
|
|
286
|
+
**Docker.** Commands that run the stack need Docker Compose and a local runtime that has passed
|
|
287
|
+
`cockpit runtime measure --image <local-image>`; [Measure the container runtime](environment.md#measure-the-container-runtime)
|
|
288
|
+
lists the supported runtimes. Configuration, generation and `check` need no runtime, though validating
|
|
289
|
+
declared Compose files needs Docker Compose.
|
|
290
|
+
|
|
291
|
+
### Bring the product up
|
|
292
|
+
|
|
293
|
+
```sh
|
|
294
|
+
./node_modules/.bin/cockpit setup --config ./cockpit.toml
|
|
295
|
+
./node_modules/.bin/cockpit sync --config ./cockpit.toml
|
|
296
|
+
./node_modules/.bin/cockpit check --config ./cockpit.toml
|
|
297
|
+
./node_modules/.bin/cockpit up --config ./cockpit.toml
|
|
298
|
+
./node_modules/.bin/cockpit preflight --config ./cockpit.toml
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
`setup` clones or verifies each declared repository and checks its remote. `up` starts or resumes the
|
|
302
|
+
stack, but only `preflight` says it is healthy; it also fails with `GIT_STATE_UNHEALTHY` while the
|
|
303
|
+
cockpit has uncommitted changes. With `--json`, `up` reports the stack identifier, whether it
|
|
304
|
+
`started`, `resumed` or was `unchanged`, the leased port for each `[ports.bases]` name and the cold-start
|
|
305
|
+
time of the services it started.
|
|
306
|
+
|
|
307
|
+
## Other situations
|
|
308
|
+
|
|
309
|
+
| On disk | Do |
|
|
310
|
+
|---|---|
|
|
311
|
+
| Repositories scattered across the disk | Moving them is the human's call. Otherwise `sibling add <slug> --from <path> --purpose "<purpose>"` records each checkout's `origin` with `acquire = "auto"`, and `setup` clones a fresh copy into the cockpit. It never moves, changes or deletes the original. |
|
|
312
|
+
| A service that has only ever run in CI, staging or a cluster | Follow **Create a local setup** in the shipped [setup procedure](https://github.com/b0dea/cockpit/blob/main/packages/cockpit/surfaces/skills/procedures/setup.md#create-a-local-setup): derive each value from manifests, CI workflows and deployment files, record it as inferred with its source, and keep every unknown a named gap. |
|
|
313
|
+
| Committed `.claude/settings.json`, `.codex/config.toml` or `.codex/hooks.json` | [Adopt existing agent settings](#adopt-existing-agent-settings), after the human agrees. |
|
|
314
|
+
| A sibling with a `.env.schema` (Varlock) | `preflight` and `doctor` check each schema through Varlock and report key names and validity, never values. Follow **Secret handling** in the [setup procedure](https://github.com/b0dea/cockpit/blob/main/packages/cockpit/surfaces/skills/procedures/setup.md#secret-handling) and [Secret sources and environment schemas](environment.md#secret-sources-and-environment-schemas). `varlock init`, provider login, encryption and moving secrets are the human's actions. |
|
|
315
|
+
|
|
316
|
+
## Adopt an existing setup
|
|
317
|
+
|
|
318
|
+
For teams that already run a multi-repository product with their own scripts or a shell-registry
|
|
319
|
+
cockpit, and want to move to cockpit one layer at a time. Keep the old path runnable until the
|
|
320
|
+
cockpit path passes the same checks.
|
|
321
|
+
|
|
322
|
+
### Bootstrap from the registry
|
|
323
|
+
|
|
324
|
+
Preview for one harness, then accept. Replace `<tool>` with its target, listed in
|
|
325
|
+
[chapter 1](#install-cockpit):
|
|
326
|
+
|
|
327
|
+
```sh
|
|
328
|
+
./node_modules/.bin/cockpit init . --target <tool> --registry ./env/lib/instance.sh --json
|
|
329
|
+
./node_modules/.bin/cockpit init . --target <tool> --registry ./env/lib/instance.sh --interactive
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
The first command writes nothing; the second needs a terminal and the exact preview digest. init
|
|
333
|
+
reads the registry's repositories, marks every value the registry did not state with its source and
|
|
334
|
+
the reason it was inferred or defaulted, and asks for the rest, such as
|
|
335
|
+
<!-- cockpit:ref schema=ports.bases --> `ports.bases`, which no registry dialect records. A missing
|
|
336
|
+
registry file is refused with `REGISTRY_NOT_FOUND`. Accepted answers keep their source, and
|
|
337
|
+
re-running resumes where it stopped. When `init` finds
|
|
338
|
+
repositories directly beneath the cockpit root instead of reading a registry, it records
|
|
339
|
+
`siblings_root = "."` as an inference for you to confirm.
|
|
340
|
+
|
|
341
|
+
### Adopt in layers
|
|
342
|
+
|
|
343
|
+
Keep each layer's old path until the new one passes:
|
|
344
|
+
|
|
345
|
+
1. **Registry.** Get the reviewed configuration to validate.
|
|
346
|
+
2. **Surfaces.** Run `sync --dry-run`, `sync` and `check` (chapter 1), and read the dry run before
|
|
347
|
+
every `sync`.
|
|
348
|
+
3. **Runtime.** Run `up` and `preflight` against the same configuration
|
|
349
|
+
([chapter 2](#chapter-2-several-repositories-and-a-compose-stack)).
|
|
350
|
+
4. **Guards, grading and more harnesses.** Add them once the earlier layers are stable. The
|
|
351
|
+
[capability matrix](capability-matrix.md) shows each harness feature's
|
|
352
|
+
[Cockpit harness capability state](concepts.md#cockpit-harness-capability-state); an
|
|
353
|
+
`instructed` feature should not yet replace a legacy control that is enforced.
|
|
354
|
+
|
|
355
|
+
Two rules matter in the surfaces layer:
|
|
356
|
+
|
|
357
|
+
- **cockpit never takes over an unmanaged file.** If a file already exists where cockpit wants to
|
|
358
|
+
generate one, `sync` refuses; move the existing file deliberately. The one supported exception
|
|
359
|
+
is a team's agent settings file, which you can [adopt](#adopt-existing-agent-settings).
|
|
360
|
+
[Cockpit generated ownership](concepts.md#cockpit-generated-ownership) covers only cockpit's own
|
|
361
|
+
output and never permits removing a file cockpit did not write.
|
|
362
|
+
- **Secrets after the ignore boundary.** Let `sync` create the ignore boundary before adopting
|
|
363
|
+
environment credentials, then follow
|
|
364
|
+
[Secret sources and environment schemas](environment.md#secret-sources-and-environment-schemas).
|
|
365
|
+
|
|
366
|
+
### Keep shell scripts on the registry while you migrate
|
|
367
|
+
|
|
368
|
+
While old scripts still read the shell registry, `registry-resolve` validates it and prints the
|
|
369
|
+
same rows as data a script can `source`, so the scripts and cockpit read one checked copy. It
|
|
370
|
+
takes three required flags:
|
|
371
|
+
|
|
372
|
+
```sh
|
|
373
|
+
./node_modules/.bin/cockpit registry-resolve \
|
|
374
|
+
--registry ./env/lib/instance.sh --siblings-root .. --adoption ./adoption.state > resolved.sh
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
`--adoption` names a five-line file that records how far each layer has moved to cockpit. The
|
|
378
|
+
lines name the layers in this order, each set to `migrated` or `documented-only`, and the migrated
|
|
379
|
+
layers come first:
|
|
380
|
+
|
|
381
|
+
```text
|
|
382
|
+
registry=migrated
|
|
383
|
+
environment=documented-only
|
|
384
|
+
surfaces=documented-only
|
|
385
|
+
guards=documented-only
|
|
386
|
+
grading=documented-only
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
The output assigns `COCKPIT_REGISTRY_ROWS`, `COCKPIT_SIBLING_PATHS`, `COCKPIT_SIBLING_VARIABLES`
|
|
390
|
+
and `COCKPIT_ADOPTION_STATES`, exports one `*_DIR` variable per sibling, and records the registry
|
|
391
|
+
digest in `COCKPIT_REGISTRY_SHA256`. `COCKPIT_SOURCE_REVISION` is the cockpit commit that produced
|
|
392
|
+
the data. A cockpit installed from a tarball packed from source has no release commit, so the
|
|
393
|
+
value is `development` and the command warns with `COCKPIT_REVISION_UNSTAMPED`. Nothing is printed
|
|
394
|
+
unless every input passed validation.
|
|
395
|
+
|
|
396
|
+
### Adopt existing agent settings
|
|
397
|
+
|
|
398
|
+
For a repository that already commits its own `.claude/settings.json`, `.codex/config.toml` or
|
|
399
|
+
`.codex/hooks.json`. cockpit writes those files whole, so a plain `sync` refuses with
|
|
400
|
+
`SURFACE_STATE_CONFLICT` and names the command that keeps the team's settings:
|
|
401
|
+
|
|
402
|
+
```sh
|
|
403
|
+
./node_modules/.bin/cockpit sync --config cockpit.toml
|
|
404
|
+
./node_modules/.bin/cockpit sync --config cockpit.toml --adopt .claude/settings.json
|
|
405
|
+
./node_modules/.bin/cockpit check --config cockpit.toml
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
`--adopt <path>` can be repeated, once per file. It moves the file to `cockpit/adopted/<path>`,
|
|
409
|
+
records a <!-- cockpit:ref schema=surfaces.adopted --> `surfaces.adopted` row in cockpit.toml (path, source, SHA-256 of the moved bytes, date,
|
|
410
|
+
provenance), and syncs. The file at `<path>` becomes cockpit's merge of the adopted copy and its
|
|
411
|
+
own generated version:
|
|
412
|
+
|
|
413
|
+
- **Hooks:** the team's hooks are kept beside cockpit's guard hook. `PreToolUse` entries are
|
|
414
|
+
combined; any other hook event both sides define must be identical.
|
|
415
|
+
- **Claude permissions:** `allow`, `ask` and `deny` rules are combined. A rule cockpit denies is
|
|
416
|
+
never kept as a team `allow` or `ask`.
|
|
417
|
+
- **Every other key** is the team's, unless cockpit writes the same key; then the two values must
|
|
418
|
+
match.
|
|
419
|
+
|
|
420
|
+
Commit `cockpit/adopted/` with cockpit.toml: it is the team's copy and, from now on, the place to
|
|
421
|
+
change those settings. To change them, edit the adopted copy, delete the merged file and run
|
|
422
|
+
`sync`; `check` reports a hand-edited merged file, or an adopted copy changed since the last
|
|
423
|
+
merge, and `sync` refuses the former. The recorded SHA-256 says which bytes were moved; it is not
|
|
424
|
+
a lock.
|
|
425
|
+
|
|
426
|
+
Adoption is refused with `SURFACE_ADOPTION_REFUSED`, naming the key, when the file would switch off
|
|
427
|
+
or route around the guard, or carries a setting cockpit declares elsewhere:
|
|
428
|
+
|
|
429
|
+
- `disableAllHooks`, `permissions.defaultMode = "bypassPermissions"`, or any hook that names a
|
|
430
|
+
`.cockpit/guards/` transport;
|
|
431
|
+
- `permissions.additionalDirectories` and `enabledMcpjsonServers` (declare a sibling or approve
|
|
432
|
+
the MCP server instead);
|
|
433
|
+
- in `.codex/config.toml`, `mcp_servers` and `features.codex_hooks = false`.
|
|
434
|
+
|
|
435
|
+
Adoption reads and moves only regular files inside the cockpit root, so it also refuses redirected
|
|
436
|
+
ancestors, links, special files and files that change while being read; replace them with plain
|
|
437
|
+
files and re-run. A refusal is rolled back, leaving the file in place and cockpit.toml unchanged. If
|
|
438
|
+
a concurrent replacement prevents a safe rollback, the refusal names every private recovery path
|
|
439
|
+
that may still hold the original bytes, with their SHA-256; keep those paths until the source is
|
|
440
|
+
restored. Because adoption changes cockpit.toml, it has no dry run or `--interactive` form, and an
|
|
441
|
+
agent's guard never treats it as an ordinary command.
|
|
442
|
+
|
|
443
|
+
`opencode.jsonc` needs no adoption: cockpit writes only its `$schema`, `instructions`, `mcp` and
|
|
444
|
+
`permission` keys and keeps the team's other keys as they are.
|
|
445
|
+
|
|
446
|
+
### Complete the cutover
|
|
447
|
+
|
|
448
|
+
Retire the old path only when everything it did passes under cockpit (`check`, `up` and
|
|
449
|
+
`preflight` for the same configuration and runtime) and you know how to roll back. Destructive
|
|
450
|
+
environment commands, stale-output removal, changes to external services and publication stay
|
|
451
|
+
explicit human decisions. For recovery, see [Environment](environment.md) and
|
|
452
|
+
[Troubleshooting](troubleshooting.md).
|
|
453
|
+
## Add or remove a repository
|
|
454
|
+
|
|
455
|
+
`sibling add` and `sibling remove` edit the `[[sibling]]` tables of `cockpit.toml` for you. They
|
|
456
|
+
append or delete only that table, keep every other line and comment, and refuse rather than write
|
|
457
|
+
anything that is not exactly the intended change. Pick the form for where the repository is:
|
|
458
|
+
|
|
459
|
+
```sh
|
|
460
|
+
# a directory that already exists under the siblings root (acquire = "none")
|
|
461
|
+
./node_modules/.bin/cockpit sibling add api --config ./cockpit.toml --purpose "HTTP API for orders"
|
|
462
|
+
|
|
463
|
+
# a repository that does not exist yet: runs `git init` on an empty or missing path
|
|
464
|
+
./node_modules/.bin/cockpit sibling add api --config ./cockpit.toml --create --purpose "HTTP API for orders"
|
|
465
|
+
|
|
466
|
+
# a checkout elsewhere on disk: records its origin so `setup` clones a fresh copy
|
|
467
|
+
./node_modules/.bin/cockpit sibling add api --config ./cockpit.toml --from ~/code/api --purpose "HTTP API for orders"
|
|
468
|
+
|
|
469
|
+
# a known remote (acquire = "auto"); also records a remote for an existing acquire = "none" sibling
|
|
470
|
+
./node_modules/.bin/cockpit sibling add api --config ./cockpit.toml --remote git@example.com:team/api.git --purpose "HTTP API for orders"
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
| Option | Meaning |
|
|
474
|
+
|---|---|
|
|
475
|
+
| `--purpose "<text>"` | what the repository is for; required for a new sibling, never defaulted |
|
|
476
|
+
| `--dir <relative dir>` | directory under the siblings root; defaults to the slug |
|
|
477
|
+
| `--var <NAME>` | exported variable; defaults to the slug as `API_DIR`. A default that would start with a Docker, Compose or host-process control prefix gets `SIBLING_` prepended, and an explicit control variable is refused, because handing it to Compose could change the runtime plan |
|
|
478
|
+
| `--mount <always\|none\|profile:NAME>` | how the stack uses the checkout. Defaults to `always`, except in a compose-first cockpit, where it defaults to `none`: cockpit never edits your Compose files, and `check` and `up` refuse a `mount = "always"` sibling no service bind-mounts. Pass `--mount always` once a service mounts the sibling's variable |
|
|
479
|
+
|
|
480
|
+
A duplicate slug, directory or variable is refused by name. `--create` never creates a GitHub
|
|
481
|
+
repository: it prints the `gh repo create` command to run and the `--remote` call that records the
|
|
482
|
+
result (with `--json`, `result.publish.command` and `result.publish.recordRemote`). `--from` never
|
|
483
|
+
moves, modifies or deletes the original checkout, and refuses one with no `origin` remote.
|
|
484
|
+
|
|
485
|
+
`--instruction-pointer` opts a separate sibling into a marked link from its **AGENTS.md** to the
|
|
486
|
+
cockpit instructions. That changes what agents in that repository load, so `setup` reports the
|
|
487
|
+
proposal first and writes it only when asked:
|
|
488
|
+
|
|
489
|
+
```sh
|
|
490
|
+
./node_modules/.bin/cockpit sibling add api --config ./cockpit.toml --from ~/code/api \
|
|
491
|
+
--purpose "HTTP API for orders" --instruction-pointer
|
|
492
|
+
./node_modules/.bin/cockpit setup --config ./cockpit.toml --json
|
|
493
|
+
# after a human approves the exact AGENTS.md block
|
|
494
|
+
./node_modules/.bin/cockpit setup --config ./cockpit.toml --write-instruction-pointers
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
The link targets the **AGENTS.md** beside the selected **cockpit.toml**. The write appends only the
|
|
498
|
+
marked block and keeps existing team text (a missing **AGENTS.md** becomes a new guide); an edited,
|
|
499
|
+
partial or duplicate pointer is refused. The root sibling (`dir = "."`) cannot opt in: its guide
|
|
500
|
+
is the cockpit guide.
|
|
501
|
+
|
|
502
|
+
Plain `setup` also proposes the **AGENTS.md** or **CLAUDE.md** a sibling needs so every agent tool
|
|
503
|
+
started there loads its instructions, and `setup --write-instruction-files` writes it after review;
|
|
504
|
+
[Lifecycle and ownership](environment.md#lifecycle-and-ownership) has the cases.
|
|
505
|
+
|
|
506
|
+
```sh
|
|
507
|
+
./node_modules/.bin/cockpit sibling remove api --config ./cockpit.toml
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
`remove` drops the table only if nothing refers to the sibling (generated services, vendor
|
|
511
|
+
endpoints, mounts, its exported variable, or a declared Compose file using that variable);
|
|
512
|
+
otherwise it lists every reference and changes nothing. It never deletes the checkout or a
|
|
513
|
+
generated file. After either command, run `cockpit sync --config ./cockpit.toml --dry-run` to see
|
|
514
|
+
what changes.
|
|
515
|
+
|
|
516
|
+
While a stack is up or asleep, both commands act at once only on a repository the stack does not
|
|
517
|
+
use (`mount = "none"`, named by none of its Compose files); for any other they refuse and ask for
|
|
518
|
+
`./node_modules/.bin/cockpit down --config ./cockpit.toml` first. Hand edits follow the same rule:
|
|
519
|
+
a change that never reaches a container (a `purpose`, guards, MCP, skills, surfaces, comments,
|
|
520
|
+
the `[environment.machine]` floor and cold-start budget, the reset volumes and the seed command)
|
|
521
|
+
needs only `sync`, and the next `up` resumes the same stack. A change to a Compose file, ports,
|
|
522
|
+
mounts or anything else the containers receive makes `up` refuse with `LIFECYCLE_PROGRESS_INVALID`,
|
|
523
|
+
because `up` never replaces a running stack in place; run the `down` it prints, then `up`.
|
|
524
|
+
|
|
525
|
+
## Rename a cockpit
|
|
526
|
+
|
|
527
|
+
`cockpit.name` is part of every identity cockpit records: owner markers in generated files, the
|
|
528
|
+
ownership ledger, the Compose project and the stack's saved state. A running stack keeps the name
|
|
529
|
+
it started under, and only `down` under that name removes its containers, so take the stack down
|
|
530
|
+
before renaming:
|
|
531
|
+
|
|
532
|
+
```sh
|
|
533
|
+
./node_modules/.bin/cockpit down --config ./cockpit.toml
|
|
534
|
+
# edit name under [cockpit] in cockpit.toml, then:
|
|
535
|
+
./node_modules/.bin/cockpit sync --config ./cockpit.toml
|
|
536
|
+
./node_modules/.bin/cockpit check --config ./cockpit.toml
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
`sync` rewrites the generated files and the ledger under the new name and keeps your own text
|
|
540
|
+
around cockpit's regions. If you renamed while a stack was recorded, `sync`, `check`, `up` and
|
|
541
|
+
`down` refuse with `STACK_RECORDED_UNDER_EARLIER_NAME` and print the earlier name: put it back, run
|
|
542
|
+
`down`, then rename again. Never delete or hand-edit cockpit's ownership files to get past a
|
|
543
|
+
refusal; they are how `sync` knows which files are its own.
|
|
544
|
+
## Run an agent inside the environment
|
|
545
|
+
|
|
546
|
+
`session` is the everyday command. It runs `up`, holds the stack while your agent runs, and
|
|
547
|
+
releases it when the agent exits:
|
|
548
|
+
|
|
549
|
+
```sh
|
|
550
|
+
./node_modules/.bin/cockpit session --config ./cockpit.toml -- codex
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
Put the agent command and its arguments after `--`. It starts with each `[ports.bases]` name set
|
|
554
|
+
to the stack's leased port and each entrypoint under `COCKPIT_ENTRYPOINT_`
|
|
555
|
+
([Environment lifecycle](environment.md#lifecycle-and-ownership)). When the command's process
|
|
556
|
+
group stops, `session` calls `sleep`, which stops the stack only if no other checkout still holds
|
|
557
|
+
it. Interrupting `session` stops only the process group it started, and a `session` inside another
|
|
558
|
+
is refused. Use plain `up` only when the stack should outlive one command.
|
|
559
|
+
|
|
560
|
+
To remove the stack and its containers, run `down`. It reads the active Docker context once,
|
|
561
|
+
refuses one that is not local, and deletes only from that daemon, so a deletion never lands on a
|
|
562
|
+
remote daemon or on a context switched mid-command
|
|
563
|
+
([Choose the Docker daemon](environment.md#choose-the-docker-daemon)):
|
|
564
|
+
|
|
565
|
+
```sh
|
|
566
|
+
./node_modules/.bin/cockpit down --config ./cockpit.toml
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
## Upgrade cockpit
|
|
570
|
+
|
|
571
|
+
```sh
|
|
572
|
+
./node_modules/.bin/cockpit upgrade --config ./cockpit.toml --dry-run
|
|
573
|
+
./node_modules/.bin/cockpit upgrade --config ./cockpit.toml
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
`upgrade [<version>]` moves the exact pin to a newer version and re-runs `sync`; `--dry-run` prints
|
|
577
|
+
the commands and runs nothing. Until `sync` finishes, the guard holds every agent tool call, because
|
|
578
|
+
it trusts only the cockpit, Node and `cockpit.toml` it was generated for. Review and commit the
|
|
579
|
+
regenerated files. [Upgrade cockpit](harness-surfaces.md#upgrade-cockpit) has the details.
|
|
580
|
+
|
|
581
|
+
## Install from source
|
|
582
|
+
|
|
583
|
+
To run an unreleased build, pack the package and install the tarball. That exercises the same files,
|
|
584
|
+
lifecycle scripts, dependencies and binary entry point as a registry install; `npm link` does not.
|
|
585
|
+
|
|
586
|
+
```sh
|
|
587
|
+
git clone https://github.com/b0dea/cockpit.git
|
|
588
|
+
cd cockpit
|
|
589
|
+
npm ci --ignore-scripts
|
|
590
|
+
npm run build
|
|
591
|
+
COCKPIT_PACKAGE_DIR="$(mktemp -d)"
|
|
592
|
+
npm pack --workspace @b00dea/cockpit --pack-destination "$COCKPIT_PACKAGE_DIR"
|
|
593
|
+
cd /path/to/your/repository
|
|
594
|
+
npm install -D "$COCKPIT_PACKAGE_DIR"/*.tgz
|
|
595
|
+
./node_modules/.bin/cockpit --help
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
If `npm pack` or `npm install` fails, stop: a command run from the source checkout does not prove the
|
|
599
|
+
package works. Keep the tarball while the lockfile resolves cockpit from it.
|
|
600
|
+
|
|
601
|
+
## Next steps
|
|
602
|
+
|
|
603
|
+
- [Environment lifecycle](environment.md): who holds the stack, resources, cold-start limits and recovery.
|
|
604
|
+
- [Harness surfaces](harness-surfaces.md): what `sync` writes for each agent tool.
|
|
605
|
+
- [Safety and autonomy](safety-and-autonomy.md): what the guards allow, ask about and deny.
|
|
606
|
+
- [Work and browser](work-and-browser.md): work orders, grading and browser checks.
|
|
607
|
+
- [Troubleshooting](troubleshooting.md): every diagnostic code and its remedy.
|
|
608
|
+
- [FAQ](faq.md): short answers to common questions.
|