Skip to main content

kind: Connector

What it is

A Connector installs an entry from the server-side connector catalog (Linear, GitHub, Slack, …) into the current workspace. The manifest cannot define new connector types — connector authoring lives in internal/connectors/fixtures/*.yaml, baked into the binary. What the manifest CAN do is:
  • Mark a catalog entry as installed in this workspace (spec.install: true).
  • Bind the connector’s expected runtime env-vars to the names of workspace credentials that satisfy them (spec.credentials).
  • Drift back to uninstalled (spec.install: false) where the server endpoint exposes a delete verb — best-effort; if the catalog entry has no DELETE handler the planner degrades to Unchanged with a warning.
This makes Connector an install-only reference kind, alongside Recipe and CrewTemplate. The distinction matters when authoring a manifest:
  • Full-CRUD kinds (Project, Label, Milestone, …) let the manifest describe shape and trigger create/update/delete.
  • Reference kinds express intent only (“this connector should be installed and wired to these credentials”); the underlying schema is owned by the server catalog.
The catalog connector id (e.g. linear, github, slack) is the metadata.slug. Apply matches it against GET /api/v1/connectors.

YAML schema

Field reference

Credential mapping — how to think about it

The mapping is directional, but both sides are env-var names.
The left-hand side is fixed by the connector — the catalog manifest declares which env vars the connector binary expects. You can see them on GET /api/v1/connectors/{slug} under required_credentials. The right-hand side is yours. Each value names a workspace credential (a Credential kind, or an existing row in credentials.name). At install time the server resolves that name → decrypted value → env-var injection into the connector’s MCP runtime. Both halves must be valid POSIX env-var names (^[A-Za-z_][A-Za-z0-9_]*$). Validate enforces this at parse time so a typo on either side fails fast rather than blowing up at runtime with a mysterious “credential not found”.

Examples

Minimal example — connector with no required credentials

Realistic example — Linear with an API-key binding

LINEAR_PROD_KEY here refers to a workspace credential row whose name column equals LINEAR_PROD_KEY. You either declare it earlier in the same manifest (kind: Credential) or it already exists in the workspace from a previous apply / UI action.

Cross-kind reference — credential declared in the same bundle

Apply orders Phase 1 (Workspace credentials) before Phase 11 (Connectors), so a credential declared in the same multi-doc manifest will be on the server by the time the connector install runs.

Uninstall intent

The planner issues DELETE /api/v1/connectors/linear/install. A 404/405/501 from that endpoint is treated as “catalog entry doesn’t support uninstall” and the plan item is reported as Unchanged with a description flagging the manual cleanup — Apply does not fail on the remainder of the bundle.

CLI reference

Connector is driven by the generic crewship apply / crewship export commands; there is no per-kind crewship connector … subcommand because the install verb is a single-shot operation that the standard manifest flow already covers end-to-end. For interactive exploration use the existing connectors API directly:
The UI page /connectors wraps the same endpoints.

REST endpoint mapping

The credential map is wire-equivalent to what the POST /api/v1/connectors/{id}/install handler reads off the request body. See internal/api/connectors_handler.go for the canonical Go shape.

Validation rules

These run at parse time, before any HTTP traffic:
  • metadata.name is non-empty.
  • metadata.slug is non-empty.
  • For every entry in spec.credentials:
    • The key matches ^[A-Za-z_][A-Za-z0-9_]*$ (POSIX env-var name).
    • The value matches the same env-var regex.
    • The value is not empty / whitespace-only.
These run at Plan time (one HTTP round-trip):
  • metadata.slug exists in GET /api/v1/connectors. A 404 surfaces as connector slug "X" is not in the catalog so the user can spot the typo immediately.
  • Every entry in the catalog entry’s required_credentials array has a corresponding key in spec.credentials. Missing entries produce an Action=Create plan item whose Exec returns an error before any HTTP call (so dry-run sees the failure too).
These run inside the install Exec (defer-failure semantics so credentials declared earlier in the same bundle have a chance to land in Phase 1):
  • Every workspace credential name on the right-hand side of spec.credentials exists in GET /api/v1/credentials. Missing names abort the install before the POST goes out, with an error that names the missing credential.

Apply behavior

The kind plans against the catalog detail and the workspace credential list to decide one of four outcomes: ApplyUpsert (default): runs the table above. ApplyStrict: same as upsert. Connector installs are idempotent at the catalog level; Strict doesn’t add an “already-installed = error” arm because the install endpoint itself is idempotent and connector catalog entries are not workspace-unique resources. ApplyReplace: connectors do not participate in the delete-then-recreate pass. The install is already a “force overwrite” verb at the server level, so a Replace on a connector entry just re-runs the Create branch.

Round-trip via export

crewship export workspace walks GET /api/v1/connectors and emits one kind: Connector document for every entry whose installed=true. Uninstalled catalog entries are dropped — emitting them as install: false would explode the bundle by one doc per global catalog connector with no useful state preserved. The credential mapping is exported empty today (credentials: {}) because the current server does not echo the per-install mapping back in the GET response. The exported document round-trips structurally (same slug, same install flag); re-applying it without re-filling the credential map is a no-op when the connector is already installed and an error when it is not. Future server work that surfaces the binding back through the API will make the round-trip lossless without a YAML schema change.

See also

  • kind: Recipe — sister install-only reference kind.
  • kind: CrewTemplate — deploys a packaged crew rather than wiring a single integration.
  • Your First Crew — defines workspace credentials a connector can bind to.
  • Backend handler: internal/api/connectors_handler.go.
  • Catalog fixtures: internal/connectors/fixtures/*.yaml.