kind: CrewTemplate
What it is
ACrewTemplate is a deploy-only reference kind. The manifest entry instantiates an existing template (creating a new crew + its agents from the template’s blueprint) but cannot author the template itself. Template authoring belongs to the seeded built-in catalog under internal/database or to direct workspace inserts into the crew_templates table — both outside the manifest pipeline.
In other words: a CrewTemplate document is the YAML equivalent of clicking “Deploy” on a card in the templates UI.
One-shot semantics — there is no update flow
The backend endpoint behind this kind is:errCrewSlugConflict). There is no PATCH /deploy, no DELETE /deploy, and no diff-and-reapply path. Once a crew exists under the crew_slug_override slug, this kind has nothing left to do.
As a consequence the planner emits only two actions:
Idempotency is by slug alone. Thecrewstable has notemplate_slugprovenance column, so a pre-existing crew whose slug happens to equalcrew_slug_overrideis treated as “already deployed” — even if it was actually created by hand viakind: Crew. By design: the server would 409 on the deploy POST anyway, and the manifest’s job is to converge to “a crew with this slug exists”, not to enforce who created it.
deploy: falseis inert. Settingdeploy: falsedoes not trigger an “undeploy”. There is no inverse endpoint. To remove a crew that came from a template, delete it viakind: Crew(orcrewship crew delete <slug>). The CrewTemplate planner records intent and surfaces a warning in dry-run output so the no-op is visible.
YAML schema
Field reference
Examples
Minimal example — deploy a built-in template
Deploy the same template twice under different override slugs
A single template can back many crews —crew_slug_override distinguishes them:
eng-team-a and eng-team-b exist. Re-applying the same bundle is a pure Unchanged plan (no HTTP traffic to the deploy endpoint).
Deploy with inputs (forward-compatible)
inputs map is currently ignored server-side; future versions of the deploy handler may consume specific keys. Manifest authors can include them today without breaking compatibility.
deploy: false — pin without re-applying
Unchanged with a warning. Useful for keeping a CrewTemplate document in a versioned bundle for documentation purposes while temporarily disabling automatic deploys.
CLI reference
The crew-template surface has a dedicated CLI undercrewship template … (no hyphen — registered as templateCmd in cmd/crewship/cmd_template.go); manifest-level apply does not add new subcommands beyond the global apply / export.
REST endpoint mapping
POST body shape
The deploy handler (internal/api/crew_templates.go) reads two fields and tolerates extras:
crew_name→metadata.name. Server 400s on empty.crew_slug→spec.crew_slug_override. Server slugifies + validates; collision returns 409.inputs→ forwarded but currently unused. Forward compatibility hook.
DB columns touched (informational)
The deploy handler writes one row tocrews (id, workspace_id, name, slug, icon, color, timestamps) and N rows to agents (one per template agent, with agent_slug = template_agent.slug + "-" + crew_slug). It does not record provenance — there is no crews.template_slug column.
Validation rules
Validate (offline, no HTTP) enforces:
apiVersionmust be empty orcrewship/v1.kindmust be empty orCrewTemplate.metadata.nameis non-empty (sent ascrew_name).metadata.slugis non-empty (source template slug; existence is checked at Plan time).spec.crew_slug_overrideis non-empty.spec.crew_slug_overridematches^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$(kebab-case, no leading/trailing hyphen, no underscores, no uppercase).
metadata.slug actually exists in GET /api/v1/crew-templates) is not checked at validate time — WorkspaceContext does not carry remote templates. The check is deferred to Plan, where the live HTTP client is available, and surfaces as a transparent “source template not found” error in dry-run output.
Apply behavior
Default (ApplyUpsert)
Plan decision table:
ApplyStrict
Strict mode adds no extra constraints for this kind. A crew already occupying the override slug is not a strict-mode error — it is the expected Unchanged outcome. Strict mode only fires for kinds whose backend supports re-creation; deploy is one-shot, so strict semantics collapse onto upsert semantics.
ApplyReplace
Replace mode is also a no-op for the deploy itself: there is no DELETE endpoint at /api/v1/crew-templates/{slug}/deploy, so even “destructively recreate” cannot undeploy the existing crew. To remove a crew before re-deploying, declare a kind: Crew document with the same slug and delete it via that kind’s Replace semantics, or use crewship crew delete <slug> first. When the backend grows an inverse deploy verb this kind will start emitting Delete + Create pairs in Replace mode without any YAML schema change.
Round-trip via export
Provenance gap
Thecrews schema has no template_slug column today. The deploy handler writes the crew row without recording the source template. There is therefore no authoritative way to round-trip a deployed crew back into a kind: CrewTemplate document.
ExportCrewTemplates makes a best-effort heuristic match: a crew whose slug exactly equals a known template’s slug is reported as a CrewTemplate deployment with crew_slug_override = crew.slug. Crews whose slugs diverge from any template slug — the common case, since operators usually rename — are not exported as CrewTemplate; they round-trip via kind: Crew instead.
This means an export → wipe → re-apply cycle re-creates renamed crews as raw
Crew documents, not template deployments — losing the “deployed from X” semantic but preserving the actual state of the world.
When/if the server grows a template_slug column on crews, the heuristic in ExportCrewTemplates switches to an exact provenance check; the public Export* signature stays the same.
Emitted document shape
For each match, the export produces:CrewTemplate doc is a pure Unchanged plan (the crew is already there).
See also
docs/manifest/recipe.md— sibling install-only reference kind.docs/manifest/connector.md— sibling install-only reference kind (integrations).internal/api/crew_templates.go— backend handler forGET /api/v1/crew-templates,GET /api/v1/crew-templates/{slug},POST /api/v1/crew-templates/{slug}/deploy.internal/database/seed_crew_templates.go— source of truth for built-in templates that ship with the binary.internal/manifest/kinds/crew_template.go— this kind’s Go implementation.