Documentation Index
Fetch the complete documentation index at: https://docs.crewship.ai/llms.txt
Use this file to discover all available pages before exploring further.
Port Expose
When an agent runsnpm run dev or starts a service inside its container, the operator wants a clickable URL to open it. Port expose creates a capability URL — https://<host>/exposed/<token> — that reverse-proxies to the in-container port. The token is the auth: anyone with the URL gets through, anyone without it gets a 404.
This is the right shape for ephemeral dev URLs: short-lived, easy to share with a teammate via Slack, no JWT plumbing needed. For long-lived or sensitive surfaces, do not use this — set up a proper authenticating proxy.
Implementation: internal/api/port_expose_handler.go. Capability URLs hit Go 1.22+ ServeMux with /exposed/{token} and /exposed/{token}/ (trailing slash and bare-token forms both routed to the same handler).
Capability URL — reverse proxy
Upgrade: websocket header and switches to bidirectional pipe mode.
Errors:
| Status | Condition |
|---|---|
| 404 | Token unknown, expired, or revoked. (Same shape so existence isn’t leaked.) |
| 502 | Upstream (in-container) port not reachable. |
| 504 | Upstream timeout. |
Sidecar request
X-Internal-Token required. The agent asks the sidecar (e.g. via a tool call), the sidecar asks the server. Agents cannot reach this endpoint directly.
Request body:
| Field | Type | Description |
|---|---|---|
container_port | integer | Port number inside the crew container. |
label | string | Operator-facing name; surfaced in the audit list. |
ttl_seconds | integer | Lifetime in seconds. Server clamps to a max of 24 hours. |
201 Created
User-facing audit + revocation
List
200 OK
request_count is incremented by the reverse proxy on every successful forward, so operators can spot which exposes are actually being hit. Use this to find the dead expose left over from yesterday’s debugging.
Revoke
204 No Content.
Tenancy and policy
crewIdis validated viacrewBelongsToWorkspace.- An
AllowAllPolicyruns on every capability-URL request (currently always returns allow). Custom policies can be wired by replacing the policy object — useful for restricting expose to specific IP ranges or to authenticated browser sessions. - The capability URL itself has no workspace context (it’s a public URL). The token-to-port lookup happens server-side and is workspace-isolated by construction.
Security notes
- Tokens are 256 bits of
crypto/rand. Brute-forcing a valid token via the 404 oracle is not feasible. - Tokens land in URL paths, which means they end up in HTTP server logs and browser history. Do not paste a capability URL into a public chat or screenshot it without thinking.
- TLS termination is the operator’s responsibility — Crewship does not currently terminate HTTPS for
/exposed/. Run behind nginx / Caddy / a cloud load balancer that does. - Revocation is fast but not transactional with in-flight requests. A request that is mid-stream when revoke fires completes; subsequent requests fail.
Related
- Devcontainers — Container actuals — pairs with port expose for “this agent installed Node and started a server”.
- Architecture — Sidecar Proxy — the surrounding sidecar surface.