Help us improve
Share bugs, ideas, or general feedback.
From Captain's Cabinet
Onboarding interview for a new Cabinet deployment. Use when a captain sets up this repo for the first time (or adds/changes lanes) — interviews for captain profile, lanes, org shape, autonomy posture, and seed outcomes, writes instance/config/cabinet-init.answers.yml, runs cabinet/scripts/generate-instance.py, and prints the exact activation steps. Idempotent on re-run.
npx claudepluginhub nate-step/captains-cabinet --plugin captains-cabinetHow this skill is triggered — by the user, by Claude, or both
Slash command
/captains-cabinet:cabinet-initThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
You are interviewing the captain sitting in this Claude Code session and
Provides UI/UX resources: 50+ styles, color palettes, font pairings, guidelines, charts for web/mobile across React, Next.js, Vue, Svelte, Tailwind, React Native, Flutter. Aids planning, building, reviewing interfaces.
Fetches up-to-date documentation from Context7 for libraries and frameworks like React, Next.js, Prisma. Use for setup questions, API references, and code examples.
Explores codebases via GitNexus: discover repos, query execution flows, trace processes, inspect symbol callers/callees, and review architecture.
Share bugs, ideas, or general feedback.
You are interviewing the captain sitting in this Claude Code session and
turning their answers into this deployment's instance/ configuration.
The repo stays UNIVERSAL — everything captain- or lane-specific lands
only under instance/ (and secrets only in the gitignored
cabinet/.env). Nothing you generate activates anything: contexts ship
active: false, projects ship activation.status: pending, outcomes
ship status: draft, and officers start only when the captain runs the
printed deploy steps.
Idempotency: safe to re-run any time (new lane, changed boards, renamed captain). The answers file is the single input; the generator overwrites only files it generated before (marker-checked), never hand-authored ones. Before appending outcomes, check for existing ids.
Work through the six phases in order. Ask conversationally, batch related questions, and confirm the assembled answers back before generating. If an answers file already exists, load it first and only ask about gaps/changes.
Collect:
Ada).Europe/Madrid). All officer
communication renders times in it.chat_id after the bot exists —
leave it for a re-run rather than guessing.A lane is a product/venture/area the Cabinet works (see
docs/work-model.md — products are lanes, not outcomes). Per lane:
Acme Storefront) and slug (kebab-case,
e.g. acme-store — becomes the context slug and the <slug>-ceo
role id).org/name or URL; first repo becomes product.repo.plugin:dev-tasks with board ids,
linear with a team key, github-issues, or none. When the route
is a plugin, the project file deliberately carries NO tasks block —
just a comment saying so (avoids duplicate adapters).cos, single bot, the only human
surface) + one on-demand lane-CEO consultant per lane, generated from
presets/portfolio/agents/_lane-ceo.md.template. Functional depth
comes from hats + Sonnet crew, not extra officers.work preset; no per-lane roles
generated.presets/_template/).State it, don't ask it:
Every lane starts propose-first: actions touching the captain's world are proposed and approved before they apply. On top sits the hard ceiling that never lifts regardless of graduation — secrets, spend, external communications, and production deploys are ALWAYS propose-only.
Autonomy is earned later, per lane, from evidence: the consequence ledger (
docs/consequence-ledger.md) records every action's proposal decision, outcome, and review verdict; graduation math reads only that ledger. There is nothing to configure today — good behavior under the gate IS the configuration.
Record autonomy.posture: propose_first in the answers and move on.
Interview each lane for at most 1–2 campaigns, applying both tests
from docs/work-model.md before accepting one:
Zero seed outcomes for a lane is healthy (officers work the stream).
For each accepted campaign, append an entry to
instance/config/outcomes.yml.draft (create the file with a short
header pointing at framework/schemas/outcome.schema.json and
docs/work-model.md if it doesn't exist) with:
status: draft, captain_ratified: false — the captain ratifies
per outcome later; the compiler ignores drafts.measurable_criteria as rich nodes where you can (owner_role,
acceptance_criteria, evidence_required, verifier_role, risk_level);
owner/verifier use the generated role ids (<slug>-ceo, cos).risk_level: high with an explicit PROPOSE-ONLY acceptance line.On re-run: never duplicate — skip ids that already exist in the draft. Validate the draft parses against the schema before finishing.
Walk it with the captain; config carries env-var NAMES and TOKEN-TBD
placeholders only:
/newbot), record the bot USERNAME in the answers, and
put the token ONLY in cabinet/.env under the chosen env-var name —
canonical: TELEGRAM_<OFFICER_UPPER>_TOKEN (e.g.
TELEGRAM_COS_TOKEN=...; legacy TELEGRAM_BOT_TOKEN_<UPPER> still
resolves as a fallback). Never reuse a token another
poller uses — two pollers on one token steal each other's updates.
Optional warroom group: create the group, invite the bot, store the
group chat id env name the same way.bash cabinet/scripts/grant-mac-permissions.sh — interactive; the
OS requires human clicks. This and the bot token are typically the
only captain-blocking steps.integrations.mcp_env_names; values go in cabinet/.env
(chmod 600, gitignored). bash cabinet/scripts/setup-env.sh walks
key entry interactively.Write the assembled answers to
instance/config/cabinet-init.answers.yml. Schema (also available
via python3 cabinet/scripts/generate-instance.py --example):
version: 1
captain: {name, timezone, telegram_chat_id}
cabinet: {id, mode: single|multi, org_shape: portfolio|functional|custom, officer_model}
lanes:
- {name, slug, repos: [], task_system, boards: [],
neon_project, vercel_project, # NAMES only
linear_team_key, linear_workspace_url} # when task_system: linear
autonomy: {posture: propose_first} # fixed at init
integrations:
telegram: {ceo_bot, bot_token_env} # username + ENV VAR NAME
mcp_env_names: [] # ENV VAR NAMES
Run the generator and show the captain its output:
python3 cabinet/scripts/generate-instance.py # add --dry-run to preview
It generates (portfolio shape): per-lane
instance/config/contexts/<slug>.yml + projects/<slug>.yml,
instance/agents/<slug>-ceo.md (rendered from the lane-CEO
template), the marked officers: block + captain keys in
instance/config/platform.yml, and instance/config/roster.yml
for bootstrap-roles.sh --roster. It refuses path escapes,
secret-shaped values, and clobbering hand-authored files, and
validates every written YAML.
Relay the generator's printed list, expanded:
echo <preset> > instance/config/active-preset (portfolio /
work / custom preset slug).<slug>-ceo under agents: in cabinet/mcp-scope.yml
and add its capability rows to cabinet/officer-capabilities.conf.cabinet/.env under the recorded env-var name
(canonical TELEGRAM_<OFFICER_UPPER>_TOKEN, e.g.
TELEGRAM_COS_TOKEN; config keeps TOKEN-TBD). Multi-cabinet
deployments also set CABINET_MODE=multi + CABINET_ID=<id> in
cabinet/.env — in multi mode boot aborts without a CABINET_ID,
and the outcomes deployment gate compiles missions only when
CABINET_ID matches.bash cabinet/scripts/bootstrap-roles.sh --roster instance/config/roster.yml
(functional shape: plain bootstrap-roles.sh; add --prune to
retire roles left over from a previous roster).bash cabinet/scripts/grant-mac-permissions.sh (TCC, interactive).bash cabinet/scripts/load-preset.sh, then deploy selectively —
deploy-mac.sh for the coordinating role only; lane CEOs are
on-demand consultants and need no persistent deploy.instance/config/outcomes.yml pinned to another deployment via its
top-level deployment: key — the compiler refuses any file whose
deployment value differs from this machine's CABINET_ID, so a
pinned file is inert everywhere else (the repo no longer ships an
outcomes.yml.draft; the draft file from phase 5 is just this
interview's staging scratch). A new deployment REPLACES the shipped
outcomes.yml with its own ratified outcomes (status: active +
captain_ratified: true) carrying its own CABINET_ID as the
deployment key — or no deployment key at all for a single-cabinet
setup.Close by restating what is and isn't live: roles seeded, nothing polling, no lane active, no outcome compiled — each activation is a separate explicit captain action.