cplt keeps your AI agent sandboxed.Kernel-level isolation for AI coding agents. Your secrets stay secret. Enforced by the OS, not by trust.
Read the argument: a sandbox confines the process, not the token
brew install navikt/tap/cplt
macOS (Apple Seatbelt) · Linux (Landlock + seccomp-BPF) · Windows: WSL2 only
What your agent can and cannot access, enforced at the kernel level.
| Resource | Without cplt | With cplt |
|---|---|---|
| Project directory (read/write) | Allowed | Allowed |
| Secrets (.env*, .pem, .key§, SSH keys) | Exposed | Protected |
| Cloud credentials (~/.aws, ~/.azure) | Exposed | Protected |
| Build tool homes (~/.m2, ~/.gradle, ~/.cargo) | Allowed | Allowed |
| Tool credential files (~/.m2/settings.xml, ~/.gradle/gradle.properties) | Exposed | Protected |
| Git hooks‡, /tmp execution, SSH agent | Exposed | Protected |
| Outbound network (HTTPS) | Exposed | Filtered* |
| Private IPs, and localhost on macOS† | Exposed | Protected |
| Destructive git/gh commands (push to default branch, force push, merge, delete) | Exposed | Protected |
| Copilot auth and tool caches (read-only) | Allowed | Allowed |
*Routed through CONNECT proxy. Telemetry and non-allowlisted domains are blocked.
†On Linux, localhost is not blocked and UDP is unrestricted unless proxy.forced is on.
‡Git hooks are write-protected on macOS. On Linux .git/hooks stays writable unless bubblewrap is installed.
§Blocked in the project on macOS. On Linux, Landlock cannot deny single files inside the project. Key files are matched by exact name (.pem), not by extension (server.pem), unless sandbox.deny_key_files_by_extension is on.
The filesystem and syscall layers are kernel-enforced: Apple Seatbelt on macOS, Landlock + seccomp-BPF on Linux, plus bubblewrap namespace isolation when bwrap is installed. The git and gh guards are a different mechanism: PATH shims and a best-effort command filter. Bubblewrap is not a network boundary, because the host network is shared by design so the proxy keeps working, and the root filesystem is bind-mounted read-only with Landlock as the access-control layer. Known limits are written down in SECURITY.md.
Block destructive GitHub and git operations. The agent can commit and branch, but not push to main or merge PRs.
Default-deny engine over 133 classified gh commands: 52 allowed, 64 blocked, 17 scope-checked.
Read
gh issue list, gh pr view
Write
gh pr create, gh issue edit
Destructive
gh repo delete, gh pr merge
gh api calls restricted to /repos/{current-repo}/...
Blocks pushes to the default branch, and force pushes everywhere. A push to a feature branch goes through, so the review gate is the pull request rather than the push. Commit, branch, rebase. All fine.
Refuse every push instead? cplt config set git_guard.protect_default_branch_only false
$ cplt --no-gh-guard --no-git-guard⚠️ BLOCKED by sandbox: 'gh repo delete' is not allowed in this environment. Reason: deletes entire repository This operation is restricted by the cplt sandbox to prevent unintended changes. Please make a note of this for the human operator and continue with your remaining work.
Both guards are on by default. Opt out for a single run with --no-gh-guard or --no-git-guard, or set mode: audit to observe before enforcing.
Commit .cplt.toml to your repo and every developer gets the same sandbox, without the agent being able to loosen it.
# Tightens the sandbox, applied without approval [deny] env = ["VAULT_TOKEN", "NPM_TOKEN"] # Loosens the sandbox, inert until `cplt trust accept` [propose] allow_localhost_any = true [propose.allow] localhost = [3000, 5432]
Can only tighten the sandbox. Block env vars and deny file paths. No approval needed.
Request additional permissions. Each developer approves with cplt trust accept --all. Content-pinned, so any change invalidates the approval.
.cplt.toml is read from git HEAD, so an edit in the working tree changes nothing, and the file is write-denied inside the sandbox anyway. A committed [deny] block therefore applies unconditionally: it can only tighten the sandbox, so there is nothing to approve. A [propose] block is content-pinned and stays inert until the developer runs cplt trust accept, and any change to the block invalidates that approval.
Three steps from zero to sandboxed agent.
STEP 1
brew install navikt/tap/cpltHomebrew on macOS, the apt archive on Debian and Ubuntu (WSL2 included), the install script anywhere else.
STEP 2
cplt init --writeDetect your project's tooling and generate sandbox config.
STEP 3
cplt -- -p "fix the tests"Your agent works normally, but your secrets are unreadable.
Copilot CLI is the default. --agent takes copilot, opencode, gemini, antigravity, pi, claude, goose, dsh and shell, the last being a sandboxed shell with no AI.
Run cplt --shell-install so copilot always runs sandboxed.
[cplt] Installed 'copilot' alias in ~/.zshrc [cplt] Restart your shell or run: source ~/.zshrc
A local CONNECT proxy filters and logs the agent's HTTPS traffic. By default the kernel still permits direct outbound :443, so the proxy only sees what is routed to it. Turn on proxy.forced to make it mandatory.
Agent traffic (curl, fetch, git) goes to the CONNECT proxy on localhost:ephemeral inside the sandbox. The proxy applies its blocklist and allowlist, a private IP filter and DNS rebinding protection, and writes an audit log. Allowed traffic reaches the internet: github.com, npm, PyPI, api.openai.com, anything allowlisted or not in the blocklist. Blocked traffic is dropped: webhook.site, ngrok.io, pastebin.com, 169.254.x.x, 10.x.x.x, tunneling services. proxy.blocked_domains adds to the 47 built-in domains and reloads every 5s; proxy.allowed_domains turns on fail-closed allowlist mode, which still lets the agent reach its own hosts.
By default the kernel still allows direct outbound :443, so a raw socket or an unset HTTPS_PROXY can skip the proxy. proxy.forced closes that bypass: the proxy becomes mandatory and kernel-level egress is restricted to the proxy port only. Fails closed. If the proxy cannot start, the agent does not launch. macOS pins connections to localhost:<proxy_port>, though name lookups through the system resolver still work; Linux drops the direct :443 allow, but Landlock filtering is port-based, so a narrow port-based residual remains. That is a deliberate limitation, tracked upstream.
cplt config set proxy.forced trueBehind a corporate proxy? proxy.upstream forwards CONNECT tunnels through it instead of forcing you to disable the cplt proxy. cplt applies its own domain filtering, logging, and port checks before forwarding the tunnel upstream, so a blocked target never reaches the corporate proxy. Optional basic-auth userinfo is supported; http scheme only.
cplt config set proxy.upstream "http://proxy.example.com:8080"cplt init scans your project for build files, frameworks, and patterns, then generates the right .cplt.toml automatically.
Detected: Spring Boot application.yml + spring-boot-starter Flyway db/migration/ directory Docker Dockerfile + compose.yml Gradle build.gradle.kts .env .env.example found Generated .cplt.toml: # Deny access to sensitive env vars [deny] env = ["API_KEY", "DB_PASSWORD"] [propose] # ⚠️ grants access to the Docker socket, effectively root on the host allow_docker = true allow_jvm_attach = true allow_localhost_any = true [propose.allow] localhost = [5432, 8080] Run cplt init --write to save
Each detector knows which sandbox permissions the ecosystem needs. Dangerous permissions get risk warnings.
Detects Gradle wrapper, Playwright browsers, GPG signing, and alternative agents on your machine. Writes to ~/.config/cplt/config.toml.
Every option explained. Search by name or description.
74 options
proxy.enabledbooldefault: trueEnable the CONNECT proxy for outbound HTTPS traffic logging and domain filtering.
cplt config set proxy.enabled false --forceproxy.forcedbooldefault: falseForce all egress through the proxy: make the proxy mandatory and restrict kernel-level egress to the proxy port only (no direct *:443). Fails closed if the proxy cannot start.
cplt config set proxy.forced trueproxy.portintegerdefault: 0Local port for the CONNECT proxy listener.
cplt config set proxy.port 8080proxy.blocked_domainsstringdefault: ""Path to a file listing domains to block through the proxy (one per line).
cplt config set proxy.blocked_domains "~/.config/cplt/blocked-domains.txt"proxy.allowed_domainsstringdefault: ""Path to a file listing the only domains allowed through the proxy (allowlist mode).
cplt config set proxy.allowed_domains "~/.config/cplt/allowed-domains.txt"proxy.default_allowlistbooldefault: falseFail-closed networking (opt-in): restrict egress to the agent's built-in default allowlist (e.g. GitHub Copilot infrastructure + package registries) merged with allowed_domains; block all other domains. Override for one run with --allow-all-domains.
cplt config set proxy.default_allowlist trueproxy.log_filestringdefault: ""Path to write proxy connection logs (CONNECT requests and outcomes).
cplt config set proxy.log_file "~/.cache/cplt/proxy.log"proxy.log_levelstringdefault: noneStderr verbosity for proxy events: "none" (silent), "error" (DNS/connect failures), "blocked" (errors + blocked connections), "all" (everything including CONNECTED). With an allowlist, an unset level shows blocked connections; an explicit "none" stays silent. The separate log_file records everything.
cplt config set proxy.log_level blockedproxy.timeoutintegerdefault: 60Timeout in seconds for proxy request/header reads. Established tunnels may idle up to 1h.
cplt config set proxy.timeout 120proxy.upstreamstringdefault: ""Upstream (corporate) proxy URL to forward CONNECT tunnels through, e.g. "http://corporate-proxy.example.com:8080". cplt still enforces all domain filtering, logging, and port checks before forwarding. Optional basic-auth userinfo is supported; only the http scheme is supported.
cplt config set proxy.upstream "http://proxy.example.com:8080"proxy.upstream_no_proxystring[]default: []Hosts that BYPASS the upstream proxy and are connected to directly (like NO_PROXY). Only meaningful with proxy.upstream. Suffix matching: "example.com" covers all subdomains; CIDR/IP ranges are NOT honored. Merged additively with the ambient NO_PROXY/no_proxy environment. All of cplt's domain/port/SSRF filtering still applies, so an internal host that resolves to a private IP is BLOCKED (403) unless you ALSO add it to proxy.allow_private_domains.
cplt config set proxy.upstream_no_proxy intern.example.comproxy.allow_private_domainsstring[]default: []Domains allowed to resolve to private/internal IPs (opt-in DNS-rebinding bypass). Use for corporate intranet services. Suffix matching: "intern.nav.no" covers all subdomains.
cplt config set proxy.allow_private_domains intern.example.comallow.readstring[]default: []Extra directories to allow read access (e.g., shared libraries outside the project).
cplt config set allow.read "~/shared-libs"allow.writestring[]default: []Extra directories to allow write access (use sparingly, the project dir is already writable).
cplt config set allow.write "~/shared-libs"allow.execstring[]⚠ dangerousdefault: []\u{26a0}\u{fe0f} DANGEROUS: Trees the agent may execute binaries from (e.g. a relocated Homebrew prefix). Read + execute, never write. Refused for an unsafe root (/, /tmp, $HOME and its parents, the platform system dirs) and for any tree that overlaps a writable one \u{2014} writable + executable is a binary-drop path.
cplt config set allow.exec "/opt/toolchain"allow.socketstring[]default: []Unix socket paths to allow access to.
cplt config set allow.socket "~/.colima/default/docker.sock"allow.domainsstring[]default: []Domains to add to the proxy allowlist. Adds to an allowlist already in force; does not turn one on.
cplt config set allow.domains registry.example.comallow.portsinteger[]default: []Additional outbound ports to allow (443 is always allowed).
cplt config set allow.ports 3000allow.localhostinteger[]default: []Specific localhost ports to allow outbound connections to (e.g., local dev servers).
cplt config set allow.localhost 3000deny.pathsstring[]default: []Extra paths to deny access to (overrides project-dir allows for sensitive subdirs). Each entry is one literal path: globs such as `**/*.pem` are not expanded.
cplt config set deny.paths "~/secrets"deny.envstring[]default: []Environment variables to strip from the sandbox (repo-local only: tightens env filtering).
cplt config set --repo deny.env VAULT_TOKENsandbox.agentstringdefault: ""Preferred AI coding agent (copilot, opencode, gemini, antigravity, pi, claude, goose, dsh, shell). Auto-detected from PATH if not set.
cplt config set sandbox.agent opencodesandbox.presetstringdefault: standardSecurity posture baseline: "standard" (the default: both guards on in block mode, the git guard scoped to the default branch), "strict" (all toggles off, every push blocked, proxy.forced and proxy.default_allowlist on), "permissive" or "full-trust" (both guards off, sandbox toggles loosened). Individual keys/flags override it.
cplt config set sandbox.preset strictsandbox.validatebooldefault: trueValidate the sandbox profile with sandbox-exec before launching Copilot.
cplt config set sandbox.validate false --forcesandbox.briefbooldefault: falseEXPERIMENTAL: Write the per-session agent-facing sandbox brief (CPLT_BRIEF.md) to the scratch dir. Unstable — may change or be removed in a future release.
cplt config set sandbox.brief truesandbox.agents_mdbooldefault: falseEXPERIMENTAL: Also inject the managed cplt sandbox block into the project's AGENTS.md on launch (writes into the repo). Requires sandbox.brief. Unstable — may change or be removed in a future release.
cplt config set sandbox.agents_md truesandbox.allow_env_filesbooldefault: falseAllow Copilot to read .env, .pem, .key files in the project directory.
cplt config set sandbox.allow_env_files truesandbox.allow_localhost_anybooldefault: falseAllow outbound connections to any localhost port (for local dev servers).
cplt config set sandbox.allow_localhost_any truesandbox.pass_envstring[]default: []Extra environment variables to pass through to the sandbox (exact names).
cplt config set sandbox.pass_env MY_VARsandbox.repo_dirsstring[]default: []Additional repositories this project spans (local config only: cplt config set --local). Relative paths are resolved when set; stored absolute and re-validated on every launch.
cplt config set --local sandbox.repo_dirs ../other-reposandbox.inherit_envbool⚠ dangerousdefault: false⚠️ DANGEROUS: Pass ALL environment variables instead of the safe allowlist. May leak secrets.
cplt config set sandbox.inherit_env true --forcesandbox.allow_lifecycle_scriptsbool⚠ dangerousdefault: falseAllow npm/yarn/pnpm lifecycle scripts (postinstall, prepare, etc.) to run.
cplt config set sandbox.allow_lifecycle_scripts true --forcesandbox.allow_gpg_signingbool⚠ dangerousdefault: false⚠️ DANGEROUS: Allow GPG commit/tag signing. Exposes the GPG agent socket for signature requests. Private keys stay protected.
cplt config set sandbox.allow_gpg_signing true --forcesandbox.allow_tmp_execbool⚠ dangerousdefault: false⚠️ DANGEROUS: Allow executing binaries from /tmp and /var/folders. Weakens code-exec isolation.
cplt config set sandbox.allow_tmp_exec true --forcesandbox.scratch_dirbooldefault: trueCreate a per-session scratch directory and redirect TMPDIR into it.
cplt config set sandbox.scratch_dir falsesandbox.auditbooldefault: truePrint the post-session project-change and network audit reports (net file changes vs a pinned baseline commit). Suppressed by quiet.
cplt config set sandbox.audit false --forcesandbox.use_bubblewrapbooldefault: auto-detectLinux only: wrap the sandbox in Bubblewrap namespaces (PID/IPC/UTS/cgroup/user + private /tmp) for defense-in-depth. Unset = auto-detect with fallback to Landlock-only.
cplt config set sandbox.use_bubblewrap truesandbox.quietbooldefault: falseHide the startup configuration summary (sandbox rules, network, env info).
cplt config set sandbox.quiet truesandbox.yesbooldefault: falseSkip the confirmation prompt at startup (equivalent to --yes).
cplt config set sandbox.yes truesandbox.deny_clipboardbooldefault: trueDeny the macOS clipboard (com.apple.pasteboard) to the agent, so `pbpaste` cannot read whatever was last copied. Override for one run with --allow-clipboard. No effect on Linux.
cplt config set sandbox.deny_clipboard falsesandbox.allow_jvm_attachbooldefault: falseAllow JVM Attach API unix sockets for ByteBuddy/MockK/Mockito inline mocking.
cplt config set sandbox.allow_jvm_attach truesandbox.allow_msbuildbooldefault: falseAllow MSBuild worker-node unix sockets for `dotnet build` (not the persistent MSBuild Server).
cplt config set sandbox.allow_msbuild truesandbox.gradle_initbooldefault: falseInstall a cplt-managed Gradle init script in the Gradle user home ($GRADLE_USER_HOME/init.d/ or ~/.gradle/init.d/cplt-sandbox.gradle) that applies the preferIPv4Stack workaround inside the sandbox. Inert outside sandbox builds.
cplt config set sandbox.gradle_init truesandbox.deny_nested_gitbooldefault: falsemacOS only: refuse to create a .git file, directory or symlink anywhere below a writable root, so a session cannot plant a repository whose config runs on the host (#576). Breaks `git worktree add` and fixtures that create a .git inside the project. No effect on Linux, where the session-end check is the only cover.
cplt config set sandbox.deny_nested_git truesandbox.refuse_cache_exec_linksbooldefault: falseLinux only: refuse to launch when an allow_cache_exec entry reaches its directory through a symlink inside ~/.cache, instead of granting the link's target with a warning. The agent can write ~/.cache, so it can plant or re-point such a link for the next launch. A symlinked ~/.cache itself is not affected.
cplt config set sandbox.refuse_cache_exec_links truesandbox.deny_key_files_by_extensionbooldefault: falsemacOS only: inside the project and every granted tree (--repo-dir, allow.write, allow.read), deny .pem, .key, .p12, .pfx and .jks files by extension (server.pem, tls.key), not only files named exactly .pem. Breaks anything there that reads a key or certificate: a local HTTPS dev server, key fixtures in tests, a project virtualenv's certifi/cacert.pem (pip and requests fail TLS), and system CA bundles if a grant covers /etc or /opt/homebrew. No effect on Linux.
cplt config set sandbox.deny_key_files_by_extension truesandbox.protect_pnpm_configbooldefault: falseKeep pnpm's global config dir (~/.config/pnpm, or $XDG_CONFIG_HOME/pnpm) read-only and deny its token files, auth.ini (pnpm 11+) and rc (pnpm 10 and older). Breaks pnpm installs from a private registry whose token is only in those files, and `pnpm config set --global` / `pnpm login` inside the sandbox. config.yaml stays readable. Re-allow a token file with allow.read.
cplt config set sandbox.protect_pnpm_config truesandbox.refuse_invalid_repo_configbooldefault: falseRefuse to launch when a repository's .cplt.toml cannot be loaded or has a [deny] key this cplt does not recognize, naming the problem, instead of warning and launching without those [deny] rules. Covers the launch repository and every named repository. Catches broken files, not an adversarial session.
cplt config set sandbox.refuse_invalid_repo_config truesandbox.deny_copilot_dir_execbooldefault: falseLinux only: stop granting execute on ~/.copilot, so the writable directory Copilot keeps its config in is not also a place to run a dropped binary from (#324). Copilot runs its bundled tools from ~/.cache/copilot/pkg. Breaks a plugin, MCP server, LSP server or hook launched as a program stored under ~/.copilot. No effect on macOS, where the launch warns instead.
cplt config set sandbox.deny_copilot_dir_exec truesandbox.allow_dockerbool⚠ dangerousdefault: false⚠️ DANGEROUS: Allow Docker/Colima/OrbStack access. Exposes daemon socket and ~/.docker config. Container mounts bypass sandbox.
cplt config set sandbox.allow_docker true --forcesandbox.allow_cache_execstring[]default: []~/Library/Caches subdirs to allow exec from (e.g. ["ms-playwright"] for Playwright browsers).
cplt config set sandbox.allow_cache_exec ms-playwrightsandbox.allow_cache_exec_anybool⚠ dangerousdefault: false⚠️ DANGEROUS: Allow exec from ALL ~/Library/Caches subdirs. Prefer allow_cache_exec with specific subdirs.
cplt config set sandbox.allow_cache_exec_any true --forcesandbox.allow_browserbool⚠ dangerousdefault: false⚠️ DANGEROUS: Launch Services grant for OAuth code flows. Lets the agent launch ANY application outside the sandbox, via launchd. Cannot be scoped.
cplt config set sandbox.allow_browser true --forcesandbox.keychain_substitutebooldefault: true for Copilot and Claude, false for other agentsDrop the macOS Keychain grant when the agent has a credential it can reach without it. Copilot uses `gh auth token`, Claude uses CLAUDE_CODE_OAUTH_TOKEN; both keep the grant without one.
cplt config set sandbox.keychain_substitute truesandbox.allow_build_credentialsbool⚠ dangerousdefault: false\u{26a0}\u{fe0f} DANGEROUS: Let the agent read ~/.npmrc, ~/.gradle/gradle.properties and ~/.m2/settings.xml (the files only; read-only on macOS, while Linux leaves the Maven and Gradle files read/write either way). Exposes every registry token in them, not only the one the project uses.
cplt config set sandbox.allow_build_credentials true --forcesandbox.allow_git_worktreesbooldefault: falseGrant read, write and execute on a cplt-owned directory for this repository's sub-agent worktrees (~/.cplt-worktrees/<id>, exported as CPLT_WORKTREE_ROOT). Worktrees and branches there persist after the session. macOS only. User config only; .cplt.toml cannot propose it.
cplt config set sandbox.allow_git_worktrees truesandbox.worktree_walk_max_dirsintegerdefault: 100000With allow_git_worktrees on: how many directories the check of the worktree root visits at launch and session end. Past it the launch refuses to start, since a .git beyond it would go unseen. Raise it for large dependency trees.
cplt config set sandbox.worktree_walk_max_dirs 200000sandbox.gh_proxybooldefault: falseDEPRECATED: use [gh_guard] section instead. Enables gh CLI proxy.
cplt config set sandbox.gh_proxy truesandbox.git_push_preventionbooldefault: falseDEPRECATED: use [git_guard] section instead. Enables git push prevention.
cplt config set sandbox.git_push_prevention truegh_guard.enabledbooldefault: trueEnable gh CLI proxy that blocks destructive GitHub operations (delete repo, merge PR, etc.).
cplt config set gh_guard.enabled false --forcegh_guard.modestringdefault: blockEnforcement mode: "block" (deny and exit), "warn" (print warning, allow), or "audit" (silent log).
cplt config set gh_guard.mode audit --forcegh_guard.scope_checkbooldefault: trueEnforce same-repo check. Blocks operations targeting other repositories via the -R flag.
cplt config set gh_guard.scope_check false --forcegh_guard.block_auth_tokenbooldefault: trueBlock 'gh auth token' command to prevent credential exfiltration.
cplt config set gh_guard.block_auth_token false --forcegh_guard.inject_tokenbool⚠ dangerousdefault: falseDEPRECATED on macOS: gh gets its token from the gh guard, Copilot from sandbox.keychain_substitute. Still needed on Linux when Copilot's login sits in the Secret Service. Pre-extracts GH_TOKEN into the agent env (Copilot only).
cplt config set gh_guard.inject_token true --forcegh_guard.unknown_commandstringdefault: blockPolicy for commands not in the classification table: "block" (default-deny) or "allow" (permissive).
cplt config set gh_guard.unknown_command allow --forcegh_guard.allow_api_writebool⚠ dangerousdefault: falseAllow 'gh api' write operations (POST/PATCH/PUT and input flags). Writes are scope-checked to the current repo. GraphQL is always blocked.
cplt config set gh_guard.allow_api_write true --forcegh_guard.allow_pr_mergebool⚠ dangerousdefault: falseAllow 'gh pr merge' of the account's own PRs, in scope, into a branch where an active ruleset the account cannot bypass requires an approving review that a new push dismisses. '--admin' is always refused.
cplt config set gh_guard.allow_pr_merge true --forcegit_guard.enabledbooldefault: trueIntercept git push, request-pull and send-pack. What happens to an intercepted command is `mode`: block (default) refuses it, warn prints and runs it.
cplt config set git_guard.enabled false --forcegit_guard.modestringdefault: blockEnforcement mode: "block" (default: deny and exit), "warn" (print warning, allow), or "audit" (silent log).
cplt config set git_guard.mode audit --forcegit_guard.prevent_pushbooldefault: trueTreat git push, request-pull and send-pack as violations. `mode` decides what a violation costs.
cplt config set git_guard.prevent_push false --forcegit_guard.prevent_force_pushbooldefault: trueBlock force push (only meaningful when prevent_push is false).
cplt config set git_guard.prevent_force_push false --forcegit_guard.protect_default_branch_onlybooldefault: trueOnly block pushes to the default branch (main/master), the default outside --preset strict. Set false to block every push.
cplt config set git_guard.protect_default_branch_only falsegit_guard.allow_pushtable[]⚠ dangerousdefault: []Structured push exceptions. Each entry specifies remote/branches/force conditions under which push is allowed.
cplt config explain git_guard.allow_pushshell.skipstring[]default: []Agents the PATH shim sync leaves out (e.g. ["goose"] when your goose is pressly/goose, the migration tool). Only matters after `cplt --shell-install --shims`.
cplt config set shell.skip gooseOpen source, MIT licensed, built at Nav.