К основному содержанию
скилл CX Codex

setup · stefanoginella — скилл для Claude Code: настройка aicontainer в проекте

Проводит проект от «песочницы нет» до запуска ИИ-агента внутри devcontainer aicontainer с настройкой под конкретный стек.

Установить в Claude Code · Через Skills CLI (Vercel) Все способы и платформы ↓
npx skills add stefanoginella/aicontainer --skill setup -a claude-code
Открыть на GitHub

Что делает setup

Скилл определяет стек проекта, проверяет, подходит ли вообще Linux-контейнер, предлагает план кастомизации и после подтверждения применяет его. Вся работа идёт с хоста: если /etc/aic уже существует или выставлены переменные REMOTE_CONTAINERS, DEVCONTAINER, AIC_TOOLS, значит вы внутри песочницы, и запись в .devcontainer/ заблокирована хуком PreToolUse — тогда скилл останавливается и просит запустить настройку из терминала хоста.

Кастомизация живёт только в файлах, которые принадлежат проекту: Dockerfile.project, docker-compose.override.yml, chown-paths, post-create.project.sh, vscode-extensions, firewall-allowlist, shell-rc.zsh, statusline.{sh,mjs,js,py}. Файлы devcontainer.json и docker-compose.yml трогать нельзя: их пишет aic init, а aic sync перезаписывает, выживают только выборы AIC_TOOLS и AIC_SHELL. Собирает не aic up, а aic rebuild — у управляемого Compose стоит pull_policy: missing, поэтому закэшированный образ переиспользуется и Dockerfile.project не выполняется.

Если скилл пишет Dockerfile.project или добавляет монтирование, aic validate, up и rebuild будут падать до тех пор, пока человек не выполнит aic trust. Команда требует TTY, из инструмента Bash её не запустить, и обойти это флагом --allow-unsafe нельзя. Доверие привязано к хешу конфигурации: любая правка docker-compose.override.yml или Dockerfile.project его снимает, так что конфиг стоит довести до финала до запроса.

Какие задачи решает

  • определить стек проекта и решить, подходит ли ему Linux-devcontainer
  • собрать план кастомизации песочницы под Python, Postgres или language server
  • перенести настройки инструментов, алиасы и statusline в новое окружение
  • разобраться, почему после aic up пропали все собранные инструменты
  • пройти aic trust после правки Dockerfile.project

Примеры запросов агенту

  • Настрой aicontainer в этом проекте
  • Проверь, что мы на хосте, и предложи план кастомизации под мой стек
  • Обнови существующую настройку aicontainer под новый стек

Как установить setup

1Через Skills CLI (Vercel)

npx skills add stefanoginella/aicontainer --skill setup -a claude-code

2Вручную: положить файлы

~/.claude/skills/setup/SKILL.md

Папка скилла целиком; для одного проекта — .claude/skills/setup/

По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов

Вопросы о setup

Как установить setup в Claude Code?

Выполните npx skills add stefanoginella/aicontainer --skill setup -a claude-code. Скилл окажется в ~/.claude/skills/setup/SKILL.md.

Что делает скилл setup?

Ведёт проект от отсутствия песочницы до запуска ИИ-агента внутри devcontainer aicontainer: определяет стек, предлагает план кастомизации и применяет его после подтверждения.

Почему после aic up нет собранных инструментов?

Управляемый Compose использует pull_policy: missing, и закэшированный образ переиспользуется без сборки Dockerfile.project. Собирает aic rebuild.

Исходный текст

SKILL.md · MIT
---
description: "Manual setup of aicontainer (the sandboxed devcontainer for running AI coding agents in bypass/auto-approve mode) in a project."
disable-model-invocation: true
---

# Set up aicontainer in a project

Your job is to take a project from "no sandbox" to "the AI agent runs behind the
aicontainer devcontainer boundary, configured for *this* project's stack." You
detect the stack, sanity-check that a Linux devcontainer is even the right tool,
propose a concrete customization plan, and — once the user approves — apply it.

aicontainer's whole point is letting Claude Code / Codex / OpenCode run with
permissions skipped *without* handing a prompt-injected dependency your real
`$HOME`, `.env`, SSH keys, or `gh` token. Good setup is what makes that sandbox
actually usable for the project — a Python repo needs a writable `.venv`, an
agent that uses go-to-definition needs a language server on `PATH`, a Postgres
app needs the DB reachable. That per-project wiring is the work here.

The other half is the *person*: their tool settings, prompt, aliases, and
statusline. Some of that is seeded automatically, some is deliberately dropped,
and some needs an explicit opt-in they'd never guess at. Step 6 walks them
through it — a sandbox the user can't stand working in doesn't get used.

## Golden rules (read first — they shape everything below)

These come straight from how aicontainer is designed; violating them creates work
that silently gets wiped or breaks `aic sync`.

- **Run `aic` from the host, never from inside the container.** Setup happens
  before (or outside) the sandbox. If you detect you're *inside* an aicontainer
  already (see Step 0), stop and tell the user to run this from a host terminal —
  `.devcontainer/` is mounted read-only in the sandbox by design.
- **Never hand-edit `.devcontainer/devcontainer.json` or
  `.devcontainer/docker-compose.yml`.** They are template-managed: `aic init`
  writes them and `aic sync` overwrites them (only the `AIC_TOOLS` / `AIC_SHELL`
  choices survive). All per-project customization goes in the **project-owned**
  files instead (listed in the next rule). Edits to the managed files get reset on the
  next sync.
- **All customization lives in project-owned files** that `aic sync` never
  touches: `Dockerfile.project`, `docker-compose.override.yml`, `chown-paths`,
  `post-create.project.sh`, `vscode-extensions`, `vscode-settings.json`,
  `firewall-allowlist`, `firewall-enable`, `firewall-presets`, `shell-rc.zsh`,
  `p10k.zsh`, `statusline.{sh,mjs,js,py}`. These are opt-in by presence.
- **`aic rebuild` is the verb that builds — `aic up` is not.** `aic up` runs a
  plain `devcontainer up`, and the managed pull-mode Compose sets
  `pull_policy: missing`: when the resolved image tag is already cached, Compose
  reuses it and **never runs your `Dockerfile.project`**. The stack comes up
  looking healthy on the plain base image, with every baked tool missing and
  every named volume still `root:root`. `aic rebuild` adds
  `--remove-existing-container --build-no-cache`, which is what actually builds.
  So: if the plan writes a `Dockerfile.project`, the first boot is `aic rebuild`,
  and so is every boot after you edit it.
- **Host-boundary trust is the user's to grant — you can't, and shouldn't.** A
  `Dockerfile.project` (or an added mount, a protected env key, Docker socket
  exposure) makes `aic validate` / `up` / `rebuild` fail closed until the human
  runs `aic trust`, which **requires a TTY** and so cannot run from your Bash
  tool. Hand it to them; never route around it with `--allow-unsafe`. Trust
  binds to an exact config hash, so **any** later edit to
  `docker-compose.override.yml` or `Dockerfile.project` revokes it — settle the
  config completely before you ask (Step 8).
- **Show the plan, then apply.** Detect and confirm first, present the full plan,
  get a yes, then write files and run `aic init` / `aic sync`. **Confirm before
  the first boot** — it pulls or builds a multi-gigabyte image and can take
  minutes — but once the user says go, drive it yourself: verify the container
  actually boots and fix what's broken (Step 9). Don't just hand back a command
  and hope.

## Step 0 — Preconditions

Before anything, confirm the ground is solid:

1. **Are we on the host, or already inside an aicontainer?** If `/etc/aic` exists,
   or env vars like `REMOTE_CONTAINERS` / `DEVCONTAINER` / `AIC_TOOLS` are set,
   you're *inside* the sandbox — `.devcontainer/` writes are blocked by the
   PreToolUse hook. Stop and tell the user to run setup from a host terminal.
2. **Is this a git repo?** `aic init` expects a project directory. If there's no
   repo, that's fine, but note it (the sandbox bind-mounts `$PWD` as `/workspace`
   regardless).
3. **Is the `aic` CLI installed?** Check `command -v aic`. If it's missing,
   don't abort — **offer to install it**, since nothing else in this skill works
   without it:
   - **Confirm Node.js 18+ first** (`node --version`) — it's the one
     prerequisite for the npm install (and the bundled `@devcontainers/cli`). If
     Node is too old or absent, say so and point the user at it rather than
     attempting the install.
   - **Offer the install and wait for a yes** — this is a global package
     install, so never run it silently. The default method is
     `npm install -g aicontainer`. If the user prefers a git checkout, the
     alternative is
     `git clone https://github.com/stefanoginella/aicontainer ~/.aicontainer && ~/.aicontainer/install.sh`
     (a checkout also needs `npm install -g @devcontainers/cli` separately).
   - **Verify after installing** — re-run `command -v aic` (or `aic --version`)
     and confirm it's now on `PATH` before continuing. If the install failed or
     `aic` still isn't found, stop and surface the error; don't push ahead into
     the steps below.
4. **Is Docker running?** `docker info` should succeed (Docker Desktop / OrbStack
   / Colima). Setup can still proceed without it, but Step 9's boot verification
   (and `aic up` generally) will need it — note it rather than blocking.
5. **Is there already an aic setup here?** If `.devcontainer/devcontainer.json`
   exists and references aicontainer (the GHCR image or `AIC_TOOLS`), this is a
   *re-setup*, not a fresh install — you're in **update mode**. Don't regenerate
   from scratch and don't re-propose files that already exist and are correct.
   Still read the docs (Step 1) and re-detect/confirm the stack (Steps 2–3),
   then follow "Update mode" below instead of the greenfield Step 5. (If no
   `.devcontainer/` exists, it's a fresh setup — continue straight through
   Steps 1–10.) A missing `.devcontainer/` still isn't proof of a clean slate: a
   repo set up under an older aic can leave a stale legacy Docker volume/stack
   that `aic up` migrates automatically (`aic: migrating legacy session
   transcripts …`). That's expected, not an error — don't treat it as a failure.
6. **Is a stale stack still running for this path?** The Compose project name is
   derived from the canonical path (`aic-<basename>-<hash>`), so a *previous*
   setup for this directory — even one whose `.devcontainer/` is long gone — can
   still own containers and volumes in the same namespace. `aic up` deliberately
   does **not** pass `--remove-orphans` (it can't attribute them), so those
   services keep running and resurface later as mystery containers in `docker
   compose ps`. Look now:
   `docker ps -a --filter "name=aic-<basename>-"` and
   `docker volume ls --filter "name=aic-<basename>-"`. The clean sweep is
   `aic down` (which *does* use `--remove-orphans`) once a config exists. Stale
   named volumes may hold real data — surface them and let the user decide;
   never delete a volume unasked.

## Update mode — auditing an existing setup

When Step 0 found an existing aic setup, the job is **not** "generate config." It
is "check whether this project's personalization still fits its stack, and update
only what's missing, stale, or drifted." A project set up months ago may have
gained a language, a service, browser e2e tests, or new build artifacts — or had
the global `aic` upgraded under it. Read the docs (Step 1) and refresh the
stack profile (Steps 2–3) first, then:

1. **Inventory what's already there.** List which project-owned files exist and
   **read their contents**: `Dockerfile.project`, `docker-compose.override.yml`,
   `chown-paths`, `post-create.project.sh`, `vscode-extensions`,
   `vscode-settings.json`, `firewall-allowlist`, `firewall-enable`,
   `firewall-presets`, `shell-rc.zsh`, `p10k.zsh`, `statusline.{sh,mjs,js,py}`. Also
   note the current `AIC_TOOLS` / `AIC_SHELL` in `devcontainer.json` (the only
   managed values that survive `aic sync`), and which host-global overlays
   already exist at `~/.config/aicontainer/` (`rc.zsh`, `p10k.zsh`,
   `statusline.*`). This is your baseline — what's already covered.
2. **Compute the delta against the refreshed stack — look for three things:**
   - **Missing coverage** — a stack fact with no matching personalization: a new
     language with no LSP server in `post-create.project.sh` and no editor
     extension; a Python project with no writable `.venv` volume; a newly-added
     Postgres/Redis service not wired in `docker-compose.override.yml`;
     Playwright/Chromium added with no `Dockerfile.project`. Compare each
     confirmed stack against its `## Stack:` section in the stack reference
     (Step 1) — that section lists everything the stack should have.
   - **Missing personalization** — the user's environment, not the stack: no
     shell/prompt overlay and no statusline while their host has them (Step 6),
     or a statusline copied into the seed dir that has since drifted from the
     host original. An existing setup predating a slot won't have it; offer it
     rather than assuming they declined.
   - **Stale / incorrect entries** — personalization that no longer matches: a
     `chown-paths` line for a volume that's no longer declared; a
     `vscode-settings.json` interpreter path that no longer exists; an LSP install
     or extension for a language the project dropped; a tool in `AIC_TOOLS` the
     user no longer wants.
   - **Version / base drift** — the tooling flags this one: after
     `npm update -g aicontainer`, a `Dockerfile.project` whose `FROM …:vX.Y.Z`
     lags the tag now pinned in `docker-compose.yml`. `aic sync` **warns**; the
     fix is `aic sync --bump-base` (it rewrites the `FROM` in place — never
     hand-edit a project-owned file's base for this).
3. **If nothing is missing, stale, or drifted, say so and stop.** "Your
   personalization already matches your stack; nothing to update" is a valid,
   useful outcome — don't invent changes to look busy.
4. **Otherwise present only the delta (Step 7) and apply it (Step 8).** Write the
   new/changed project-owned files, leave correct existing ones untouched, then
   run `aic sync` (the re-setup verb) so override wiring and the
   `vscode-extensions` / `vscode-settings.json` merges refresh. Then move to
   Step 9 to confirm the refreshed setup actually boots — an update that
   "should" fix a gap isn't done until you've watched it come up clean.

## Step 1 — Read the aicontainer docs for the installed version

Fetch the user-guide pages **from the release tag of the installed `aic`**, not
from `main`. `main` can describe features the user's aic doesn't have (e.g. a
`firewall-presets` file an older aic ignores — the user would believe the
firewall allows hosts, or is on, when it isn't). Tags are never rewritten, so
a tag fetch is also fixed content.

1. **Get the version:** `aic --version` prints `aic vX.Y.Z` (Step 0 made sure
   `aic` is installed). Base URL:
   `https://raw.githubusercontent.com/stefanoginella/aicontainer/vX.Y.Z/docs/user/`
2. **Fetch these pages from that base:**
   - `stack-reference.md` — **the stack → files mapping. Always fetch this
     one.** For each stack (Node.js, Python, Go, Rust, Ruby, PHP, Java, C/C++):
     marker files, `Dockerfile.project` toolchain lines, named volumes +
     `chown-paths`, `post-create.project.sh` steps (incl. the agent's LSP
     server), editor extensions/settings, firewall presets, and
     trust/caveats. Also: the shared `Dockerfile.project` /
     `post-create.project.sh` parts, how to combine stacks, the volume reset,
     and the devcontainer-fit matrix. Steps 2, 4, and 5 use it.
   - `customization.md` — `docker-compose.override.yml`, named volumes +
     `chown-paths`, `post-create.project.sh`, VS Code extensions/settings, LSP
     and `.venv` recipes. Always fetch this one.
   - `extra-tools.md` — `Dockerfile.project` and the Playwright recipe. Fetch
     when the project needs OS packages or a browser.
   - `personal-config.md` — shell overlay and statusline. Fetch when the user
     asks about their prompt or statusline.
   - Index of all pages: `…/vX.Y.Z/docs/README.md` on the same host.
   - Human URL (for linking the user):
     `https://github.com/stefanoginella/aicontainer/tree/vX.Y.Z/docs`

**When the version-matched page isn't available, pick the safe path. Never
fall back to `main` silently:**

- **Version unknown** (`aic --version` fails or prints no `vX.Y.Z`): don't
  fetch any stack page. Fix the install first (back to Step 0.3); without a
  known version, generate only what the user explicitly asks for.
- **The tag has no `stack-reference.md`** (HTTP 404 — an aic older than the
  page): tell the user their aic predates the stack reference and recommend
  `npm update -g aicontainer` (then `aic sync` in an existing project), and
  re-fetch from the new tag. If they decline:
  - installed aic is **v0.11.0 or later** (the page's baseline): you may use
    the page from `main`, but say so first, and drop every item whose
    `(since …)` marker is `Unreleased` or a version newer than the installed
    one. Name each dropped item to the user.
  - installed aic is **older than v0.11.0**: don't use the page at all; tell
    the user, and generate only what they explicitly ask for.
- **Offline / fetch failed:** use a local copy only if it is version-matched —
  a git-checkout install at `~/.aicontainer` whose `package.json` `version`
  equals the installed version. Any other copy (e.g. the plugin marketplace
  clone at `~/.claude/plugins/marketplaces/aicontainer/`) tracks `main`:
  treat it exactly like the `main` case above (say so, apply the markers).
  For the managed-vs-project-owned split, the version-matched
  `.devcontainer/README.md` that `aic init` writes and `aic help` also work.
  With no usable copy of `stack-reference.md`, don't invent stack snippets
  from memory: tell the user, and generate only what they explicitly ask for.

The docs are the source of truth for *what to generate* — `stack-reference.md`
for the stack mapping, the other pages for recipe syntax. This skill carries
the *flow and judgment*: reading the repo, confirming with the user, choosing
the optional pieces, and sequencing trust and boot
(`references/stack-and-suitability.md` has the detection judgment the page
leaves out).

## Step 2 — Detect the stack

Build a picture of what this project actually is. Read, don't guess. Cover:

- **Manifests & lockfiles** — `package.json`, `pyproject.toml` / `requirements.txt`
  / `uv.lock`, `go.mod`, `Cargo.toml`, `Gemfile`, `pom.xml` / `build.gradle`,
  `composer.json`, `*.csproj` / `*.sln`, `mix.exs`, `pubspec.yaml`,
  `Package.swift`, `*.xcodeproj`, `CMakeLists.txt`.
- **Runtime/version pins** — `.nvmrc`, `.python-version`, `.tool-versions`,
  `.ruby-version`, `Dockerfile`, existing `docker-compose.yml`.
- **Services the app needs** — scan `docker-compose.yml` services, `.env.example`
  / `.env.sample` keys (`DATABASE_URL`, `REDIS_URL`, …), ORM/migration config.
  These become host-service or sibling-container wiring.
- **Test/automation tooling** — especially browser e2e (`@playwright/test`,
  `cypress`, `puppeteer`) and native build steps, which need a `Dockerfile.project`.
- **`.md` design docs** — `README.md`, `ARCHITECTURE.md`, `docs/`, PRD / spec /
  design files. Lean on these when code signals are thin or the repo is greenfield;
  a spec saying "React + FastAPI + Postgres" is a real signal.

The "Detect a stack" table in `stack-reference.md` maps marker files to stack
sections; `references/stack-and-suitability.md` covers the signals a marker
table can't (services, design docs, greenfield repos). The goal is a short
profile: **language(s) + package manager(s) + runtime versions +
services + test tooling + any GUI/mobile/native/hardware signals.**

## Step 3 — Confirm the stack with the user

Don't proceed on a guess. Present the detected profile compactly and ask the user
to confirm or correct it — use AskUserQuestion when the choice is crisp, plain
prose when it's open. If detection was inconclusive (sparse repo, unfamiliar
layout), **ask the user directly** what the stack is rather than inventing one.
The customization plan is only as good as this profile, so it's worth the round-trip.

## Step 4 — Check devcontainer suitability

aicontainer is a **headless Linux** devcontainer. Most server / web / CLI /
library / data / ML-on-CPU work is a great fit. Some work fundamentally can't run
here — flag it *before* generating config so the user isn't surprised after a
rebuild. The fit/non-fit list (iOS/macOS-native, Windows-native, host-display
GUI, hardware passthrough, Android emulator, GPU/CUDA) is the "Check the fit"
section of `stack-reference.md` — classify against it. Also a non-fit here: no
Docker runtime at all (Step 0) — nothing runs without one.

When you hit a non-fit, say so plainly, explain what specifically won't work, and
note whether a **partial** setup still helps (e.g. an iOS app with a Node backend
— sandbox the backend, build the app on the host). Then let the user decide
whether to proceed. Don't silently generate a config that can't work.

## Step 5 — Choose tools, shell, and map the stack to customization

First the two `aic init` choices (ask, or take the defaults and say so):

- **AI tools** (`--with`): `claude-code`, `codex`, `opencode`, or a comma-list.
  Default is all three.
- **Shell** (`--shell`): `zsh` (default), `bash`, or `fish`.

Then map the confirmed stack to **project-owned files** with
`stack-reference.md` (Step 1). That page is the single source for the
mapping — take the snippets from it; don't keep or improvise a private copy:

- **One `## Stack: <name>` section per confirmed stack.** Every section has the
  same subheadings in the same order — Detect, Toolchain, Named volumes and
  chown-paths, Post-create, Editor, Firewall presets, Trust and caveats — so
  read each one and carry its snippets into the plan.
- **Two or more stacks → its "Combine stacks" section.** One file of each kind:
  one `FROM`, one override `services.devcontainer` block, one `post-create`
  header, merged `chown-paths` / `vscode-extensions` / `vscode-settings.json`.
- **Shared parts → its "Common files" section**: the `Dockerfile.project`
  `FROM` line and the override `build:` block with its own `image:` tag, the
  `post-create.project.sh` header, and the post-create constraints (guard on
  the manifest, read-only `.git/hooks`, `NPM_CONFIG_IGNORE_SCRIPTS`).
- **Host services and browser e2e** are add-ons, not stacks: the page's
  "Detect a stack" table links to the override example and the Playwright
  recipe.
- **A stack the page doesn't cover** (.NET, Elixir, Dart, …): say so plainly.
  Propose only the common files and the pattern of the stack sections, flag
  that none of it is tested, and get the user's explicit yes before you write
  toolchain lines for it.

Judgment that stays with you:

- **Optional pieces are the user's call.** The page marks some entries
  optional (a `node_modules` volume, a C/C++ build-dir volume, the Poetry
  variant). Offer them; don't impose them.
- **The firewall files are opt-in.** `firewall-enable` / `firewall-presets` /
  `firewall-allowlist` fit stricter containment (reviewing untrusted code,
  corporate LAN). Off by default; mention it, don't impose it. If the user opts
  in, take the preset names and extra hosts from the stack sections.
- **Every `Dockerfile.project` costs one `aic trust` and makes `aic rebuild`
  the boot verb** — the golden rules above. Plan the sequence around them.
- **Personal overlays (`shell-rc.zsh`, `p10k.zsh`, `statusline.*`)** are
  *personalization*, not stack mapping, and they're the piece users most often
  assume happens automatically. Handle them in **Step 6**, not here.

**LSP is a first-class concern** (the user cares about it). Make explicit that
there are *two* LSP surfaces: the **editor's** IntelliSense (extensions +
settings) and the **agent's** LSP tool (a language-server binary on `PATH`,
installed from `Dockerfile.project` or `post-create.project.sh`). A project
usually wants both. Each stack section of `stack-reference.md` has both: the
Editor subsection, and the server in Toolchain or Post-create.

## Step 6 — Port the user's host config and preferences

A sandbox that builds the project but feels alien to work in is a half-done
setup. This step closes the gap between "the container runs" and "it's *my*
environment." Do it for fresh setups and update-mode runs alike.

Lead with what's already handled — most users assume nothing carries over, and
that's wrong. **Don't re-explain the whole boundary; tell them what to *do*.**

### 6.1 — Already automatic: nothing to do but keep it current

Before every `aic up`/`rebuild`, a root-only, networkless one-shot sanitizer
reads four fixed host files and emits allowlisted JSON the container consumes
read-only. The user edits these **on the host** and re-runs `aic rebuild`:

| Host file | Carries over |
| --- | --- |
| `~/.claude/settings.json` | model, effort, editor mode, theme, plugins/marketplaces, MCP servers, verbosity… |
| `~/.codex/config.toml` | model, reasoning effort, personality, `[mcp_servers.*]`, `[projects.*]` |
| `~/.config/opencode/opencode.json` | provider/model, agents, instructions, theme, keybinds, formatter, lsp, mcp |
| `~/.gitconfig` | identity + non-executable workflow prefs (pull/push/rebase/diff/merge) |

### 6.2 — Deliberately dropped: say so before they hunt for it

Not bugs — the allowlist exists because these either defeat the sandbox or carry
host-only paths/secrets. State the *replacement*, not just the removal:

- **`permissions`, `hooks`, Codex `approval_policy` / `sandbox_mode`** — the
  container enforces its own at root-managed precedence. That's the whole point.
- **`env` blocks, inline MCP `env`/`headers`, API keys/tokens** — never
  forwarded. Replacement: log in **inside** the container once (`claude`,
  `codex`, `opencode auth login`, `gh auth login`, `npm login`); credentials
  persist in a global volume across rebuilds and projects.
- **`statusLine`** — a command string pointing at a host path. Replacement: the
  statusline overlay in 6.3.
- **Git `credential.helper`, aliases, `include`/`includeIf`, `core.hooksPath`,
  signing key paths** — command/path-bearing. Replacement for signing: `aic
  signing` provisions a sandbox-only key (the host key is never forwarded).
- **Host `~/.zshrc` / `~/.p10k.zsh`** — never auto-forwarded. Replacement: 6.3.
- **MCP servers pointing at host-only binaries** will be seeded but fail to
  start in Linux; URL-based and npm-installed ones work. Worth naming if the
  user has any, so a startup error later isn't a mystery.

### 6.3 — The opt-in overlays: offer to set them up

Three independent slots, all **opt-in by file presence**, all surviving `aic
sync`, each available host-globally (once, every project) or per-project:

| What | Host-global seed | Project file |
| --- | --- | --- |
| zsh startup (aliases, functions, exports) | `~/.config/aicontainer/rc.zsh` | `.devcontainer/shell-rc.zsh` |
| powerlevel10k prompt | `~/.config/aicontainer/p10k.zsh` | `.devcontainer/p10k.zsh` |
| Claude Code statusline | `~/.config/aicontainer/statusline.{sh,mjs,js,py}` | `.devcontainer/statusline.{sh,mjs,js,py}` |

Mind the **filename asymmetry**: the shell rc is `rc.zsh` host-side but
`shell-rc.zsh` project-side. `p10k.zsh` and `statusline.*` use the same name in
both places. The project file wins when both exist. All take effect on the next
`aic rebuild`.

The statusline slot is the script only — aicontainer supplies the command
(`/usr/local/bin/aic-statusline`, a fixed launcher) and picks the interpreter
from the **extension**: `.sh`→bash, `.mjs`/`.js`→node, `.py`→python3. So:

- **One self-contained file.** A statusline that `import`s sibling modules
  breaks; vendor it or pick a different one. Its own state under
  `~/.claude/statusline/` is writable and per-project, so caches work.
- Anything it shells out to must exist in the container (`git` does; host-only
  binaries don't).
- **Best host setup:** keep the real script *at* `~/.config/aicontainer/statusline.mjs`
  and point the host `~/.claude/settings.json` there too — one file, no drift.
  Otherwise it's a copy that will go stale; say so.

> ⚠️ All three are **code, not data**: they cross **verbatim** (they can't be
> sanitized) and the in-container agent can read them. **No secrets, ever** — and
> flag that host paths/usernames baked into them become visible in the sandbox.
> They land root-owned `0444`, so once installed the agent can't modify them, and
> they run only as the unprivileged `vscode` user.

### 6.4 — Offer to draft the overlays from their host files (optional)

Users who want "my shell/statusline inside the sandbox" usually already have a
host `~/.p10k.zsh`, `~/.zshrc`, or statusline script and reasonably expect them
to appear. They don't — host dotfiles routinely hold secrets and host-specific
breakage, and this sandbox runs an untrusted agent that can read whatever is
mounted. So *offer to bridge that gap*: **draft** the overlay from their host
files — an assisted, reviewed draft, never a silent transform.

This is safe to do here because *you* run on the **host**, as the user's
permissioned session — a different trust context from the sandboxed
bypass-permissions agent the threat model targets, and you can already read
these files. The trust anchor holds **only if the user stays the approver**: you
move them from author to reviewer, you don't remove them. Do not auto-place a
drafted file.

When the user opts in:

1. **Read the host files** host-side — `~/.p10k.zsh`, `~/.zshrc`, and the script
   named by their host `statusLine.command` (parse the path out of
   `~/.claude/settings.json`; don't guess a location).
2. **`p10k.zsh` — near-verbatim.** Almost always `p10k configure` output:
   declarative `typeset -g POWERLEVEL9K_*`, no secrets. Copy it, but **scan** for
   the unusual — custom segment functions that shell out, hardcoded host paths,
   anything secret-shaped — and flag those.
3. **`rc.zsh` — whitelist-extract, don't blacklist-strip.** Pull only
   clearly-safe categories (aliases, simple functions, `setopt`, keybindings,
   prompt tweaks). Leave everything else behind: `export *_KEY/_TOKEN/_SECRET=…`,
   `source`d secret/env files, plugin managers and `eval "$(tool init)"` for
   tools not in the sandbox, aliases to host-only binaries. **When in doubt,
   leave it out.**
4. **`statusline.*` — copy whole, then audit.** Unlike an rc file you can't
   extract "the safe half" of a program, so it's all-or-nothing: read the whole
   script and report what would break or leak — a hardcoded host path, a
   host-only binary it shells out to, an API token, a network call, a sibling
   `import`. If any of those are present, say so and let the user decide between
   fixing the script, dropping the slot, or accepting it.
5. **Be honest about the two distinct risks when you present it.** You are
   *reliable* at avoiding breakage ("this sources oh-my-zsh at a host path —
   dropped"); you *assist but cannot certify* secret removal. Never say "I
   sanitized your config" — say "here's a lean draft; review it and confirm there
   are no secrets."
6. **Show a kept / dropped-with-reason summary** per file and fold the candidates
   into the Step 7 plan. Require an explicit yes — this is content pulled from the
   user's private files, so it gets its own focused look, not a blanket approval.
7. **On approval, write** to `~/.config/aicontainer/` (host-global — one setup
   for every project) or `.devcontainer/` (this project only), as the user
   prefers, using the filenames in 6.3's table.

If the user declines, or you can't confidently produce a clean draft, fall back
to the manual path: they place the files by hand — no secrets — then `aic
rebuild`. Either way, verify the result in Step 9 (`aic run test -r
/etc/aic/user-config/statusline/statusline.mjs`, `aic run
/usr/local/bin/aic-statusline`, or a login `zsh -lic true`) rather than assuming
it landed.

## Step 7 — Present the plan

Show the user, before touching anything:

1. The confirmed stack and the suitability verdict.
2. The `aic init` invocation (with `--with` / `--shell`).
3. Each project-owned file you'll create, **with its contents**, and one line on
   *why* (which stack fact drives it).
4. **The Step 6 personalization**, called out separately from the stack wiring —
   what carries over untouched, what is deliberately dropped and what replaces
   it, and any overlay file you drafted (kept/dropped summary, its own explicit
   yes). Say plainly where each overlay lands: host-global `~/.config/aicontainer/`
   or this project's `.devcontainer/`.
5. **Whether this plan will need `aic trust`, stated up front** — name the
   finding it will produce (almost always the `Dockerfile.project` root build)
   and that they'll run one command in their own terminal at a known point. A
   user who meets the gate only when the build stops thinks setup broke.
6. That you'll offer to verify the setup boots — `aic rebuild` when...

© stefanoginella · MIT · stefanoginella/aicontainer

Похожие скиллы

Все скиллы по теме «Настройка агента: память, контекст, субагенты» →

Сначала — setup от других авторов.

setup Alireza Rezvani Собирает настройки эксперимента autoresearch: цель, файл, команду оценки, метрику и направление улучшения. Пригодится, когда вы хотите запустить цикл оптимизации файла. 1 480установок setup aws Скилл запускает настройку подключений к AWS DevOps Agent и AWS Security Agent. Нужен, когда MCP-инструменты не отвечают или вы только начинаете работу с тулкитом. CX Codex +1 1 500установок setup marketcalls Разворачивает виртуальное окружение Python для тестирования торговых стратегий на VectorBT и OpenAlgo. Настраивает зависимости, папки и файл .env. CX Codex +1 2 000установок setup assistant-ui Скилл помогает создать проект assistant-ui, подключить его к существующему приложению и выбрать адаптер для бэкенда. Пригодится и для обновления установки. CX Codex +1 6 100установок setup aladicf Собирает дизайн-контекст проекта, исследуя код и опрашивая разработчика, затем сохраняет UX-цели и стек в файл .better-web-ui.md. CX Codex +1 605установок setup-matt-pocock-skills Matt Pocock Скилл настраивает репозиторий для инженерных скиллов Matt Pocock: задаёт трекер задач, метки триажа и расположение доменной документации. Запустите его перед первым использованием остальных скиллов. 1 052 851установок ask-matt Matt Pocock Помогает выбрать подходящий скилл или рабочий поток из набора Matt Pocock. Пригодится, когда непонятно, с чего начать задачу: от идеи до разбора бага. 766 587установок to-tickets Matt Pocock Разбивает план, спецификацию или переписку на небольшие сквозные задачи и отмечает, какие из них блокируют остальные. Пригодится, когда нужно согласовать порядок работы до публикации задач в трекере. 711 230установок writing-plans Jesse Vincent Скилл превращает требования к многошаговой задаче в подробный план реализации до начала работы с кодом. Пригодится, когда исполнителю нужно зафиксировать файлы, интерфейсы и проверки. CX Codex 282 859установок caveman-review JuliusBrussee Пишет замечания к коду одной строкой: место, проблема, исправление. Пригодится, когда ревью диффа или PR надо пройти быстро и без воды. CX Codex +1 411 800установок caveman-compress JuliusBrussee Сжимает CLAUDE.md, списки задач и другие текстовые файлы в краткий формат, сохраняя читаемую резервную копию. CX Codex +1 411 500установок

Спонсоры проекта

Компании, которые помогают держать аналитику открытой