crewship crew
A crew is a team of AI agents that share one runtime container and a common Shared Ship volume. Use these commands to create and tune crews, manage members and cross-crew connections, wire up MCP servers, drive the devcontainer build pipeline (provision, rebuild, cache), and read or write files in the crew’s shared workspace.Subcommands
crewship crew list
List all crews in the workspace.
Output columns: SLUG, NAME, AGENTS, NETWORK, MEMORY, CPUS (plus runtime/cached-image/provisioning columns when
--runtime is set).
crewship crew get
Show detailed information about a crew.
crewship crew create
Create a new crew.
Sizing a crew
--memory-mb and --cpus are checked by the server against two
different floors.
The hard floor is Docker’s own — 6 MB and 0.01 CPU. The daemon
refuses to create a container below either, so a value under them comes
back as a 400 naming the field. Failing here is strictly better than
failing at wake time, where the daemon’s own error (“Range of CPUs is
from 0.01”) names neither the crew nor the field and every run wedges on
it. The --cpus ceiling cannot be fully validated server-side, because
the daemon’s real upper bound is the host’s core count.
The usable floor is advisory — 2048 MB and 0.5 CPU by default.
A crew sized between the two is created, and the CLI prints a
warning:
0.5 CPU is a quarter of the shipped 2.0 default — the CPU limit is a
hard quota, so a smaller fraction stretches toolchain startup
proportionally, past the run timeout.
This is a warning rather than a refusal because a small crew can be a
deliberate choice, and refusing does not make an undersized crew any
bigger — it only stops it existing. Memory is a cgroup ceiling, not a
reservation, so sizing every crew at the floor does not commit that much
RAM on an idle host.
Moving the floor. Both values are instance settings, so an operator
who knows their workload can change them:
runtime.agent_min_memory_mb warns earlier and lowers every
crew’s concurrency budget; lowering it does the reverse. A value that
does not parse, or that falls outside the hard bounds, is ignored in
favour of the default.
On upgrade: crews that were set to
0 change size. crewship crew update --memory-mb 0 used to store the literal 0 instead of resolving it, and the
runtime then substituted its own fallback of 8192 MB — twice the documented
default, and 2.0 CPUs became a fallback too. Those rows are corrected on
first boot after this release, so an affected crew moves from an effective
8192 MB to the 4096 it always said it had, and its concurrent-run budget
goes from 1 back to 2. Crews with an explicitly configured size are not
touched. Run crewship crew get <slug> to see where a crew landed, and
--memory-mb <n> if it needs more.Host capacity
A crew’s own size says nothing about whether the host can afford to start its container. Twenty crews waking on the same cron minute used to start twenty containers in parallel; the only limit in the product sat inside the run, after every one of those containers already existed. Crewship now holds a container start — before the container is created — while the host cannot afford another one, and starts it when it can. A held start is not a failed one and not a hung one;crewship capacity shows what
is being held and why, and crewship now says so on its status board.
crewshipd, and enough page cache that the host stays
responsive.
Why starts are staggered. Creating a network namespace takes a single
global kernel lock whose cost grows steeply with concurrency — measured at
1.45 ms serial and ~418 ms at 24× concurrency on a production fleet. Spreading
a twenty-crew wake over a few seconds makes every start in it cheaper than
firing them together would.
The host-memory signal is read from
/proc/meminfo and
/proc/pressure/memory, which exist on Linux only. On macOS — where the
apple container provider runs — the host-memory gate is inactive, and
crewship capacity says so rather than reporting a gate that is quietly doing
nothing. The concurrency bound and the stagger still apply there; they need no
kernel file. /proc/pressure/memory additionally requires a kernel built with
CONFIG_PSI; where it is absent the pressure veto simply never fires, and is
never treated as infinite pressure.docker pause is one write
to cgroup.freeze and the cgroup keeps every page.)
Idle crews are stopped
A crew container that has done nothing for 4 hours is stopped. That is the server default, applied to any crew whose--ttl was never set; set
--ttl <hours> to change it for one crew, or --ttl 0 to opt that crew out
entirely. crewship crew get shows which of the three states a crew is in:
Nothing is lost when a container stops.
/workspace, /output and /crew
are host-persistent mounts and survive; the writable layer and volumes
survive; only running processes and the scratch tmpfs (/tmp, /secrets)
do not. The next wake starts the container again, which costs a few hundred
milliseconds — less than the model round trip of the run that triggered it.
A busy container is never stopped, even long past its TTL. Four things
count as busy:
- a running
type: scriptroutine step - a detached agent session (a run whose CLI is still alive in
tmux) - an attached terminal (the dashboard’s container terminal)
- a live exposed port
services: (redis,
postgres, …) run as their own containers alongside the crew container, not
inside it, so stopping an idle crew leaves them running. Crewship stops the
agent runtime it owns and manages nothing else.
crewship crew update
Update a crew. Only changed flags are sent.
Issue prefixes
An issue identifier is<prefix>-<n>. The prefix is the crew’s
--issue-prefix, or, when it is not set, the first three letters of the crew
slug upper-cased — so a crew slugged engineering files ENG-1 without anyone
configuring anything.
engineering files ENG-1, engine files ENG-2 — because
the number comes from a counter keyed on the workspace and the prefix, not on
the crew. Nothing is rejected and nothing collides: identifiers are unique per
workspace, and one sequence per prefix is what makes that true by construction.
Changing a crew’s prefix does not renumber or rewrite the identifiers it has
already minted, and does not restart numbering: the new prefix picks up above
whatever that prefix already holds in the workspace.
--memory-mb and --cpus reach a running container only when it is
recreated. They are cgroup limits, fixed when the container is created, so a
crew that is already up keeps the old ones while crewship crew get reports
the new ones. When the crew is running, the update says so:crewship crew container-status shows the configured and effective
figures side by side — see Limits:.crewship crew image-status
Report whether a crew’s running container is behind the image tag it was
built from. A pure read — it never pulls and never restarts anything.
crewship crew refresh-image
Pull the crew’s configured image, then drop its runtime container so the next
agent exec recreates it from the fresh copy.
update role action (OWNER, ADMIN, MANAGER).
Not the same as
restart-agents. restart-agents drops the container
without pulling — that picks up a devcontainer image you have already
rebuilt locally. refresh-image pulls first, which is what picks up a base
image that has moved on in the registry.crewship crew delete
Delete a crew. Prompts for confirmation.
The crew’s agents are retired with it, which frees their slugs as well as
the crew’s: re-applying the manifest that created them works straight away.
Before v1.x the agents survived their crew and kept holding their slugs, so the
re-apply answered
409 Agent slug already taken in this workspace until each
one was deleted by hand (#1712).
crewship crew status
Show live crew status including agents, recent assignments, and open escalations.
Requires login and workspace context. The command resolves the crew by slug or
ID, then reads GET /api/v1/crews/{crewId},
GET /api/v1/agents?crew_id={crewId},
GET /api/v1/crews/{crewId}/assignments, and
GET /api/v1/crews/{crewId}/escalations. A missing crew is 404; each list is
workspace-scoped and a failed dependency is reported as a command error.
- AGENTS — all agents with their slug, role, and status
- ASSIGNMENTS (last 5) — recent task assignments with status colors
- ESCALATIONS (open) — pending or open escalations
PENDING or OPEN; closed escalations are
not shown in the open section. The command is a read-only member operation and
does not resolve assignments or escalations.
crewship crew standup
Show crew standup summary (last 24h activity).
crewship crew peer-conversations
List peer conversations in a crew.
Output columns: ID, FROM, TO, QUESTION, STATUS, ESCALATED, CREATED
crewship crew suggest
Get AI-powered crew suggestions based on a goal.
Crew Members
crewship crew member list
List members of a crew.
crewship crew member add
Add a user to a crew.
crewship crew member remove
Remove a member from a crew.
Crew Connections
Crew connections (“crew links” in the UI) are what let one crew hand work to another: with a link, a lead can assign to an agent in the other crew (/assign with a crew field), crews can message each
other and share files. Without one, every attempt is refused.
--direction unidirectional means work flows from the FIRST crew to the second only. Re-running
connect on a pair that is already linked updates that link rather than creating a second one; naming
the pair the other way round makes it bidirectional.
crewship crew connect
Create a connection between two crews.
crewship crew disconnect
Remove a crew connection by connection ID.
crewship crew connections
List all crew connections in the workspace.
crewship crew mcp
Show or set MCP server configuration for a crew.
--set and --set-file are mutually exclusive. The JSON must contain a "mcpServers" top-level object.crewship crew credential-readiness
Report which of a crew’s credentials are for a CLI the crew’s container does not have.
The sandbox runtime image ships git, curl and jq. Tools like gh, aws, az, gcloud, kubectl, docker, terraform, npm and ansible only exist in the container when the crew’s devcontainer config declares the matching feature (or mise installs the tool). A valid credential and a working agent are therefore two different things — a healthy GitHub PAT on a crew with no github-cli feature still gets the agent gh: command not found, with nothing connecting the two facts.
This command only reports. It never edits the crew’s devcontainer config and never triggers a rebuild — adding a feature changes what runs inside the container, so it stays your call. Apply the fix with
crewship crew config, then crewship crew rebuild.docker-outside-of-docker satisfies a DOCKER credential and a mise nodejs satisfies an NPM one.
Credentials are considered when they are workspace-scoped, scoped to this crew, or assigned to one of its agents with a live lease. Revoked and deleted credentials are ignored.
crewship crew services
Show the crew’s live sidecar service inventory, including status, image, inferred
type, and published ports. This is the running-container view, not a snapshot of
the services declared in the last configuration.
GET /api/v1/crews/{crewId}/services.
crewship crew containers
Show every container the crew has on the runtime right now — its agent runtime
container and its sidecars — with live state, CPU, memory, and how many
agents run in the runtime container.
KIND is crew (the agent runtime) or sidecar (a declared service). NAME
is the real container name, so it can be pasted straight into docker logs.
A - in CPU, MEM or AGENTS means unmeasured, not zero: a stopped container
has no usage reading, a runtime without stats support reports none at all, and
only the crew row has an agent count.
Three commands answer three different questions.
containers is the whole-crew
docker view. crew container-status answers
about the crew’s one runtime container in depth, including configuration drift.
crew services answers about the sidecars under
their manifest service names.GET /api/v1/crews/{crewId}/containers.
crewship crew config
Manage runtime configuration for a crew — the devcontainer devcontainer.json, mise tool config, and optional runtime base image override. Together these drive what crewship crew provision builds.
--show, --export, and --clear are read-or-reset operations; the three upload flags apply a new value. Combine upload flags in one invocation to update multiple fields atomically.
After changing runtime configuration, run crewship crew rebuild to invalidate the container cache and apply the new build.
Container-privilege controls
The highest-blast-radius runtime settings have dedicated flags rather than requiring a hand-editeddevcontainer.json. They merge onto the crew’s
stored config (image, features and mise stay intact) and the server re-validates
every one on save — see
Container isolation → Runtime escape hatches.
Security flags form their own mode: they cannot be combined with
--show,
--export, --clear, or the upload flags in a single invocation. The crew must
already have a devcontainer_config (there would otherwise be no base image to
merge onto).
crewship crew provision
Trigger devcontainer provisioning for a crew. Kicks off the same build pipeline the server runs when an agent first starts in a fresh workspace. Streams live build progress until the build completes or fails — pass --no-watch to fire-and-forget.
crewship crew provision status
Check provisioning status for a crew. Prints the current status, cached image tag, config hash, and resolved devcontainer config. Pass --watch to stream live progress until the build completes. Exit code is always 0 — branch on the Status field (ready, building, failed, not-provisioned) in downstream scripts rather than relying on the exit code.
When the most recent build failed, the command also prints the persisted Error and a Build log (tail) — the last ~100 lines / 8 KB of BuildKit stderr (secret-scrubbed) that name the failing step. This is read back from the provisioning journal, so it survives a server restart and the live stream ending: you can debug a failed feature build after the fact without having watched it happen. -f json returns the same tail under log_tail.
crewship crew rebuild
Invalidate the crew’s cached devcontainer image and re-provision. Use after changing crewship crew config values — provision alone will reuse the cached layer keyed by the old config hash. Streams live progress unless --no-watch is passed.
crewship crew start
Start a crew’s runtime container and wait until it is running.
This is not
crew provision. Provision builds the container image;
this creates and starts the container itself, running the same sequence
an agent run performs — the crew’s provisioned image, its mounts, env,
capabilities and resource limits, and any declared sidecar services. A
crew with no image yet is provisioned first, so start works on a cold
crew (that build can take minutes).
Idempotent. Starting a running crew returns its container and exits
0, so a deploy script can start-then-write without branching.
Reach for it when you need the container up without spending tokens:
shared/ are owned by the container user, so the server
replays the write inside the container. On a stopped crew that write
fails with 409 file is owned by the crew runtime — this is the command
that answers it.
Anything the start had to do without (a container provider with no
sidecar support, for instance) is printed under Notices: rather than
logged, because “up, but without its declared postgres” changes what you
do next.
crewship crew stop
Stop a crew’s runtime container, along with any sidecar services it
declared.
crewship crew start) brings
it back.
Because container memory and CPU limits are fixed at container-create
time, this is also how a resize takes effect: crew stop then crew start recreates the container with the crew’s current limits. See
container-status, whose
config_drift block reports when a running container no longer matches
its crew.
Stopping an already-stopped crew succeeds — the caller asked for a
stopped crew and got one, so a script never has to bracket the call in a
status check.
Sidecars stop with the crew. A crew that declares
services: gets them
stopped on the same call, which is the point — a “stopped” crew whose
Postgres still held its memory would not be stopped in any sense the
operator meant. Named volumes are not removed, so data survives.crewship crew container-status
Show the crew’s runtime container state.
Container: is one of running, creating, stopped, error,
not_configured (no container runtime configured on the server) or unknown
(the runtime could not be reached). Backed by
GET /api/v1/crews/{crewId}/container-status.
--format json (or yaml) emits the endpoint’s payload as it stands, which is
how an agent reads the figures behind the Limits: block below — including
fields this command does not print:
config_drift is absent when the container matches its crew, and when the
provider reported no limits to compare against. An absent effective_* is
“this provider said nothing”, never zero.
Config: — is this container running today’s configuration?
A crew container is created once and reused for as long as it keeps running.
Everything that hardens it is applied at create time and nowhere else: the
init process that reaps orphaned processes, the core: 0 limit that stops a
crashing agent writing a core dump full of its credentials onto disk,
supplementary groups, swap being off, the /dev/shm size, the restart policy.
Upgrade the server while a crew is up and that crew keeps the configuration it
was created with — indefinitely, and until now silently.
- Nothing is broken. The crew runs exactly as it did before the upgrade. What it lacks are improvements, some of which are security hardening.
- A stopped container fixes itself. When a crew whose container is stopped is next woken, a container carrying an older configuration is rebuilt rather than restarted — at that moment the rebuild costs nothing (the crew’s root filesystem is read-only, so its writable layer holds nothing, and the wake was going to pay for a container start anyway). With the idle TTL stopping crews after four hours, a fleet converges on its own.
- A running container is never torn down for it. That would kill whatever
the crew is executing. Run
crewship crew restart-agents <slug>when the crew is idle, or leave it to the TTL.
Config: line at all means the provider does not report it — the Apple
container provider does not today. Absence is “unknown”, not “current”.
Limits: — is this container running today’s crew configuration?
The same shape of gap, one level down. Config: asks whether the container is
older than the build; Limits: asks whether it is older than this crew’s own
settings. container_memory_mb and container_cpus are cgroup limits, and a
cgroup limit is set when the container is created — it cannot be changed on a
running one. So crewship crew update <slug> --memory-mb 8192 stores the new
figure, crewship crew get reports it, and the container keeps the old one:
restart-agents on a stopped crew
answers restarted=0, which reads as the report being wrong.
A running container is never torn down for a resize — unlike a network-policy
change, where the stale policy is a live exposure, a stale memory limit is not,
and killing a run to apply it would cost more than it saves. crewship crew update says so on the spot when the crew is running, so the gap does not have
to be discovered here.
crewship crew restart-agents
Force-remove the crew’s runtime container. The next agent exec recreates it from the current cached image, so agents pick up a new system prompt, new MCP config, and new env vars without a full rebuild. Idempotent — succeeds with restarted=0 when no container was running.
POST /api/v1/crews/{crewId}/restart-agents. The handler returns {"restarted": <n>}. Use restart-agents for hot config refreshes; reach for rebuild only when the image itself has changed.
restart-agents is also the fix for a stale sidecar: after a redeploy, a still-running crew container keeps executing the OLD bind-mounted crewship-sidecar (memory recall and egress policy can silently degrade). Crewship detects this on the next agent run and records a sidecar.stale severity-error entry in the activity feed (GET /api/v1/journal?severity=error) — recycle the container with restart-agents to pick up the fresh sidecar.
On servers built via make build / make build:go, the expected sidecar hash is baked into the server binary at build time, so detection also catches a stale artifact — a deploy that updated the server but never rebuilt/recopied crewship-sidecar (the on-disk file is as old as the running one, which runtime file-hashing alone cannot see). In that case the server additionally logs a stale sidecar ARTIFACT detected error: restart-agents is not enough, because a fresh container would remount the same old file — rebuild the sidecar (make build:sidecar), redeploy it, then run restart-agents. Builds without the baked-in hash (plain go build, go run) fall back to comparing against the on-disk binary, as before.
restarted: <n> (n > 0) confirms the container was actually dropped; a fresh one is created cold on the next exec. restarted: 0 means no running container was found for this crew — expected when the crew is idle, but if you know a container is up and still see 0, you’re on a build that predates the container-name-matching fix (the matcher looked for crewship-team-<slug> and missed the real <prefix>-team-<slug>-<crewID> name on any multi-instance or post-cross-tenant-fix deployment, so the drop silently no-op’d). Upgrade the server.crewship crew apply-avatar-style
Set the avatar_style override for every agent in a crew in one call, or clear existing per-agent overrides so they fall back to the template default. Mirrors the crew toolbar’s “Apply to all agents” avatar action.
Exactly one of
--style or --reset is required. Backed by POST /api/v1/crews/{crewId}/apply-avatar-style. The response reports updated (agent row count affected) plus either style or reset: true.
This also drops any stored avatar renders for the crew’s agents, since those depict the previous style. Affected agents go back to generating from their seed and are re-stored on next view.
crewship crew files
Inspect or write files in the crew’s /crew/shared/ directory — the inter-agent Shared Ship namespace. Alias: crew file. Server routes live in internal/api/proxy_files.go; the CLI download path mirrors crewship agent files so the table / json / yaml output feels identical across scopes.
crewship crew files list <slug-or-id>
crewship crew files get <slug-or-id> <path>
Stream a file from the crew shared volume. Defaults to stdout when no --out is given so the output is pipe-friendly; pass --out <file> (or - to force stdout) to land bytes on disk.
Disk writes use the same atomic-tempfile-then-
rename(2) pattern as agent files --download, so a Ctrl-C or transport hiccup mid-copy does not clobber an existing good file.
crewship crew files save <slug-or-id> <path>
Upload bytes to the crew shared volume. Source comes from --file (local path), --content (inline string), or stdin when neither flag is given. --content and --file are mutually exclusive.
Save issues a raw
PUT /api/v1/crews/{crewId}/files/save?path=… with Content-Type: application/octet-stream so binary uploads round-trip byte-for-byte.
crewship crew files delete <slug-or-id> <path>
Remove a file from the crew shared volume — the CLI-native way to clean up a probe script or scratch file instead of falling back to rm on the host. Alias: crew files rm. Prompts for confirmation unless --yes is given. Path-traversal is rejected server-side, identical to save.
Delete issues
DELETE /api/v1/crews/{crewId}/files/delete?path=… and is idempotent — removing a file that is already gone still succeeds. On a running crew whose shared tree the runtime owns (UID 1001), the removal is routed through the container so it lands regardless of host-side file ownership.
crewship crew cache
Manage the devcontainer image cache shared across crews. Cache tags use the crewship-cache:* prefix and are keyed by a hash of devcontainer.json + mise config + runtime image, so two crews with identical configs share a single image.
crewship crew cache list
crewship crew cache prune
Remove old or unreferenced cached images. With no flags, defaults to --older-than 30d and leaves referenced images alone.
See also
- Guides → Devcontainers & Runtime Images — end-to-end walkthrough of the provisioning pipeline.
- Configuration → Devcontainers — flat reference for config fields and env vars.
crewship features— browse the devcontainer feature catalog before editingdevcontainer.json.crewship runtimes— browse the mise runtime catalog before editing the mise config.