Configuration Reference
cc-deck uses XDG-compliant paths for configuration and data storage.
Config File
Location: $XDG_CONFIG_HOME/cc-deck/config.yaml (typically ~/.config/cc-deck/config.yaml)
The config file is optional. All settings have sensible defaults and can be overridden via CLI flags.
# Default namespace for Kubernetes commands
namespace: cc-deck
# Default credential profile
profile: default
# Verbose output
verbose: false
# Voice relay defaults
defaults:
voice:
threshold: 45 # VAD sensitivity (0-100, logarithmic)
commands: # Custom command words (optional)
submit:
- send
- done
- enter
attend:
- next
The defaults.voice.threshold setting controls how sensitive voice activity detection is.
Lower values capture quieter speech but pick up more background noise.
A value between 30 and 50 works well for most indoor environments.
This value can be overridden per invocation with --threshold.
The defaults.voice.commands setting maps action names to trigger words.
Two actions are available by default:
| Action | Default Word | Description |
|---|---|---|
|
|
Sends a carriage return to the attended pane (same as pressing Enter) |
|
|
Cycles to the next session needing attention (same as Alt+a) |
When the entire transcribed utterance, after stripping filler words, matches a trigger word, the corresponding action fires. Words embedded in longer sentences are treated as normal dictation.
When you set commands in the config, it replaces the defaults entirely.
Each action can have multiple trigger words, and you can change the defaults to avoid conflicts with your natural speech patterns.
Environment Variables
| Variable | Description |
|---|---|
|
Base directory for config files. Default: |
|
Base directory for data files. Default: |
|
Base directory for cache files. Default: |
|
Path to kubeconfig file. Default: |
|
Zellij configuration directory. Default: |
File Locations
| Path | Purpose |
|---|---|
|
CLI configuration |
|
Sidebar plugin binary |
|
Default layout (symlink to chosen variant) |
|
Standard layout variant |
|
Minimal layout variant |
|
Clean layout variant |
|
Personal layout (never overwritten by install) |
|
Claude Code settings (hooks registered here) |
|
User-defined domain groups for network filtering |
|
Snapshot storage |
|
Whisper model files for voice relay |
|
Voice relay diagnostic log (created with |
|
Hook pane ID cache (ephemeral) |
Plugin Configuration
Plugin settings are specified in the layout file’s plugin block:
plugin location="file:~/.config/zellij/plugins/cc_deck.wasm" {
navigate_key "Alt s" // Key to toggle navigation mode
attend_key "Alt a" // Key for smart attend
voice_key "Alt m" // Key for voice mute toggle
}
| Setting | Default | Description |
|---|---|---|
|
|
Global shortcut for navigation mode |
|
|
Global shortcut for smart attend |
|
|
Global shortcut for voice mute toggle |
Key format follows Zellij conventions: Alt, Ctrl, Super (Cmd on macOS) as modifiers, followed by the key name.
Build Manifest Credentials
Location: .cc-deck/setup/build.yaml (relative to project root)
The credentials section of the build manifest declares which credential providers an OpenShell workspace needs.
It stores only provider type identifiers and environment variable names, never actual credential values.
Values are resolved from the host environment at workspace creation time (cc-deck ws new).
credentials:
# API key credentials (auto-injected via OpenShell providers)
- type: claude
env_vars: [ANTHROPIC_API_KEY]
- type: github
env_vars: [GITHUB_TOKEN]
# File-based credentials (uploaded into the sandbox at runtime)
- type: vertex
file: GOOGLE_APPLICATION_CREDENTIALS
env_vars: [ANTHROPIC_VERTEX_PROJECT_ID, CLOUD_ML_REGION]
# Custom service with explicit endpoints for network policy
- type: generic
env_vars: [CUSTOM_API_KEY]
endpoints:
- host: api.custom.com
port: 443
Credential Entry Fields
| Field | Type | Required | Description |
|---|---|---|---|
|
string |
yes |
Provider profile type. Known types: |
|
list of strings |
no |
Environment variable names to resolve from the host. Auto-populated from known profiles if omitted. |
|
string |
no |
Name of an env var whose value is a file path (for example, |
|
list of host/port |
no |
Custom network endpoints for |
Known Provider Types
| Type | Default env_vars | Description |
|---|---|---|
|
|
Anthropic API key for Claude Code (direct API access) |
|
|
Claude Code via Google Vertex AI. Detected when both |
|
|
GitHub personal access token |
|
|
GitLab personal access token |
|
|
OpenAI API key |
|
|
NVIDIA API key |
|
|
Google Vertex AI (file-based auth). Adds GCP endpoints to network policy automatically. |
|
(must be specified) |
Custom service. Requires explicit |
When a credential’s required env var is not set in the host environment, the provider is skipped with a warning. The workspace still starts, but the corresponding service will not be available.
Use /cc-deck.capture to detect available credentials automatically.
Use /cc-deck.capture --all to auto-accept all proposals without prompting.
Network Configuration
The network section of the build manifest controls domain-level egress filtering for containerized sessions.
network:
allowed_domains:
- pypi.org
- files.pythonhosted.org
- crates.io
- github # expands to domain group
network.allowed_domains
A list of domain names or domain group names that should be permitted for outbound network access.
Each entry produces a network policy in the assembled openshell/policy.yaml with port 443.
Entries can be:
-
Literal domains (contain a dot): Used as-is with port 443. Example:
pypi.org. -
Domain group names (no dot): Expanded to the set of domains defined in
~/.config/cc-deck/domains.yaml. Example:githubexpands togithub.com,api.github.com, etc.
Domains already covered by catalog components are not duplicated.
If a catalog component (e.g., python) already includes pypi.org in its endpoints, adding pypi.org to allowed_domains has no effect.
This field is populated automatically by cc-deck build record, which captures DNS queries during an interactive session and appends new domains.
It can also be edited manually.
Policy Component System
The build refresh command assembles openshell/policy.yaml deterministically from YAML component files.
Each component file defines a set of network endpoints, match conditions, and optional binary restrictions.
Component File Locations
Components are loaded from three tiers in precedence order. A component at a higher tier replaces one with the same filename stem entirely (no merging).
| Tier | Path | Precedence |
|---|---|---|
Embedded |
Built into the |
Lowest |
Cached catalog |
|
Middle |
User-local |
|
Highest |
The capture command fetches catalog components from the remote catalog repo and caches them in the middle tier.
User-local components can be created manually for project-specific endpoints.
Built-in Components
The following components are embedded in the cc-deck binary:
| Component | Match | Endpoints |
|---|---|---|
|
Always included |
|
|
Always included |
|
|
Tools: |
|
|
Tools: |
|
|
Tools: |
|
|
Tools: |
|
|
Credentials: |
All Vertex AI regional endpoints, |
Components with always: true in their match conditions are always included regardless of the manifest.
Tool and credential matches use OR semantics: any single condition match includes the component.
Probe and Runtime Glob Fields
Tool-matched components (those without explicit binaries) support two optional fields for the two-pass binary probing system:
| Field | Type | Description |
|---|---|---|
|
|
Binary names to search for via |
|
|
Glob patterns for binaries created at runtime (virtual environments, toolchain installs).
Merged into the policy alongside probed paths.
Entries must start with |
Components with explicit binaries (like claude-code.yaml and git-hosting.yaml) ignore both fields.
Custom Component File Format
Create a YAML file in .cc-deck/setup/openshell/policies/ with this schema:
key: internal_api
name: Internal API
match:
always: true
endpoints:
- host: api.internal.corp
port: 8443
To add a tool-matched component with probing support:
key: pkg_elixir
name: Elixir packages
match:
tools:
- mix
- elixir
probe_binaries:
- mix
- elixir
runtime_globs:
- /sandbox/.mix/escripts/*
endpoints:
- host: hex.pm
port: 443
- host: repo.hex.pm
port: 443
Required fields: key, name, match (with at least one condition), endpoints (at least one entry).
Each endpoint requires host and port.
Endpoints with protocol: rest must also have access or rules (OpenShell 0.0.46 compliance).
MCP Endpoint Policy Entries
MCP servers configured in the manifest can include an optional endpoint field in host:port format.
During policy assembly, each MCP entry with a non-empty endpoint generates a network policy entry keyed as mcp_<slugified_name>.
This allows Claude Code to connect to remote MCP servers at startup without being blocked by the OpenShell supervisor.
The capture command extracts endpoints automatically from HTTP/SSE MCP servers (via the url field) and from stdio servers that use mcp-remote (by scanning arguments for HTTPS URLs).
Local stdio servers without a URL produce no endpoint.
mcp:
- name: google-work
transport: http
endpoint: mcp-google-work.int-tichny.org:8443
description: "Google Workspace (work)"
- name: jira-redhat
transport: stdio
endpoint: mcp.atlassian.com:443
description: "Red Hat Jira (npx mcp-remote)"
- name: playwright
transport: stdio
description: "Browser automation via Playwright"
The generated policy entries use the claude_code component’s binary paths, since Claude Code is the process that connects to MCP servers.
When the pkg_node component is also present (because node or npm is in the tools list), Claude Code binary paths are appended to its binary list.
This allows Claude Code to spawn npx processes that download and run npm packages for MCP stdio proxies.
MCP entries without an endpoint, or with a malformed endpoint (missing port), are skipped with a warning during policy assembly.
If the claude_code component is not available, all MCP policy entries are skipped gracefully.
Containerfile Template Snippets
The cc-deck build init command renders fixed Containerfile layers into snippet files at <target>/snippets/.
These snippets are pre-rendered Go templates with all paths and variables resolved.
The /cc-deck.build Claude Code command assembles the final Containerfile by copying snippets verbatim and generating only the variable parts (tool installs, plugin commands, settings) between them.
Snippet files:
| File | Content |
|---|---|
|
|
|
User creation and shell setup (container target only, empty for OpenShell) |
|
cc-session, cc-setup, cc-deck self-install with Zellij, Claude Code install |
|
Skills directories, policy file COPY, |
|
Starship prompt init, Zellij auto-start on login (OpenShell only) |
|
Final |
The Zellij binary installed by --install-zellij defaults to the latest GitHub release.
Pin a specific version with cc-deck config plugin install --install-zellij --zellij-version 0.44.3.
Domain Groups Configuration
Location: $XDG_CONFIG_HOME/cc-deck/domains.yaml (typically ~/.config/cc-deck/domains.yaml)
This file defines custom domain groups for network filtering in containerized sessions.
Create it with cc-deck config domains init to get a commented template, or write it manually.
The file is a YAML mapping where each top-level key is a group name and the value defines its domains and resolution behavior.
Custom Groups
Define a new group with a domains list:
internal-registry:
domains:
- registry.internal.corp
- artifacts.internal.corp
Extending Built-in Groups
Use extends: builtin to merge additional domains with a built-in group of the same name.
The user-defined domains are appended to the built-in domains rather than replacing them.
python:
extends: builtin
domains:
- pypi.internal.corp
This produces a python group containing all built-in Python domains plus pypi.internal.corp.
Without extends: builtin, the user-defined group replaces the built-in group entirely.
Including Other Groups
Use includes to compose a group from other groups.
Included groups are resolved recursively.
dev-stack:
includes:
- python
- golang
- github
domains:
- artifacts.internal.corp
This produces a group containing all domains from python, golang, and github, plus the literal domain artifacts.internal.corp.
Resolution Rules
-
Groups defined in
domains.yamltake precedence over built-in groups of the same name. -
If
extends: builtinis set, the built-in domains are included as a base. -
Circular includes are detected and reported as errors.
-
Source labels in
cc-deck config domains listreflect the resolution:builtin,user(override or new), orextended(extends builtin).