@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.
Files changed (363) hide show
  1. package/CHANGELOG.md +375 -0
  2. package/LICENSE +21 -0
  3. package/README.md +22 -2
  4. package/bin/cockpit.mjs +33 -0
  5. package/cockpit.schema.json +2574 -0
  6. package/dist/autonomy.d.ts +44 -0
  7. package/dist/autonomy.js +156 -0
  8. package/dist/bounded-read.d.ts +14 -0
  9. package/dist/bounded-read.js +42 -0
  10. package/dist/browser/commands.d.ts +62 -0
  11. package/dist/browser/commands.js +349 -0
  12. package/dist/browser/package-paths.d.ts +1 -0
  13. package/dist/browser/package-paths.js +6 -0
  14. package/dist/browser/proxy.d.ts +22 -0
  15. package/dist/browser/proxy.js +37 -0
  16. package/dist/browser/runtime.d.ts +117 -0
  17. package/dist/browser/runtime.js +183 -0
  18. package/dist/browser/surfaces.d.ts +141 -0
  19. package/dist/browser/surfaces.js +556 -0
  20. package/dist/browser/ui-gate.d.ts +15 -0
  21. package/dist/browser/ui-gate.js +18 -0
  22. package/dist/cli-guard.d.ts +5 -0
  23. package/dist/cli-guard.js +71 -0
  24. package/dist/cli-main.d.ts +139 -0
  25. package/dist/cli-main.js +1405 -0
  26. package/dist/cli.d.ts +3 -0
  27. package/dist/cli.js +16 -0
  28. package/dist/command-table.d.ts +113 -0
  29. package/dist/command-table.js +512 -0
  30. package/dist/config/load.d.ts +171 -0
  31. package/dist/config/load.js +345 -0
  32. package/dist/config/sibling-toml.d.ts +48 -0
  33. package/dist/config/sibling-toml.js +160 -0
  34. package/dist/config/surface-tools-toml.d.ts +9 -0
  35. package/dist/config/surface-tools-toml.js +37 -0
  36. package/dist/config/verified-write.d.ts +43 -0
  37. package/dist/config/verified-write.js +89 -0
  38. package/dist/diagnostics.d.ts +26 -0
  39. package/dist/diagnostics.js +335 -0
  40. package/dist/emit.d.ts +22 -0
  41. package/dist/emit.js +43 -0
  42. package/dist/entrypoint-kinds.d.ts +3 -0
  43. package/dist/entrypoint-kinds.js +11 -0
  44. package/dist/environment/application/destructive.d.ts +6 -0
  45. package/dist/environment/application/destructive.js +425 -0
  46. package/dist/environment/application/doctor.d.ts +89 -0
  47. package/dist/environment/application/doctor.js +235 -0
  48. package/dist/environment/application/guard.d.ts +43 -0
  49. package/dist/environment/application/guard.js +622 -0
  50. package/dist/environment/application/health.d.ts +134 -0
  51. package/dist/environment/application/health.js +379 -0
  52. package/dist/environment/application/lifecycle-context.d.ts +228 -0
  53. package/dist/environment/application/lifecycle-context.js +154 -0
  54. package/dist/environment/application/lifecycle-state.d.ts +25 -0
  55. package/dist/environment/application/lifecycle-state.js +201 -0
  56. package/dist/environment/application/lifecycle.d.ts +17 -0
  57. package/dist/environment/application/lifecycle.js +729 -0
  58. package/dist/environment/application/logs.d.ts +45 -0
  59. package/dist/environment/application/logs.js +127 -0
  60. package/dist/environment/application/setup.d.ts +129 -0
  61. package/dist/environment/application/setup.js +741 -0
  62. package/dist/environment/application/shared.d.ts +11 -0
  63. package/dist/environment/application/shared.js +61 -0
  64. package/dist/environment/claims.d.ts +389 -0
  65. package/dist/environment/claims.js +1709 -0
  66. package/dist/environment/codex-hook-trust.d.ts +11 -0
  67. package/dist/environment/codex-hook-trust.js +185 -0
  68. package/dist/environment/compose-environment.d.ts +1 -0
  69. package/dist/environment/compose-environment.js +6 -0
  70. package/dist/environment/compose-ownership.d.ts +21 -0
  71. package/dist/environment/compose-ownership.js +117 -0
  72. package/dist/environment/compose-topology.d.ts +117 -0
  73. package/dist/environment/compose-topology.js +413 -0
  74. package/dist/environment/contract.d.ts +489 -0
  75. package/dist/environment/contract.js +761 -0
  76. package/dist/environment/declaration.d.ts +14 -0
  77. package/dist/environment/declaration.js +39 -0
  78. package/dist/environment/destructive-composition.d.ts +29 -0
  79. package/dist/environment/destructive-composition.js +333 -0
  80. package/dist/environment/docker-daemon.d.ts +30 -0
  81. package/dist/environment/docker-daemon.js +78 -0
  82. package/dist/environment/docker-endpoint.d.ts +10 -0
  83. package/dist/environment/docker-endpoint.js +19 -0
  84. package/dist/environment/env-schema-observation.d.ts +46 -0
  85. package/dist/environment/env-schema-observation.js +241 -0
  86. package/dist/environment/evidence.d.ts +136 -0
  87. package/dist/environment/evidence.js +437 -0
  88. package/dist/environment/executable.d.ts +26 -0
  89. package/dist/environment/executable.js +167 -0
  90. package/dist/environment/generated-application/authorities.d.ts +5 -0
  91. package/dist/environment/generated-application/authorities.js +61 -0
  92. package/dist/environment/generated-application/bootstrap-skill.d.ts +16 -0
  93. package/dist/environment/generated-application/bootstrap-skill.js +328 -0
  94. package/dist/environment/generated-application/check.d.ts +13 -0
  95. package/dist/environment/generated-application/check.js +189 -0
  96. package/dist/environment/generated-application/custom-surface.d.ts +26 -0
  97. package/dist/environment/generated-application/custom-surface.js +289 -0
  98. package/dist/environment/generated-application/prepare.d.ts +29 -0
  99. package/dist/environment/generated-application/prepare.js +276 -0
  100. package/dist/environment/generated-application/publication.d.ts +33 -0
  101. package/dist/environment/generated-application/publication.js +547 -0
  102. package/dist/environment/generated-application/shared.d.ts +484 -0
  103. package/dist/environment/generated-application/shared.js +349 -0
  104. package/dist/environment/generated-application/surface-observation.d.ts +4 -0
  105. package/dist/environment/generated-application/surface-observation.js +69 -0
  106. package/dist/environment/generated-application/surface-outputs.d.ts +71 -0
  107. package/dist/environment/generated-application/surface-outputs.js +389 -0
  108. package/dist/environment/generated-application/surfaces.d.ts +3 -0
  109. package/dist/environment/generated-application/surfaces.js +699 -0
  110. package/dist/environment/generated-application/sync.d.ts +6 -0
  111. package/dist/environment/generated-application/sync.js +109 -0
  112. package/dist/environment/git-observation.d.ts +183 -0
  113. package/dist/environment/git-observation.js +544 -0
  114. package/dist/environment/health-composition.d.ts +11 -0
  115. package/dist/environment/health-composition.js +628 -0
  116. package/dist/environment/host-observation.d.ts +56 -0
  117. package/dist/environment/host-observation.js +52 -0
  118. package/dist/environment/identity.d.ts +48 -0
  119. package/dist/environment/identity.js +85 -0
  120. package/dist/environment/init-application.d.ts +308 -0
  121. package/dist/environment/init-application.js +697 -0
  122. package/dist/environment/install-policy-observation.d.ts +71 -0
  123. package/dist/environment/install-policy-observation.js +284 -0
  124. package/dist/environment/install-policy.d.ts +48 -0
  125. package/dist/environment/install-policy.js +96 -0
  126. package/dist/environment/instance.d.ts +33 -0
  127. package/dist/environment/instance.js +122 -0
  128. package/dist/environment/instruction-pointer.d.ts +19 -0
  129. package/dist/environment/instruction-pointer.js +144 -0
  130. package/dist/environment/lifecycle-composition.d.ts +29 -0
  131. package/dist/environment/lifecycle-composition.js +675 -0
  132. package/dist/environment/lifecycle-stage.d.ts +115 -0
  133. package/dist/environment/lifecycle-stage.js +398 -0
  134. package/dist/environment/lifecycle.d.ts +75 -0
  135. package/dist/environment/lifecycle.js +354 -0
  136. package/dist/environment/logs.d.ts +132 -0
  137. package/dist/environment/logs.js +519 -0
  138. package/dist/environment/observations.d.ts +46 -0
  139. package/dist/environment/observations.js +344 -0
  140. package/dist/environment/operator-application.d.ts +50 -0
  141. package/dist/environment/operator-application.js +155 -0
  142. package/dist/environment/ports.d.ts +182 -0
  143. package/dist/environment/ports.js +1205 -0
  144. package/dist/environment/posture-observation.d.ts +68 -0
  145. package/dist/environment/posture-observation.js +253 -0
  146. package/dist/environment/read-composition.d.ts +27 -0
  147. package/dist/environment/read-composition.js +352 -0
  148. package/dist/environment/readiness-composition.d.ts +38 -0
  149. package/dist/environment/readiness-composition.js +130 -0
  150. package/dist/environment/reclaim.d.ts +333 -0
  151. package/dist/environment/reclaim.js +1835 -0
  152. package/dist/environment/repository-identity.d.ts +13 -0
  153. package/dist/environment/repository-identity.js +108 -0
  154. package/dist/environment/runtime-measurement-record.d.ts +38 -0
  155. package/dist/environment/runtime-measurement-record.js +111 -0
  156. package/dist/environment/runtime-measurement.d.ts +27 -0
  157. package/dist/environment/runtime-measurement.js +224 -0
  158. package/dist/environment/runtime-probe-residue.d.ts +43 -0
  159. package/dist/environment/runtime-probe-residue.js +148 -0
  160. package/dist/environment/runtime-probe.d.ts +72 -0
  161. package/dist/environment/runtime-probe.js +725 -0
  162. package/dist/environment/runtime.d.ts +505 -0
  163. package/dist/environment/runtime.js +2335 -0
  164. package/dist/environment/seed.d.ts +16 -0
  165. package/dist/environment/seed.js +43 -0
  166. package/dist/environment/selftest-application.d.ts +86 -0
  167. package/dist/environment/selftest-application.js +713 -0
  168. package/dist/environment/sensitive.d.ts +3 -0
  169. package/dist/environment/sensitive.js +48 -0
  170. package/dist/environment/setup-observation.d.ts +62 -0
  171. package/dist/environment/setup-observation.js +1473 -0
  172. package/dist/environment/setup.d.ts +43 -0
  173. package/dist/environment/setup.js +176 -0
  174. package/dist/environment/sibling-instructions.d.ts +33 -0
  175. package/dist/environment/sibling-instructions.js +224 -0
  176. package/dist/environment/sibling-registration.d.ts +45 -0
  177. package/dist/environment/sibling-registration.js +538 -0
  178. package/dist/environment/state.d.ts +371 -0
  179. package/dist/environment/state.js +2013 -0
  180. package/dist/environment/templates.d.ts +140 -0
  181. package/dist/environment/templates.js +685 -0
  182. package/dist/environment/tool-registration.d.ts +9 -0
  183. package/dist/environment/tool-registration.js +96 -0
  184. package/dist/environment/upgrade-application.d.ts +19 -0
  185. package/dist/environment/upgrade-application.js +175 -0
  186. package/dist/environment-exec/execute.d.ts +102 -0
  187. package/dist/environment-exec/execute.js +1175 -0
  188. package/dist/environment-exec/libexec-program.d.ts +6 -0
  189. package/dist/environment-exec/libexec-program.js +22 -0
  190. package/dist/environment-exec/verified-digest.d.ts +4 -0
  191. package/dist/environment-exec/verified-digest.js +16 -0
  192. package/dist/exact-keys.d.ts +7 -0
  193. package/dist/exact-keys.js +15 -0
  194. package/dist/fix-catalogue.d.ts +32 -0
  195. package/dist/fix-catalogue.js +60 -0
  196. package/dist/freshness.d.ts +29 -0
  197. package/dist/freshness.js +75 -0
  198. package/dist/generated-environment/adopt.d.ts +16 -0
  199. package/dist/generated-environment/adopt.js +275 -0
  200. package/dist/generated-environment/command.d.ts +47 -0
  201. package/dist/generated-environment/command.js +75 -0
  202. package/dist/generated-environment/transaction.d.ts +186 -0
  203. package/dist/generated-environment/transaction.js +1770 -0
  204. package/dist/grading/evaluate.d.ts +71 -0
  205. package/dist/grading/evaluate.js +403 -0
  206. package/dist/grading/grade.d.ts +33 -0
  207. package/dist/grading/grade.js +57 -0
  208. package/dist/guards/evaluator.d.ts +113 -0
  209. package/dist/guards/evaluator.js +1226 -0
  210. package/dist/guards/harness-adapter.d.ts +17 -0
  211. package/dist/guards/harness-adapter.js +57 -0
  212. package/dist/guards/host.d.ts +8 -0
  213. package/dist/guards/host.js +10 -0
  214. package/dist/guards/invocation-parser.d.ts +66 -0
  215. package/dist/guards/invocation-parser.js +595 -0
  216. package/dist/guards/local-identity.d.ts +40 -0
  217. package/dist/guards/local-identity.js +123 -0
  218. package/dist/guards/policy-pin.d.ts +13 -0
  219. package/dist/guards/policy-pin.js +175 -0
  220. package/dist/guards/protected-locations.d.ts +62 -0
  221. package/dist/guards/protected-locations.js +461 -0
  222. package/dist/guards/read-only.d.ts +37 -0
  223. package/dist/guards/read-only.js +315 -0
  224. package/dist/init/command.d.ts +40 -0
  225. package/dist/init/command.js +310 -0
  226. package/dist/init/derive.d.ts +51 -0
  227. package/dist/init/derive.js +715 -0
  228. package/dist/init/draft.d.ts +138 -0
  229. package/dist/init/draft.js +1205 -0
  230. package/dist/init/render.d.ts +35 -0
  231. package/dist/init/render.js +82 -0
  232. package/dist/init/scaffold.d.ts +53 -0
  233. package/dist/init/scaffold.js +121 -0
  234. package/dist/invocation.d.ts +13 -0
  235. package/dist/invocation.js +20 -0
  236. package/dist/package-metadata.d.ts +9 -0
  237. package/dist/package-metadata.js +19 -0
  238. package/dist/readiness.d.ts +53 -0
  239. package/dist/readiness.js +88 -0
  240. package/dist/references/named.d.ts +24 -0
  241. package/dist/references/named.js +27 -0
  242. package/dist/refusal.d.ts +15 -0
  243. package/dist/refusal.js +7 -0
  244. package/dist/registry-derivation.d.ts +31 -0
  245. package/dist/registry-derivation.js +32 -0
  246. package/dist/registry-resolve/command.d.ts +47 -0
  247. package/dist/registry-resolve/command.js +226 -0
  248. package/dist/registry-resolve/registry.d.ts +68 -0
  249. package/dist/registry-resolve/registry.js +292 -0
  250. package/dist/registry-resolve/render-shell.d.ts +18 -0
  251. package/dist/registry-resolve/render-shell.js +36 -0
  252. package/dist/repair.d.ts +29 -0
  253. package/dist/repair.js +8 -0
  254. package/dist/schema-json.d.ts +1 -0
  255. package/dist/schema-json.js +177 -0
  256. package/dist/schema.d.ts +1322 -0
  257. package/dist/schema.js +934 -0
  258. package/dist/setup/command.d.ts +4 -0
  259. package/dist/setup/command.js +4 -0
  260. package/dist/sha256.d.ts +1 -0
  261. package/dist/sha256.js +4 -0
  262. package/dist/surfaces/adoption.d.ts +41 -0
  263. package/dist/surfaces/adoption.js +217 -0
  264. package/dist/surfaces/consumer-instructions.d.ts +20 -0
  265. package/dist/surfaces/consumer-instructions.js +43 -0
  266. package/dist/surfaces/contract.d.ts +42 -0
  267. package/dist/surfaces/contract.js +169 -0
  268. package/dist/surfaces/core-declarations.d.ts +24 -0
  269. package/dist/surfaces/core-declarations.js +79 -0
  270. package/dist/surfaces/development-markers.d.ts +1 -0
  271. package/dist/surfaces/development-markers.js +18 -0
  272. package/dist/surfaces/generator-adapter.d.ts +71 -0
  273. package/dist/surfaces/generator-adapter.js +809 -0
  274. package/dist/surfaces/harness-registry.d.ts +180 -0
  275. package/dist/surfaces/harness-registry.js +117 -0
  276. package/dist/surfaces/mcp.d.ts +95 -0
  277. package/dist/surfaces/mcp.js +186 -0
  278. package/dist/surfaces/merge.d.ts +30 -0
  279. package/dist/surfaces/merge.js +105 -0
  280. package/dist/surfaces/ownership.d.ts +190 -0
  281. package/dist/surfaces/ownership.js +795 -0
  282. package/dist/surfaces/projection.d.ts +136 -0
  283. package/dist/surfaces/projection.js +681 -0
  284. package/dist/surfaces/render.d.ts +118 -0
  285. package/dist/surfaces/render.js +633 -0
  286. package/dist/surfaces/restrictions.d.ts +130 -0
  287. package/dist/surfaces/restrictions.js +447 -0
  288. package/dist/surfaces/selftest.d.ts +162 -0
  289. package/dist/surfaces/selftest.js +393 -0
  290. package/dist/surfaces/skill-contract.d.ts +85 -0
  291. package/dist/surfaces/skill-contract.js +449 -0
  292. package/dist/surfaces/sync.d.ts +57 -0
  293. package/dist/surfaces/sync.js +164 -0
  294. package/dist/team-metadata.d.ts +41 -0
  295. package/dist/team-metadata.js +512 -0
  296. package/dist/testing/gates.d.ts +91 -0
  297. package/dist/testing/gates.js +182 -0
  298. package/dist/testing/hooks.d.ts +59 -0
  299. package/dist/testing/hooks.js +139 -0
  300. package/dist/testing/verdict.d.ts +29 -0
  301. package/dist/testing/verdict.js +62 -0
  302. package/dist/work-orders/application.d.ts +99 -0
  303. package/dist/work-orders/application.js +383 -0
  304. package/dist/work-orders/composition.d.ts +124 -0
  305. package/dist/work-orders/composition.js +1010 -0
  306. package/dist/work-orders/contract.d.ts +61 -0
  307. package/dist/work-orders/contract.js +122 -0
  308. package/dist/work-orders/store.d.ts +158 -0
  309. package/dist/work-orders/store.js +197 -0
  310. package/docs/README.md +65 -0
  311. package/docs/architecture.md +136 -0
  312. package/docs/capability-matrix.md +50 -0
  313. package/docs/cli-reference.md +599 -0
  314. package/docs/command-list.md +51 -0
  315. package/docs/compose-patterns.md +99 -0
  316. package/docs/concepts.md +171 -0
  317. package/docs/configuration-essentials.md +172 -0
  318. package/docs/configuration-reference.md +621 -0
  319. package/docs/environment.md +760 -0
  320. package/docs/extending.md +43 -0
  321. package/docs/faq.md +111 -0
  322. package/docs/getting-started.md +608 -0
  323. package/docs/harness-surfaces.md +433 -0
  324. package/docs/joining-a-team.md +76 -0
  325. package/docs/release-policy.md +49 -0
  326. package/docs/safety-and-autonomy.md +419 -0
  327. package/docs/troubleshooting.md +361 -0
  328. package/docs/tutorial.md +170 -0
  329. package/docs/work-and-browser.md +254 -0
  330. package/libexec/browser-operation.cjs +186 -0
  331. package/libexec/fence-marker.cjs +101 -0
  332. package/libexec/fence-marker.d.cts +24 -0
  333. package/libexec/fenced-group-runner.cjs +77 -0
  334. package/libexec/fenced-supervisor.cjs +137 -0
  335. package/libexec/generated-filesystem.cjs +731 -0
  336. package/libexec/install-filesystem.cjs +225 -0
  337. package/libexec/rulesync-generator.NOTICE.md +1112 -0
  338. package/libexec/rulesync-generator.cjs +743 -0
  339. package/libexec/surface-generator-worker.cjs +266 -0
  340. package/libexec/surface-output-reader.cjs +99 -0
  341. package/libexec/surface-scratch-cleanup.cjs +14 -0
  342. package/libexec/validate-harness-evidence.d.mts +183 -0
  343. package/libexec/validate-harness-evidence.mjs +1312 -0
  344. package/package.json +74 -4
  345. package/surfaces/README.md +33 -0
  346. package/surfaces/agents/evaluator.agent.md +76 -0
  347. package/surfaces/guards/bash-guard.sh +48 -0
  348. package/surfaces/guards/claude.adapter.json +25 -0
  349. package/surfaces/guards/codex.adapter.json +24 -0
  350. package/surfaces/guards/opencode.adapter.json +25 -0
  351. package/surfaces/references/browser.md +63 -0
  352. package/surfaces/references/test-data-and-personas.md +84 -0
  353. package/surfaces/references/testing-tiers.md +11 -0
  354. package/surfaces/skills/cockpit-browser.skill.md +54 -0
  355. package/surfaces/skills/cockpit-explain.skill.md +32 -0
  356. package/surfaces/skills/cockpit-fix.skill.md +37 -0
  357. package/surfaces/skills/cockpit-setup.skill.md +39 -0
  358. package/surfaces/skills/cockpit-work.skill.md +34 -0
  359. package/surfaces/skills/collection.json +5 -0
  360. package/surfaces/skills/procedures/explain.md +61 -0
  361. package/surfaces/skills/procedures/fix.md +81 -0
  362. package/surfaces/skills/procedures/setup.md +379 -0
  363. 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.