Environment Variables
Operator-controlled env layers, 1Password integration, and host-env forwarding for agent containers
jackin❯ lets you set environment variables for agent containers at four scopes — global, per role, per workspace, and per (workspace × role). Values can be literal strings, references to host env vars, or references to 1Password items resolved through the op CLI.
Operator env vars are managed through jackin config env,
jackin workspace env, or the Environments tab in the
operator console's workspace editor (workspace and per-(workspace ×
role) scopes). You should not need to hand-edit any configuration
file — the global scope is CLI-only today; the workspace scopes
are reachable from both the CLI and the console.
Why operator env
Role manifests declare the env shape — what keys a role expects, what's interactive, what has a default. Operator env scopes declare the values for a specific operator on a specific workspace with a specific role. Keeping shape and values in different places means:
- Third-party roles never see your secrets in their git history.
- The same role can run with different credentials in different workspaces (personal laptop vs company monorepo).
- You can override a manifest default without forking the role.
Scopes
Four scopes are merged with later-wins semantics — most-specific values take priority:
- Global — applies to every agent launch.
- Role — applies whenever this role is loaded.
- Workspace — applies whenever this workspace is loaded.
- Workspace × Role — applies only for this specific (workspace, role) cell.
Keys present in multiple scopes take the value from the highest-priority scope (4 > 3 > 2 > 1). Keys unique to any scope are preserved.
Setting values from the CLI
Use jackin config env for global and per-role values, and jackin workspace env for per-workspace and per (workspace × role) values:
# Global — applies to every agent launch
jackin config env set OPERATOR_ORG "acme-corp"
# Role scope — only when loading agent-smith
jackin config env set API_TOKEN "op://Personal/acme-api/token" --role agent-smith
# Workspace scope — only when launching in big-monorepo
jackin workspace env set big-monorepo ARTIFACT_REGISTRY '${COMPANY_REGISTRY_URL}'
# Workspace × Role — most specific, wins on conflict
jackin workspace env set big-monorepo API_TOKEN "op://Work/shared-smith/token" --role agent-smithValues are stored verbatim — whatever you pass is what jackin❯ resolves at launch time. List or remove values with jackin config env list / jackin config env unset (and the matching jackin workspace env subcommands).
Value syntax
Each value is one of:
| Syntax | Resolution |
|---|---|
op://VAULT/ITEM/FIELD | Resolved via the 1Password CLI (op read "<ref>"). Requires op on PATH and an authenticated session. |
$NAME or ${NAME} | Read from the host's environment at launch time. Errors if the host var is unset. |
| Anything else | Literal string. |
When you load an agent with the example above in big-monorepo:
OPERATOR_ORG = "acme-corp"(literal; from global)API_TOKEN = <resolved via op read "op://Work/shared-smith/token">(workspace × role wins over role layer)ARTIFACT_REGISTRY = <value of $COMPANY_REGISTRY_URL on host>(from workspace layer)
Reserved names
These names are owned by the jackin❯ runtime and are rejected if set from any operator env scope (global, role, workspace, or workspace × role):
JACKINJACKIN_DIND_HOSTNAMEJACKIN_CONTAINER_NAMEJACKIN_INSTANCE_IDJACKIN_AGENTJACKIN_AGENT_CODENAMEJACKIN_ROLEJACKIN_WORKDIRJACKIN_GIT_COAUTHOR_TRAILERJACKIN_GIT_DCODOCKER_HOSTDOCKER_TLS_VERIFYDOCKER_CERT_PATHTESTCONTAINERS_HOST_OVERRIDEJACKIN_NETWORK_MODEJACKIN_ALLOWED_HOSTSJACKIN_FIREWALL_INSTALLEDJACKIN_NETWORK_ENFORCEMENTJACKIN_SUDO
Trying to set one of these is rejected before the agent launches.
JACKIN_AGENT is scoped to an agent session, not the whole container. jackin❯ passes the initial agent to the PID 1 multiplexer as an argv value, then sets JACKIN_AGENT only when spawning a real agent pane. Shell panes do not receive it.
Role identity, workspace workdir, supported agent slugs, and manifest model overrides are handed to Capsule through a generated launch config instead of being duplicated as container-wide environment variables. Runtime metadata needed by Capsule is injected by jackin❯ at launch time and is not read from operator env scopes. The Capsule reference documents the internal handoff.
Telemetry
These variables control direct OTLP delivery; see Run Telemetry for setup examples and Application observability for the full contract.
| Variable | Effect |
|---|---|
OTEL_EXPORTER_OTLP_ENDPOINT | Enables direct OTLP export for traces, logs, and metrics through one base gRPC endpoint. The backend owns history; jackin❯ does not write a local telemetry file. |
OTEL_EXPORTER_OTLP_{TRACES,LOGS,METRICS}_ENDPOINT | Overrides the endpoint per signal. jackin❯ still exports over gRPC only. |
OTEL_EXPORTER_OTLP_PROTOCOL / OTEL_EXPORTER_OTLP_{TRACES,LOGS,METRICS}_PROTOCOL | Must be grpc or unset when an endpoint is configured; any other value stops startup with E016. |
OTEL_EXPORTER_OTLP_HEADERS / OTEL_EXPORTER_OTLP_{TRACES,LOGS,METRICS}_HEADERS | Adds standard comma-separated key=value gRPC metadata. Per-signal values override the generic value. Invalid names, empty values, malformed percent encoding, and non-ASCII metadata are rejected before providers start. Header values are credentials: they are never printed or added to telemetry. |
OTEL_EXPORTER_OTLP_COMPRESSION / OTEL_EXPORTER_OTLP_{TRACES,LOGS,METRICS}_COMPRESSION | Must be gzip or unset. Other values are rejected before providers start. |
OTEL_EXPORTER_OTLP_TIMEOUT / OTEL_EXPORTER_OTLP_{TRACES,LOGS,METRICS}_TIMEOUT | Positive integer timeout in milliseconds. Per-signal values override the generic value; jackin❯ caps each exporter deadline at five seconds. |
OTEL_EXPORTER_OTLP_CERTIFICATE / OTEL_EXPORTER_OTLP_{TRACES,LOGS,METRICS}_CERTIFICATE | CA certificate path for TLS. Per-signal paths override the generic path. Paths are treated as sensitive configuration and are never telemetry fields. |
OTEL_EXPORTER_OTLP_CLIENT_KEY + OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE and per-signal variants | Optional mutual-TLS identity. Key and certificate must be configured together for each effective signal configuration; values and paths are never printed or exported. |
OTEL_TRACES_SAMPLER | May be unset or parentbased_always_on. A conflicting sampler is rejected because jackin❯ owns the fixed sampling contract. |
OTEL_SERVICE_NAME / OTEL_RESOURCE_ATTRIBUTES | Validated before provider startup, but they do not override the stable jackin❯ service identity or inject arbitrary Resource attributes. Empty service names and malformed key=value resource entries are rejected; exported Resources remain allowlisted and process-stable. |
OTEL_SDK_DISABLED | Set to true to disable OpenTelemetry provider and exporter activity explicitly. |
JACKIN_DEBUG | Backs the host --debug flag for operator-facing troubleshooting output. It does not enable delivery or create telemetry files. |
JACKIN_TELEMETRY_LEVEL | Overrides [telemetry].level from config.toml: info (default), debug, or trace. Every level remains governed by the schema and privacy allowlist. |
JACKIN_TELEMETRY_CATEGORIES | Overrides [telemetry].categories from config.toml with a comma-separated debug-category allowlist such as docker,launch; * allows every registered debug category. |
The host never forwards OTLP headers, client credentials, certificate paths, or arbitrary Resource attributes into a Capsule. Capsule export receives only routing and explicitly safe launch context when the network policy permits it; network.mode=none disables Capsule telemetry egress. jackin diagnostics validate requires a new exporter success for each signal, no new exporter failure or facade rejection, and a successful shared bounded flush. Host and Capsule daemon protocols expose typed sanitized telemetry health.
Host attach validation
JACKIN_HOST_ATTACH=1 is an opt-in host-side launch flag. Set it on the command that starts or attaches to an instance when testing host affordances:
JACKIN_HOST_ATTACH=1 jackin load <role>
JACKIN_HOST_ATTACH=1 jackin hardline <instance>With this flag, the jackin host process owns the interactive attach loop instead of using the in-container docker exec -it /jackin/runtime/jackin-capsule client. That enables explicit host actions such as clipboard image staging, GitHub PR/CI opening, and file export. See Host Affordances for the current behavior and validation checklist.
JACKIN_PASTE_IMAGE_PATHS controls auto-staging of pasted host image paths under host attach. It is on by default: when a single paste's entire content is one absolute host path or file:// URL that resolves to a real image file, jackin❯ stages the image and inserts the container path, which makes a normal Cmd+V paste work for screenshot tools that copy a file path. Set it to 0, false, no, or off to disable that and keep every paste as ordinary text:
JACKIN_HOST_ATTACH=1 JACKIN_PASTE_IMAGE_PATHS=0 jackin load <role>JACKIN_OPEN_LINKS=deny disables jackin❯ host browser-open actions while leaving ordinary terminal output and OSC 8 passthrough under their separate policies:
JACKIN_HOST_ATTACH=1 JACKIN_OPEN_LINKS=deny jackin load <role>The same opt-out also accepts off and no. It suppresses explicit jackin❯ actions such as GitHub Open PR, GitHub Open CI, visible URL modified-click, and Open link under cursor; it does not rewrite agent output or block native terminal hyperlink rendering.
Pane terminal defaults
Every shell and agent pane receives a stable terminal capability baseline:
TERM=xterm-256color
COLORTERM=truecolorTERM=xterm-256color keeps the pane tied to a conservative terminfo entry that remains safe when a long-lived container is reattached from a different terminal app. COLORTERM=truecolor tells agent CLIs and TUIs that 24-bit color output is available by default. jackin❯ sets this value directly instead of copying the host's COLORTERM, so a pane launched from Ghostty, Kitty, iTerm, Warp, SSH, or another xterm-compatible client sees the same deterministic environment.
1Password CLI setup
-
Install the 1Password CLI.
-
Sign in:
eval $(op signin)(or unlock the desktop-app integration). -
Set values with
op://...references — for example:jackin config env set ANTHROPIC_API_KEY "op://Personal/Anthropic/key"
Each jackin load that references op://... values shells out to op read <ref> per key. 1Password values are resolved concurrently, and op failures (missing item, expired session, binary not on PATH) are reported in a single message that names every failing key. Each launch-time op invocation has a 120-second timeout so cold 1Password app and daemon wakeups can finish without turning into false credential failures.
Prefer references picked through the 1Password picker in jackin❯ or otherwise backed by 1Password IDs. The 1Password CLI can resolve human-readable vault and item names, but ID-backed references are the stable and efficient form for launch-time automation. jackin❯ does not persist resolved secret values; it stores the reference metadata and asks op again when the value is needed.
Launch diagnostic
jackin❯ prints a compact diagnostic line on launch when operator env is non-empty, so you can confirm at a glance which keys flowed into the container:
[jackin] operator env: 3 resolved (2 op://, 1 host ref, 0 literal)In --debug mode, the diagnostic expands to per-key reference strings and scope attribution. Resolved secret values are never printed.
Interaction with manifest env
A role's manifest can declare env vars the role expects — including interactive prompts. Operator env is resolved first and pre-seeds matching manifest variables, so a configured value skips the manifest prompt. Manifest env fills in the remaining values, then operator env is overlaid on top: operator wins on key conflict. This lets you pin a value that the manifest would otherwise prompt for, or swap a manifest default for a workspace-specific secret.
Built-in agent credential keys stay selected-runtime scoped. If a manifest declares a sibling runtime credential such as OPENAI_API_KEY during a Claude Code launch, jackin❯ leaves that prompt/value lazy unless the selected runtime's auth mode needs that exact key. Generic manifest env vars still resolve normally.
See Authentication Forwarding for the companion mechanism that forwards Claude Code credentials from host to container. Env scopes and auth forwarding are orthogonal — use both.