# DevCage Sandbox

Secure Docker container (Ubuntu 25.10). Workspace: `/workspace` (persists to host). Everything else is ephemeral.

**Project instructions override this document.** If the project has a CLAUDE.md, AGENTS.md, CONVENTIONS.md, CONTRIBUTING.md, or similar — follow those first. This file describes the sandbox environment and development standards.

---

## First Principles

1. **Investigate before you code.** Read the project, check git state, run existing tests. Don't edit the first file that looks relevant.
2. **Isolate dependencies.** Python: `venv`. Node: local `node_modules`. **Never install project dependencies globally.**
3. **Work in small, verified increments.** Change, test, lint, review diff, repeat. Every time — not just at the end.
4. **Test the unhappy path.** For every success case, test what happens with invalid input, missing data, and error conditions.
5. **Run ALL checks after your last change.** Fresh output only — a previous run doesn't count. Show the output.
6. **Measure, don't guess.** Playwright for UI. `wrk` for APIs. Lighthouse for frontend quality. `trivy` for security.
7. **Three strikes, step back.** If three attempts fail, the problem is deeper than you think. Re-examine your assumptions and explain to the user what you've tried.
8. **Follow existing patterns.** Match the project's code style, naming conventions, file organization, and abstractions. Consistency with the codebase matters more than personal preference or theoretical best practices.
9. **Verify before you rely on training data.** Your knowledge has a cutoff. Before using any library, framework, or tool — especially for APIs, configuration, or CLI flags — look up the current version and read its latest documentation. Outdated usage causes subtle bugs that pass linting but fail at runtime.

---

## Sandbox Environment

### Persistence

**`/workspace` persists. Everything else is lost on restart.**

| Location | Survives? |
|----------|-----------|
| `/workspace` | Yes — bind-mounted from host |
| `/workspace/.devcage/context` | Yes — inside the workspace mount |
| `/workspace/.devcage/agents/<name>` | Yes — agent state (symlinked from each agent's home dir) |
| `/home/devcage` | No — ephemeral |
| Custom mounts (`--volume`) | Host-provided; read-only by default, `:rw` for read-write |
| Global packages (`npm -g`, `pip --user`, `brew`) | No |
| Per-workspace cache volume (`/cache`) | Yes |

`/workspace/.devcage/context` is your persistent project memory. It survives container restarts and is unique to this workspace. Use it for plans, architecture maps, task lists, lessons learned, and anything you want the next session (or another agent) to find. Add `.devcage/` to `.gitignore` if you don't want it tracked.

To persist tools outside `/workspace`, add to `/workspace/.devcage/config/init.sh` (sourced at startup):

```bash
brew install lazygit
PIP_REQUIRE_HASHES=0 pip install --user httpx
```

### Network

| Destination | Reachable? |
|-------------|------------|
| Public internet | Yes |
| RFC 1918 (10.x, 172.16.x, 192.168.x) | **No — REJECT** (instant error, not a hang) |
| Link-local (169.254.x, host.docker.internal) | No |
| Container loopback (localhost) | Yes |
| DinD sidecar (`docker` hostname) | Yes |
| From DinD-spawned containers to LAN | **Blocked** (DOCKER-USER chain rules). DinD is off by default — only enabled via `--embed-docker`. |

### Constraints

- **No root.** Install via `brew install`, `PIP_REQUIRE_HASHES=0 pip install --user`, or `npm install -g`. For apt packages, ask user to restart with `--apt-packages`. For brew packages, `--brew-packages`.
- **No host browser.** Use Playwright for screenshots and visual verification.
- **`pip install` requires hash override** for ad-hoc installs: `PIP_REQUIRE_HASHES=0 pip install --user <pkg>`
- **Resource limits:** 75% of host memory/CPUs. `-Xmx512m` for Java/Gradle. Chromium uses ~200-400 MB per instance.
- **Custom volume mounts** — the user may mount additional host directories via `--volume`/`-V`. These appear at the specified container paths. Read-only by default; check with `mount | grep <path>` if unsure. If you need data that isn't at `/workspace`, check if a custom volume is mounted.
- **Auto-approve mode** — available via `claude-yolo`, `gemini-yolo`, `codex-yolo`, `aider-yolo`, `copilot-yolo`, `goose-yolo`. Default commands run in normal interactive mode.
- **GPU:** auto-detected. Check: `nvidia-smi` (NVIDIA) or `rocm-smi` (AMD). Command fails = no GPU.
- **API keys** — passed from the host environment automatically. If a key is missing, check with the user — don't create placeholder values.

### Crontab support

Scheduled tasks via `crontab` files in the config hierarchy (global, user, project). All levels concatenated and installed as the `devcage` user's crontab. Cron daemon starts automatically if non-comment entries exist.

Format: standard crontab syntax. Project-level crontab requires user confirmation (auto-approve with `--yolo-config`). Check: `crontab -l` (list entries), `pgrep cron` (verify daemon).

### Custom agent instructions (AGENTS.md)

Additional instructions via `AGENTS.md` files in the config hierarchy are appended to the base sandbox instructions with `---` separators. All agent instruction files (`~/CLAUDE.md`, `~/.gemini/GEMINI.md`, `~/.codex/AGENTS.md`) are symlinks to the same merged file. No confirmation needed.

---

## Before You Start

1. **Check context** — `ls /workspace/.devcage/context/`. If files exist, read them first — a previous session may have documented architecture, gotchas, or in-progress tasks. If empty, this is a fresh start — begin building context as you explore.
2. **Read project instructions** — CLAUDE.md, AGENTS.md, CONVENTIONS.md, CONTRIBUTING.md. They override this document.
3. **Check git state** — `git status`, `git log --oneline -10`. A previous agent may have left uncommitted work.
4. **Map the architecture** — read directory structure, identify entry points, data layer, test infrastructure.
5. **Find the task runner** — Makefile, justfile, `package.json` scripts. Run `make help` or `just --list` before inventing commands.
6. **Establish a green baseline** — install dependencies, run tests + linter. If they fail before you've touched anything, tell the user.
7. **Respect version files** — `.sdkmanrc` (auto-detected at startup), `.nvmrc`, `.python-version`, `rust-toolchain.toml`.

**Before every task:** Extract every requirement as a checklist item. You'll verify each one at the end.

---

## The Work Cycle

1. **Understand** — trace execution paths in the relevant code, check git history
2. **Baseline** — run tests and linter to confirm starting state
3. **Change** — smallest focused edit that moves toward the goal
4. **Verify** — run tests, linter, type checker. **Every time, not just at the end.**
5. **Review** — `git diff`. Matches intent? Anything extraneous? Debug code?
6. **Iterate** — repeat until all requirements met and all checks pass

**Stop-the-line rule:** When anything unexpected happens — test failure, build error, behavior regression — stop adding features. Diagnose before continuing.

### Library and dependency research

**Do not trust your training data for API usage, CLI flags, or configuration syntax.** Your knowledge has a cutoff and libraries evolve. Before using any technology:

1. **Check the installed version** — `npm list <pkg>`, `pip show <pkg>`, `go list -m <module>`, `cargo tree -p <crate>`, `dotnet list package`, or the relevant package manager command.
2. **Look up the latest version** — `npm view <pkg> version`, `pip index versions <pkg>`, or check the project's release page. If a newer major version exists, note any migration requirements.
3. **Read the current documentation** — use `curl`, `wget`, or a web search to fetch the official docs for the **installed version**. Don't guess from memory — check. Pay special attention to: breaking changes in recent versions, deprecated APIs you might still "remember", new recommended patterns that replaced old ones.
4. **When in doubt, read the source** — `node_modules/<pkg>/README.md`, installed package source, or `go doc <package>` are faster than guessing.

**Store what you learn** in `/workspace/.devcage/context/tech/` (see Project Context below). This prevents the next session — or another agent — from repeating the same research.

**When to research (non-exhaustive):**
- First use of any library, framework, or CLI tool in this workspace
- Configuring build tools, bundlers, or transpilers
- Using APIs you haven't verified against current docs
- Any technology released or significantly updated after your training cutoff
- When an API call fails unexpectedly — check if the interface changed

### File modification discipline

**Every file modification follows a before/after linting workflow:**
1. **Before editing** — run all applicable linters on the file and note the output
2. **Apply your change**
3. **After editing** — rerun the same linters
4. **Compare** — new warnings/errors were introduced by your change — fix them. Do NOT fix pre-existing issues without user confirmation

After creating a new file, run all applicable linters — all findings are yours to fix.

**Tool-to-file-type reference:**

| File type | Tools |
|-----------|-------|
| `.sh` | `shellcheck`, `shfmt -d`, `shellharden --check`, `bashate` |
| `.py` | `ruff check`, `ruff format --check`, `mypy` |
| `.js` `.ts` `.jsx` `.tsx` | `biome check` |
| `.json` | `jq . file.json > /dev/null` or `biome check` |
| `.yaml` `.yml` | `yq eval file.yaml > /dev/null` |
| `.go` | `go vet ./...`, `gofmt -d` |
| `.rs` | `cargo clippy`, `cargo fmt -- --check` |
| `.c` `.cpp` `.h` `.hpp` | `cppcheck --enable=all`, `clang-tidy`, `clang-format --dry-run` |
| `.cs` `.csproj` | `dotnet format --verify-no-changes` |
| `.html` `.css` | `biome check` |
| `Dockerfile` | `hadolint` |
| Dependencies | `trivy fs .` |
| Any source | `semgrep scan --config auto` |

### Testing

- **Use real services for integration tests.** The DinD sidecar gives you PostgreSQL, Redis, MongoDB — use them instead of mocking.
- **When a test fails, determine which side is wrong** — code broken → fix code. Test outdated → update test with clear reason. Needing to change both is a red flag — pause and verify independently.

| Indicator | Test command |
|-----------|-------------|
| `vitest`/`jest` in `package.json` | `npm test` or `npx vitest run` / `npx jest` |
| `pytest.ini`, `conftest.py`, `[tool.pytest]` | `pytest` (or `pytest -x` for fail-fast) |
| `go.mod` | `go test ./...` |
| `Cargo.toml` | `cargo test` |
| `pom.xml` / `build.gradle` | `./mvnw test` / `./gradlew test` |
| `*.csproj` / `*.sln` | `dotnet test` |
| `Makefile` / `justfile` | `make test` / `just test` — read the file first |

---

## Definition of Done

**IMPORTANT: Run every applicable check after your LAST change. Fresh output only.**

- [ ] **Tests pass** — full suite, not just yours. **Show the output.**
- [ ] **Linter clean** — no new warnings
- [ ] **Type checker passes** — `tsc --noEmit`, `mypy`, `cargo check` (if applicable)
- [ ] **Build succeeds** (if applicable)
- [ ] **Security scan** — `trivy fs .` (if dependencies changed)
- [ ] **UI verified** — before/after screenshots at multiple widths, Lighthouse a11y checked, keyboard nav tested, no inline styles, existing CSS classes reused (if UI changed)
- [ ] **Shell scripts linted** — all four tools pass: `shellcheck`, `shfmt -d`, `shellharden --check`, `bashate` (if `.sh` files modified)
- [ ] **`git diff` reviewed** — matches intent, no debug code, nothing extraneous
- [ ] **Context updated** — TODOs reflect current state, lessons captured, architecture notes current
- [ ] **Every requirement addressed** — re-read the original request, check each point

If you cannot verify something, say so: "I verified X and Y but could not verify Z because [reason]."

**"Should work" is not verification. "Probably fine" is not verification. Run the check.**

---

## Quality Gates

### Linting and formatting

Use the project's existing tools. If none configured:

| Ecosystem | Command |
|-----------|---------|
| JS/TS | `biome check --write .` |
| Python | `ruff check --fix . && ruff format .` |
| Go | `go vet ./... && gofmt -w .` |
| Rust | `cargo clippy && cargo fmt` |
| Shell | `shellcheck *.sh && shfmt -d *.sh && shellharden --check *.sh && bashate *.sh` |
| C# / .NET | `dotnet format` |
| C/C++ | `cppcheck --enable=all . && clang-tidy *.cpp` |

### Security scanning — run proactively, not when asked

**Full audit commands:**
```bash
audit                        # audit current directory (Node, Python, Go, Rust, PHP, .NET, Java, Dockerfiles, Trivy, Semgrep)
audit ~/myapp                # audit a specific project directory
audit --fix                  # audit + attempt auto-fix (npm, pip, shellharden, semgrep)
audit --no-semgrep           # skip SAST (faster)
audit --no-owasp             # skip Java OWASP check (no NVD download)
audit --no-hadolint          # skip Dockerfile linting
audit --level critical       # flag critical severity only

audit-sandbox                # audit sandbox itself (posture, npm globals, OS CVEs)
audit-sandbox --no-trivy     # skip Trivy DB download
```

**Per-tool** (run after the relevant change):
- After `npm install` → `npm audit`
- After `pip install` → `pip-audit` (install: `PIP_REQUIRE_HASHES=0 pip install --user pip-audit`)
- After any dependency change → `trivy fs .`
- Before claiming a feature complete → `semgrep scan --config auto .`

High/critical findings: fix or explain to the user why they're acceptable. Never silently ignore.

### Performance and visual verification

- **API work** → `wrk -t2 -c10 -d10s http://localhost:PORT/endpoint`
- **Frontend work** → `npx lighthouse http://localhost:PORT --output html --chrome-flags="--headless --no-sandbox"`
- **UI screenshots** → `npx playwright screenshot --full-page http://localhost:PORT screenshot.png`
- **After any UI change** → before/after screenshots at mobile (375px), tablet (768px), desktop (1280px). Visual regressions are invisible without them.
- **E2E tests** → `npx playwright test` (headless only — `--headed` and `show-report` don't work here)
- **Playwright MCP** → `npx @playwright/mcp --headless` (interactive browser for Claude Code / Gemini CLI)

---

## Frontend & UI Development

### Accessibility — WCAG 2.2 AA Compliance

**All frontend/UI work must conform to WCAG 2.2 Level AA** (which includes all Level A criteria). Verify with Lighthouse a11y audit and manual keyboard testing.

**Commonly missed criteria** (pay special attention):
- **Input purpose** — use `autocomplete` on user info fields: `name`, `email`, `tel`, `street-address` (1.3.5)
- **Reflow** — no 2D scrolling at 320px width / 256px height (1.4.10)
- **Text spacing** — must tolerate user overrides: line-height 1.5×, paragraph spacing 2×, letter-spacing 0.12em, word-spacing 0.16em (1.4.12)
- **Content on hover/focus** — tooltips must be dismissible (Escape), hoverable, and persistent (1.4.13)
- **Status messages** — use `role="status"`, `role="alert"`, or `aria-live="polite"` — no focus change required (4.1.3)

**New in WCAG 2.2** (may not be in your training data):
- **Focus not obscured** — focused element must not be hidden by sticky headers/footers/overlays (2.4.11)
- **Dragging** — any drag operation must have a non-dragging alternative (2.5.7)
- **Target size** — interactive targets ≥ 24×24 CSS pixels (inline text links exempt) (2.5.8)
- **Consistent help** — help mechanisms in same relative order across pages (3.2.6)
- **Redundant entry** — don't require re-entering info already provided in same process (3.3.7)
- **Accessible authentication** — no cognitive function tests (puzzles, transcription); allow password pasting (3.3.8)

#### Testing checklist

- [ ] Lighthouse a11y ≥ 90
- [ ] Keyboard-only: Tab through entire page, all controls reachable and operable
- [ ] Focus indicators visible on every interactive element
- [ ] Zoom 200%: no content loss, overlap, or horizontal scroll
- [ ] Color contrast verified for all text and UI components
- [ ] Screen reader: landmarks, headings, form labels, errors, status messages announced (use `axe-core`)
- [ ] Touch targets ≥ 24px, works in both orientations

---

## Dev Servers & Docker

### Dev servers — bind to 0.0.0.0

**IMPORTANT:** Dev servers must bind to `0.0.0.0` for host port forwarding to work. The user configures `--ports 3000,5173` on the host side.

| Stack | Command |
|-------|---------|
| Vite | `npm run dev -- --host 0.0.0.0` |
| Next.js | `npm run dev -- --hostname 0.0.0.0` |
| Flask | `flask run --debug --host 0.0.0.0` |
| Django | `python manage.py runserver 0.0.0.0:8000` |
| Go | Listen on `:8080` (all interfaces by default) |
| Static | `npx serve --listen tcp://0.0.0.0:3000 ./dist` |

Check port first: `lsof -i :3000 2>/dev/null`. If the user needs to see your UI, remind them to relaunch with `--ports`.

### Background processes

```bash
tmux new-session -d -s dev 'npm run dev'    # start
tmux capture-pane -t dev -p                 # read output
tmux kill-session -t dev                    # stop
```

### Docker services (DinD sidecar)

`docker` connects to an isolated DinD sidecar over TLS. If `docker info` fails, DinD isn't available — fall back to SQLite or in-process alternatives.

```bash
# PostgreSQL
docker run -d --name pg -e POSTGRES_PASSWORD=dev -p 5432:5432 postgres:17
docker exec pg pg_isready                   # wait for ready

# Redis / MySQL / MongoDB
docker run -d --name redis -p 6379:6379 redis:7
docker run -d --name mysql -e MYSQL_ROOT_PASSWORD=dev -p 3306:3306 mysql:8
docker run -d --name mongo -p 27017:27017 mongo:7

# Compose
docker compose up -d --wait                 # start and wait for health checks
docker compose down -v                      # tear down with volumes
```

After starting a database: wait for ready, run migrations, use a **separate test database**. Always use migrations — never create schema by hand. Clean up: `docker stop <name> && docker rm <name>`.

### Other services

- **Email testing:** `mailpit &` — SMTP :1025, web UI :8025
- **Local HTTPS:** `mkcert -install && mkcert localhost 127.0.0.1 ::1`
- **WebSocket:** `websocat ws://localhost:8080/ws`

---

## Project Context (`/workspace/.devcage/context/`)

`/workspace/.devcage/context` is persistent storage that survives container restarts — unique to this workspace. Add `.devcage/` to `.gitignore` if you don't want it tracked.

**Read at session start. Write as you learn. Leave it better than you found it.**

Recommended files (create as needed):

- **`SUMMARY.md`** — Project overview: what it is, tech stack, current state, recent decisions. The 30-second briefing for the next session.
- **`architecture.md`** — Structure map: entry points, data flow, key abstractions, non-obvious design decisions. Update when you discover something that would surprise the next developer.
- **`todos.md`** — Active tasks and priorities. Use checklists (`- [ ]`/`- [x]`). Update status as you work. Record what's done, what's pending, what's blocked.
- **`lessons.md`** — What went wrong, what was unexpected, what to avoid. Date each entry (newest first). Review before starting work — don't repeat known mistakes.

You can create additional files and subdirectories as the project demands. The context directory is yours to organize.

### Technology reference (`/workspace/.devcage/context/tech/`)

**Store documentation summaries and usage notes for every non-trivial technology used in the workspace.** This is critical — your training data goes stale, but these files don't.

**Directory structure:** one Markdown file (or subdirectory with multiple files) per library/framework/tool, named after it:

```
/workspace/.devcage/context/tech/
├── react-router.md          # single-file summary
├── prisma.md                # ORM usage, schema patterns, migration workflow
├── tailwindcss/             # subdirectory for larger topics
│   ├── overview.md
│   └── v4-migration.md
├── vite.md                  # build config, plugin usage
└── playwright.md            # test patterns, selectors, CI config
```

**What to include in each file:**
- **Version used** in this workspace and latest available version at time of writing
- **Key APIs and patterns** actually used in the project — not a full reference, just what's relevant
- **Configuration details** — how it's configured in this project, any non-obvious settings
- **Breaking changes / migration notes** — especially from recent major versions
- **Gotchas and workarounds** — things that didn't work as expected, with solutions
- **Links** to official docs, relevant GitHub issues, or migration guides

**When to create/update these files:**
- After researching a library's documentation for the first time in this workspace
- When you discover a breaking change or deprecated API
- When you find a non-obvious configuration requirement
- When you solve a tricky integration issue

**Session start:** check `tech/` for existing notes before using any library. **Session end:** update or create entries for any technology you researched during the session.

**Session start ritual:**
1. `ls /workspace/.devcage/context/` — anything from a previous session?
2. Read `SUMMARY.md` and `todos.md` if they exist
3. Review `lessons.md` before diving into code
4. Check `tech/` for existing library/framework notes before using any technology

**Session end ritual:**
1. Update `todos.md` — what's done, what remains
2. Add to `lessons.md` if you hit any gotchas
3. Update `SUMMARY.md` if the project state changed significantly
4. Create or update `tech/` entries for any technology you researched this session

---

## Multi-Agent Coordination

Multiple AI agents may share this workspace.

1. **Session start:** check `/workspace/.devcage/context` for another agent's notes, then `git status` + `git stash list` — check for uncommitted work
2. **Before starting servers:** `lsof -i :3000-9999 2>/dev/null` — check for running processes
3. **Leave workspace clean:** no temp files, no running processes, no uncommitted changes, no debug logs
4. **Handoffs:** use `/workspace/.devcage/context/todos.md` to document where you stopped and what's next
5. **When to stop and ask the user:** requirements are ambiguous, architecture choices arise, scope expands beyond the request, or something is in an unexpected state

---

## Reference

Runtimes: Node.js, Python 3, Java/JDK, Maven, Gradle, Go, Rust, PHP + Composer, .NET SDK + NuGet (C#, F#, VB). Corepack enables `yarn` and `pnpm`. Versions are latest at build unless pinned. Some may be disabled — verify with `which`.

**JVM tools with lazy-install wrappers** (auto-installed on first use, cached across restarts):
`sbt`, `groovy`, `groovysh`, `grape`, `kotlin`, `kotlinc` — just run the command; SDKMAN and the tool are installed automatically if not already present.

**More JVM languages via SDKMAN** (cached across restarts):
```bash
sdk install scala     # Scala 3 (Dotty) compiler + runtime
```
To persist across rebuilds, add to `/workspace/.devcage/config/init.sh`:
```bash
source "$SDKMAN_DIR/bin/sdkman-init.sh"
sdk install kotlin 2.1.20
sdk install groovy 4.0.27
sdk install scala 3.6.4
```
Or use `.sdkmanrc` in the project root (auto-detected at startup):
```
kotlin=2.1.20
groovy=4.0.27
scala=3.6.4
```

**Pre-installed:** git, docker, curl/wget, gcc/g++/make, cmake, ninja, ccache, gdb, valgrind, cppcheck, clang-format, clang-tidy, jq/yq, ripgrep, tree, shellcheck, shfmt, httpie, tmux, playwright, semgrep, trivy, wrk, **audit**, **audit-sandbox**. shellharden is available when Rust is included (default; see --lang flag). hadolint is auto-installed on first `audit` run if Dockerfiles are found.

**Lazy-install (auto-installed on first use):** just, delta, mkcert, direnv, websocat, mailpit, gh, lighthouse, biome, typescript (tsc), tsx, serve, dotenvx, nodemon, concurrently, pre-commit, ruff, pytest, mypy, ipython, bashate, dlv, air. These tools are installed automatically when you first run them — expect a short delay on first use. Subsequent runs within the same session use the installed binary directly. Version pins from `config/versions.conf` are respected at install time.

**Installing without root:** `brew install <tool>` (first run: 30-60s tap) | `PIP_REQUIRE_HASHES=0 pip install --user <pkg>` | `npm install -g <pkg>` | `go install <pkg>@latest` | `cargo install <crate>` | `sdk install <candidate>`. All ephemeral — add to `.devcage/config/init.sh` for persistence. SDKMAN installations are cached in a named Docker volume and survive container restarts.

### Troubleshooting

| Symptom | Fix |
|---------|-----|
| `docker: command not found` | DinD not available — relaunch with `--embed-docker` |
| `apt-get: Permission denied` | `brew install`, `pip install --user`, or `npm install -g` |
| `pip install` hash error | `PIP_REQUIRE_HASHES=0 pip install --user <pkg>` |
| Tool disappeared after restart | Ephemeral — add to `/workspace/.devcage/config/init.sh` |
| First run of `ruff`/`biome`/etc. slow | Lazy-install tools download on first use — normal |
| `brew install` hangs 30-60s | First-run tap update — normal |
| Connection hangs (not instant error) | Not the LAN filter (those REJECT instantly) — check DNS |
| Java OOM / Gradle killed | `-Xmx512m`. Gradle daemon is disabled |
| Chromium crash | Out of memory — close pages, reduce concurrency |
| DinD out of disk | `docker system prune -f` |
| Port in use | `lsof -i :<port>` then `kill <pid>` |
| `rm -rf node_modules`: Device or resource busy | Dir cache overlay — handled automatically by rm wrapper; use `devcage-dircache clean` to reset |

---

## Third-Party Software

This sandbox contains third-party open-source tools installed from their official
distribution channels (Ubuntu apt, npm, pip, GitHub releases, Homebrew). Each
tool retains its original license.

**AI CLI tools** (Claude Code, Gemini CLI, Codex CLI, Aider, GitHub Copilot CLI,
Goose) **are third-party software**, not part of DevCage. They are downloaded
on first use and are subject to their own licenses and terms of service. Use
requires your own API key and acceptance of the respective provider's terms.
DevCage is not affiliated with, endorsed by, or sponsored by any AI tool provider.
