core/skills/shell/SKILL.md
MUST be invoked before any work involving: charly shell command, interactive shells, command execution in containers, workspace mounts, TTY allocation, or port relay.
npx skillsauth add overthinkos/overthink-plugins shellInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
charly shell runs an interactive shell or executes commands inside containers. Supports workspace mounting, device auto-detection, environment injection, and TTY allocation for automation tools.
| Action | Command | Description |
|--------|---------|-------------|
| Interactive shell | charly shell <image> | Bash shell in container |
| Bind workspace | charly shell <image> --bind workspace=~/project | Mount host dir as workspace volume |
| Volume config | charly shell <image> -v name:type[:path] | Configure volume backing (volume|bind|encrypted) |
| Run command | charly shell <image> -c "cmd" | Execute command and exit |
| Force TTY | charly shell <image> --tty -c "cmd" | PTY allocation for automation |
| Specific version | charly shell <image> --tag v1.0.0 | Use specific image tag |
| No devices | charly shell <image> --no-autodetect | Disable device auto-detection |
| Set env var | charly shell <image> -e KEY=VALUE | Inject environment variable |
| Load env file | charly shell <image> --env-file .env | Load env from file |
| Named instance | charly shell <image> -i runner-1 | Use named instance |
| Force build | charly shell <image> --build | Build locally before running |
Note: charly shell does not accept remote refs (@github.com/...). Remote
refs are handled exclusively by charly box pull (build-mode). Pull first,
then charly shell <image-name> works via labels. See /charly-build:pull.
ExtractMetadata (never charly.yml)charly.yml overlay (volumes, env, sidecars, tunnel)<engine> exec into it<engine> run with full configurationIf the image isn't in local storage, ExtractMetadata/EnsureImage return
ErrImageNotLocal and the CLI surfaces:
Error: image "X" is not available locally.
Run 'charly box pull X' to fetch it first
See /charly-build:pull for the full sentinel pattern.
charly shell <image> --bind workspace=~/project # Bind ~/project as workspace volume
charly shell <image> --bind workspace=. # Bind PWD as workspace volume
charly shell <image> # No host mount (named volume)
The --bind flag overrides volume backing for the session. For finer control, use -v name:type[:path] where type is volume, bind, or encrypted. The container working directory is ~/workspace (resolved from the workspace volume). If a .env file exists in the bound directory, it is auto-loaded.
Forces TTY allocation even when stdout is not a terminal. Uses script(1) from util-linux to provide a real PTY.
# Without --tty: "not a tty" errors from interactive commands
charly shell my-app -c "interactive-cli auth login" # fails in CI/automation
# With --tty: script(1) wraps the command in a PTY
charly shell my-app --tty -c "interactive-cli auth login" # works everywhere
Essential for automation tools (Claude Code, CI runners) where stdout is a pipe, not a terminal. Many interactive CLI commands (OAuth flows, prompts) require a TTY.
Works for both new containers (<engine> run) and exec into running containers (<engine> exec).
When charly shell detects the container is already running (via <engine> inspect), it uses <engine> exec instead of <engine> run. The same flags work:
charly start my-app # Start background service
charly shell my-app -c "cat /etc/hostname" # Exec into running container
charly shell my-app # Interactive shell in running container
The port_relay field in charly.yml solves the problem of services that bind only to 127.0.0.1 inside the container (e.g., Chrome 146+ DevTools). Container port mappings only forward to interfaces visible from outside, so a loopback-only service is unreachable from the host.
# In charly.yml:
port_relay:
- 9222
How it works:
eth0:<port> and forwards to 127.0.0.1:<port>init: vocabulary's <name>.relay_template) with priority 1 (starts before other services)This makes loopback-only services accessible through normal podman/docker port mappings and tailscale serve.
Source: charly/generate.go (relay service generation), charly/layers.go (PortRelayYAML).
By default, charly shell auto-detects available host devices and passes them through. Use --no-autodetect to disable.
Auto-detected devices:
nvidia-smi) -- --gpus all (Docker) or --device nvidia.com/gpu=all (Podman)amdgpu driver) -- --device /dev/kfd + --group-add keep-groups + auto-detected HSA_OVERRIDE_GFX_VERSION from KFD topology/dev/dri/renderD* -- GPU render nodes/dev/kfd -- AMD Kernel Fusion Driver (ROCm compute)/dev/kvm -- KVM virtualization/dev/vhost-net, /dev/vhost-vsock -- virtio networking/dev/fuse -- FUSE filesystem/dev/net/tun -- TUN/TAP networking/dev/hwrng -- hardware RNGWhen an AMD GPU is detected, keep-groups is auto-added to preserve host supplementary groups (video, render) inside the container, and HSA_OVERRIDE_GFX_VERSION is auto-set from the GPU's KFD topology (e.g., 10.3.0 for RDNA2). Additionally, the first detected /dev/dri/renderD* device is auto-injected as DRINODE and DRI_NODE env vars (used by selkies for VAAPI encoding). All auto-detected env vars can be overridden via -e.
Shared code path: charly shell calls appendAutoDetectedEnv() in charly/devices.go — the same function used by charly config and charly start. That means the three commands produce an identical env set on every run, eliminating drift that used to exist when DRINODE injection was scattered across 10 different call sites before commit 8f6f322. See /charly-core:charly-doctor (Hardware Detection) for the probe side, /charly-distros:nvidia (DRINODE Auto-Injection) for the NVIDIA consumer, and /charly-distros:rocm (Runtime Environment) for the AMD consumer.
Source: charly/devices.go (appendAutoDetectedEnv, the env/group helpers) + charly/gpu_shim.go (the DetectHostDevices/DetectGPU/DetectAMDGPU shims, which since C11 resolve+Invoke the compiled-in candy/plugin-gpu).
Runtime environment variables are injected from multiple sources. Resolution priority (last wins for duplicate keys):
env: (charly.yml / charly.yml) -- lowest priorityenv_file: (charly.yml / charly.yml).env file -- auto-loaded from -w directory--env-file flag-e flags -- highest prioritycharly shell <image> -e DB_HOST=localhost -e DB_PORT=5432
charly shell <image> --env-file production.env
Kong sep:"none" on -e means commas in values are safe (e.g., NO_PROXY=localhost,127.0.0.1).
.env file format (Docker-compatible): KEY=VALUE, KEY="VALUE", KEY='VALUE', KEY (inherits from host), # comments, blank lines ignored.
Source: charly/envfile.go (ParseEnvFile, ResolveEnvVars, LoadWorkspaceEnv).
charly shell does not accept @github.com/... remote refs. Pre-refactor
versions did; post-refactor, deploy-mode commands read only from local OCI
labels, so remote refs are rejected with a redirect:
Error: remote refs are not accepted here;
run 'charly box pull @github.com/org/repo/my-app' first,
then 'charly shell my-app'
To run a shell on a remote image, pull it first (via charly box pull) and
then invoke charly shell <short-name>. See /charly-build:pull for the full remote-ref
workflow.
When engine.build differs from engine.run, images are automatically transferred between engines on demand via <src> save | <dst> load.
Source: charly/transfer.go.
All containers are connected to a shared charly network by default, enabling inter-container DNS resolution by container name. Override with network: host in charly.yml.
Source: charly/network.go.
charly cmd vs charly shell -ccharly cmd <image> "command" is a dedicated single-command tool for running containers only. Key differences from charly shell -c:
| | charly cmd | charly shell -c |
|---|---------|--------------|
| Container state | Running only | Running or starts new |
| Notification | Yes (--[no-]notify) | No |
| Process model | exec.Command (returns) | syscall.Exec (replaces) |
| Workspace mount | No | Yes (-w) |
| Device auto-detect | No | Yes |
| Use case | Quick commands + notification | Full container setup + command |
Use charly cmd for quick operations on running services. Use charly shell -c when you need workspace mounts, device passthrough, or need to start a new container.
/charly-build:pull -- Required before charly shell can work on a fresh host. Fetches the image into local storage so ExtractMetadata can read its OCI labels. Handles remote refs (@github.com/...) that charly shell itself rejects./charly-core:cmd -- Single command execution with D-Bus notification (running containers only)/charly-automation:tmux -- Persistent tmux sessions (survives disconnects, needed for TTY-dependent TUI programs)/charly-core:service -- Starting background services before exec/charly-core:start -- Same appendAutoDetectedEnv() injection at service-start time/charly-core:charly-config -- Deployment setup + same appendAutoDetectedEnv() at deploy time; --no-autodetect flag disables it/charly-core:deploy -- charly.yml overlay applied to labels before shell spawns/charly-check:cdp -- Chrome DevTools Protocol automation/charly-check:wl (sway subgroup) -- Sway compositor control/charly-core:charly-doctor -- Host hardware probe that feeds appendAutoDetectedEnv() (DRINODE, HSA_OVERRIDE_GFX_VERSION)/charly-build:settings -- Engine and bind address settings/charly-image:image -- Box definitions (ports, volumes, env) in charly.yml; authoritative source before a pull/charly-build:build -- Build the image you intend to shell into/charly-distros:nvidia, /charly-distros:rocm -- GPU layers consuming the auto-injected envMUST be invoked when the task involves charly shell command, interactive shells, command execution in containers, workspace mounts, TTY allocation, or port relay. Invoke this skill BEFORE reading source code or launching Explore agents.
Workflow position: Any time. Interactive access to running or stopped containers.
tools
Use when authoring or modifying a charly PLUGIN — a candy with a `plugin:` block that contributes Providers (verbs/kinds/deploy-targets/steps/builders/commands), its own CUE schema, builtin (compiled-in) or external (out-of-tree git repo). Covers the unified Provider model, the per-plugin CUE-schema contract (single source → Go params for dev + schema-over-Describe RPC for runtime), the SDK, and the loader.
tools
The CUE data-validation / configuration CLI (cue), pinned to v0.16.1. Use when working with the cue candy, installing the cue binary into a box or onto a target:local dev host, or running the offline schema-vendoring pipeline that feeds charly's egress validation.
tools
CUE EGRESS validation — validating (and, where it adds value, generating) the config files charly WRITES to a system BEFORE the bytes hit disk. MUST be invoked before working on charly/egress.go, the vendored schemas under candy/plugin-egress/egress-schemas/vendor/, the ValidateEgress / registerVendoredEgressKind path, the offline `task cue:vendor` pipeline, or adding an egress schema for any written artifact (cloud-init, k8s manifests, traefik routes, runtime config, install ledger, systemd/quadlet units, ssh_config, libvirt XML).
tools
Kubernetes cluster-probe declarative check verb — the `kube:` check verb (nodes, pods, ingress, storage class, addon health, apply/delete, and arbitrary resource GETs) served out-of-process by the candy/plugin-kube plugin (vendored client-go; no external kubectl required).