crewship credential
Manage credentials (API keys, tokens, secrets) used by AI agents.crewship cred
Subcommands
crewship credential list
List all credentials in the workspace.
SOURCE column shows who owns the row: user (operator-created via UI/CLI), system (auto-managed rows minted by manifest dispatch), or agent. When a row is provisioned for a service, the service slug is suffixed (e.g. system (github-bot)).
Without
--limit, the paged request uses a page size of 100. If more results
remain, the next cursor is printed to stderr.
crewship credential get
Show credential details. The credential value is never displayed.
crewship credential create
Create a new credential. The value is validated against the provider API before saving.
Credential values are validated against the provider API automatically. If validation fails, you are prompted to confirm saving. OAuth tokens (
sk-ant-oat*) and SECRET type credentials skip validation.An OpenAI-compatible endpoint
A self-hosted or internal gateway that speaks the OpenAI wire format is stored as one credential: the endpoint and the key together, under providerOPENAI_COMPAT.
{baseURL, apiKey, headers} object, which
is the same shape an authenticated ENDPOINT_URL credential already used. The key
is delivered to the agent’s sidecar, which writes it into the outbound
request; it is not written into the agent’s environment. crewship provider route show OPENAI_COMPAT prints the route it
will take.
Four consequences to know before you create one:
-
The endpoint must carry auth material of some kind to be isolated. A
bearer token, custom headers, or both — any of these routes the credential
through the sidecar, which writes them into the outbound request so they never
enter the container. An endpoint with no auth at all stays unrouted: there is
nothing to isolate, and routing it would put a failure in front of a path that
works.
crewship crew inspectreports which of the two a run got. -
Calls bill at $0.
OPENAI_COMPAThas no rate row — Crewship cannot know what your endpoint charges — so cost-ledger rows for it are zero.crewship provider route listmarks it(unpriced)for exactly this reason. A $0 spend line for these calls is the truth, not a cheap month. -
One active credential set per crew sidecar. Agents with the same resolved
credentials safely reuse it: each request carries a self-verifying,
crew-bound route token for attribution. A key rotation or different set
forces a restart. If an older concurrent run then sends a request, its
credential fingerprint no longer matches and the sidecar returns
403/503instead of silently sending the prompt to the other endpoint or key. This is fail-closed, not full concurrent multi-tenant storage: two overlapping agents in one crew that require different endpoints may need a retry after the restart. Scope heavily concurrent, different endpoints to separate crews until #2052 adds independent per-agent stores. The fingerprint is what carries that guarantee, andcrewshipdalways has one: the internal token it is keyed on is filled in at startup from yourauth.internal_token, else derived fromENCRYPTION_KEY, else a fresh random for the boot. There is no configuration that turns this off, so nothing here asks you to switch it on. It matters only if you run a sidecar Crewship did not launch. A sidecar started without a fingerprint accepts a correctly signed route token from any agent in the container, because there is no configuration identity to compare against — a forged or malformed token is still rejected. The server logs a one-timesidecar credential isolation is fail-openwarning if it ever reaches that state itself; that would mean a build bypassing the normal startup path, so report it rather than trying to reconfigure around it. -
The endpoint and the key are one stored object, so a full-value rotate
replaces both. Pipe the whole object in rather than passing it on the command
line:
To rotate only the key and keep the endpoint, use the field-by-field form. The server merges the fields you send over the stored value and leaves the rest alone, which is what you want for a routine key rotation:
--auth-token-stdinrather than--auth-token, for the same reason--value-stdinexists: an argument is readable by anything that can see the process table while the command runs, and it lands in your shell history. The--auth-tokenflag still works and is fine for a throwaway value, but do not use it for a key you intend to keep. Secrets are never readable, so the merge has to happen server-side — the CLI cannot read the current key back in order to resend it.
crewship credential test-stored self-hosted-llm does dial it
(#2043). Two separate things make that safe, and only the second is a network
control: the path is role-gated, so an arbitrary caller cannot reach it, and the
dial itself goes through the guarded probe — the address is checked after DNS
resolution, so a link-local or cloud-metadata target is refused even when the URL
is perfectly well-formed, and redirects are never followed. A URL that passed
create-time validation is not thereby a safe one to dial; shape validation says
nothing about where a name resolves. It reports reachability — DNS, TLS, a wrong
path prefix, a gateway serving no model list — and deliberately not
authentication: the probe sends no apiKey and no custom headers, because
whoever can edit the credential can repoint baseURL, and a Test button that
posts the stored secret to that host would be a way to exfiltrate it. A key that
is present but wrong shows up on the first agent call.
--base-url on any other provider is a local validation error, exit 2:
crewship credential update
Update a credential. Only changed flags are sent.
crewship credential delete
Delete a credential.
crewship credential assign
Assign a credential to an agent. The credential is injected as an environment variable into the agent’s container.
crewship credential unassign
Remove a credential from an agent.
crewship credential field
Manage custom fields in addition to a credential’s main value. The parent has
the alias fields; subcommands are list, set, and remove (rm and
delete are aliases for remove). Secret field values are never returned.
field set flags are --value, --value-stdin, --plain, and --ordinal.
Keys must be lower_snake_case. Without --plain, a field is encrypted and
shown only as (secret) by field list; --plain is for identifiers such as
regions, account IDs, and hosts.
crewship credential bind
Bind a credential to an environment variable slot in one scope.
The credential’s name is the account (github-acme); the slot is what the agent reads (GH_TOKEN). Keeping them apart is what lets one workspace hold ten GitHub accounts — ten crews can each bind GH_TOKEN to a different one.
No scope flag means workspace scope.
--crew and --agent are mutually exclusive: a binding has exactly one scope.
Within a scope a slot points at exactly one credential — binding a slot that is already taken returns 409 Conflict instead of replacing the existing row. Binding the same slot in a different scope is not a conflict.
crewship credential bindings
The command also accepts the alias crewship credential binding-list.
List bindings in the workspace.
crewship credential unbind
Remove a binding, by id or by naming the slot and scope.
crewship credential resolve
Show the slot map one agent will actually boot with, and which rule produced each row. Values are never shown.
agent_grant (an explicit credential assign), agent_binding, crew_binding, workspace_binding, crew_link (no binding — delivered under the credential’s own name).
crewship credential test
Test a credential value against the provider API without saving it.
crewship credential test-stored
Re-test an already-saved credential against the provider API without re-supplying the value. Useful for verifying that a rotated key still works, or that a long-lived token has not been revoked upstream.
valid: true; otherwise the error message from the provider is printed.
Crewship maintains upstream probes for Anthropic, OpenAI, Google, OpenRouter, Cursor, Factory, GitHub, GitLab and Vercel, plus any ENDPOINT_URL credential. Each of those authenticates against the provider, so a pass means the key itself works.
OPENAI_COMPAT is probed here too (#2043), and it is the one that answers a different question. Because its endpoint is operator-supplied, this command asks whether the host is reachable and serving a model list — it sends no apiKey and no custom headers, so a pass means the endpoint is live and correctly addressed, not that the key is accepted. A wrong key surfaces on the first agent call.
For every other provider there is nothing to call — the agent talks to that API directly and Crewship holds only the secret. Those credentials report not checked rather than valid, and exit 0:
crewship credential rotate
Requires OWNER/ADMIN role, or the credential.rotate capability (grantable to a MANAGER/MEMBER so an oncall user can rotate a leaked token without full vault access). The new value is capped at 64 KiB.
Issue a new value for the credential. The old value is preserved on the rotation row for the grace window (max 7d) so in-flight agents that cached the old key can still fall back during their run, then the old value is scrubbed.
The cobra default for --grace-seconds is 0, but the flag is only sent when you explicitly set it. Omit the flag and the server applies its standard 24h grace. Pass --grace-seconds 0 to force an immediate cutover (no overlap). Pass any positive value (up to 604800 / 7d) to set a custom window.
crewship credential rotations
List rotation history for a credential.
crewship credential rotation-cancel
End an ACTIVE rotation’s grace window immediately and scrub the old value. EXPIRED / CANCELLED rotations are no-ops on the server side (idempotent 200).
crewship credential audit
Show the full credential timeline — the same view the detail Sheet’s Audit tab uses. Useful for grep-ing for ROTATE / TEST / REVOKE events without scraping the UI.
crewship credential default-env-var
Print the conventional env var name for a provider (GH_TOKEN, GITLAB_TOKEN, VERCEL_TOKEN, …). Useful when scripting credential assign and you don’t want to memorise every provider’s convention.
This is a suggestion, not a rule. Crewship accepts any provider string; one it has no convention for simply prints nothing and exits non-zero, and you pass
--env-var-name yourself. Every name below is the variable the vendor’s own CLI or SDK documents reading.DOCKER, TERRAFORM, ANSIBLE, CUSTOM_CLI and NONE are recognised providers with no entry: the docker CLI authenticates through ~/.docker/config.json rather than an env var, and HCP Terraform’s token variable is host-suffixed (TF_TOKEN_<hostname>), so any single value here would be invented.
crewship credential reveal
Disclose a credential’s plaintext value.
- an OWNER has enabled reveal for the workspace (
crewship credential reveal-policy --enable) - your membership carries the
credentials:revealcapability — being OWNER or ADMIN is necessary but not sufficient, and the capability is in no role bundle - you are MANAGER or above; a MANAGER is additionally limited to credentials in their own crews
- the credential is not
SEALED(seesensitivity) - your
--reasonis at least 20 characters and not a generic placeholder - the reveal can be written to the tamper-evident audit chain — if that write fails the command gets a
500and no value
The endpoint has its own per-IP rate limit (
http.cred_reveal_per_min, default 3/min), and unlike the general API bucket, authenticated CLI callers are not exempt from it.
crewship credential reveal-policy
Show or set the workspace credential-reveal switch. Reveal is off for every workspace — including newly created ones — until an OWNER turns it on.
403, because whether a tenant has reveal enabled is useful to an attacker choosing a target. Changing it requires OWNER.
Both directions are written to the tamper-evident audit chain before taking effect: if the audit write fails, the switch does not move.
Enabling the switch grants nobody reveal on its own. Each person still needs
the
credentials:reveal capability on their membership. The recommended
corporate default is two people holding it, not the whole admin team.crewship credential sensitivity
Set a credential’s classification. It is the first thing the reveal gate consults and the only layer no role can override.
Raising a classification is a MANAGER+ action and takes effect immediately — it only ever removes reach, so it needs no ceremony, and a control that is annoying to tighten stops being used. Lowering requires OWNER or ADMIN and is written to the audit chain first: it hands out a key that did not exist a moment earlier, and it is the cheap move for an attacker holding an admin session.
SEALED has no escape hatch on purpose. To get a usable value out of a sealed credential, rotate it — crewship credential rotate mints a new one and shows it once.
Existing credentials are STANDARD, which is safe only because the workspace reveal switch defaults to off.
RESTRICTED behaves like STANDARD today. The four-eyes second-approver flow
that will distinguish them is deferred, but classifying now still pays off —
that gate will key off this field.