# Ardoise

> Spawns an isolated Claude with no CLAUDE.md, no skills, no hooks, no plugin context — only training weights and built-in skills. INVOKE BEFORE running evals, design research, cold critique, baseline comparisons, or testing plugin installs as a fresh user would experience them. Triggers on 'blank slate claude', 'fresh claude', 'isolated claude', 'naive claude', 'test plugin install', 'out of box claude', 'ardoise'. (user)

- Skill: `spm1001/ardoise` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add spm1001/ardoise`
- Raw SKILL.md: https://api.skillmd.com/api/skills/spm1001/ardoise/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Research & Search
- Author: spm1001 (https://skillmd.com/u/spm1001)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/spm1001/ardoise

---


# Ardoise

Run Claude on a blank slate. The spawned Claude sees only its training weights and built-in skills — no CLAUDE.md, no custom skills, no hooks, no plugins, no project context. Like a restaurant's ardoise wiped clean.

Two modes:
- **Interactive** (default) — opens Claude's TUI as a fresh user would see it. For manual testing: plugin installs, onboarding flows, "what does a new user experience?"
- **Print** (`-p`) — runs `claude -p` for automated/scripted use. For surveys, evals, cold critique.

## When to Use

- **Plugin testing** — does `claude plugin install` work for someone with a default `~/.claude`?
- **Design research** — what verbs, patterns, or names would a Claude naturally produce?
- **Skill evaluation** — does a naive Claude understand a SKILL.md on first read?
- **Eval baselines** — "without skill" control group for A/B testing
- **Isolation testing** — verify a prompt works without your ecosystem's context
- **Cold critique** — get feedback uncoloured by your conventions

## When NOT to Use

- **Security sandboxing** — this is context isolation, not filesystem/process isolation. The spawned Claude can still read host files if it knows the paths. Use containers for security.
- **Testing your skills work** — you want context loaded for that, not stripped

## How It Works

Three mechanisms, all cross-platform (POSIX):

| Mechanism | What it blocks |
|-----------|---------------|
| `env -i` | All inherited env vars including `CLAUDECODE=1` (nesting detection) — except Vertex auth (project/region/ADC) when `CLAUDE_CODE_USE_VERTEX=1` |
| `HOME=<tmpdir>` with stripped `claude.json` + credentials only | CLAUDE.md, settings.json, hooks, skills, plugins, MCP config |
| `cd /tmp` (or chosen dir) | Project CLAUDE.md, git repo context, local `.claude/` directories |

Additional env vars suppress noise:

| Var | Effect |
|-----|--------|
| `CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY=1` | No survey popups |
| `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1` | No telemetry |
| `CLAUDE_CODE_DISABLE_AUTO_MEMORY=1` | No auto memory files |
| `ENABLE_CLAUDEAI_MCP_SERVERS=false` | No built-in Gmail/Calendar MCP |

The `claude.json` is copied from the real one (preserving onboarding state and feature flags) but stripped of project data, skill usage, and marketplace auto-install.

## Usage

The script lives in the trousse plugin. Resolve the path:

```bash
SCRIPT="${CLAUDE_PLUGIN_ROOT}/scripts/ardoise.sh"
# Fallback if CLAUDE_PLUGIN_ROOT isn't set in the calling context:
[ -x "$SCRIPT" ] || SCRIPT=$(find ~/.claude/plugins/cache -path "*/trousse/*/scripts/ardoise.sh" 2>/dev/null | sort -rV | head -1)
```

The fallback uses `sort -rV | head -1` to prefer the highest-versioned cached copy when multiple are present. The `-V` (version sort) matters: plain `sort -r` is lexicographic and resolves `1.8.7` above `1.66.0`, handing you a script months behind the skill instructions invoking it.

### Interactive mode (default)

```bash
"$SCRIPT"                    # TUI in /tmp
"$SCRIPT" ~/some/project     # TUI in a specific directory
```

Opens Claude's interactive TUI. You type commands yourself — `claude plugin install`, `/doctor`, whatever you want to test manually.

### Print mode

```bash
"$SCRIPT" -p "What is the best way to structure a CLI?"
"$SCRIPT" -p --max-turns 1 "Reply with only: hello"
echo "Design a work tracker" | "$SCRIPT" -p --stdin --max-turns 1
"$SCRIPT" -p --cwd ~/some/project "What does the README promise?"
```

Print mode runs in `/tmp` by default; `--cwd DIR` runs the subject in a chosen directory instead (the seeder pre-trusts it, so no trust dialog blocks the run). Use it whenever the probe must see a real repo, or when `/tmp`'s shared clutter could contaminate the subject's view.

### Persistent HOME (multi-step tests)

Default runs use a fresh temp HOME, deleted on exit. For a sequence that must share state across invocations — `plugin marketplace add` → `plugin install` → `-p` verify — use a named HOME:

```bash
"$SCRIPT" --home ~/ardoise-sbx ~/some/project         # seeded once, reused thereafter
"$SCRIPT" --home ~/ardoise-sbx -p "verify it loaded"   # same HOME, accumulated state intact
```

`--home DIR` creates the dir if missing, seeds it once (auth + stripped config), and **never auto-deletes** it — so plugins/marketplaces added in one invocation survive to the next. `--keep` is the throwaway-but-inspect variant: a temp HOME that skips the cleanup trap and prints its path to stderr.

### Named holes in the wall (eval harnesses)

`env -i` rebuilds the inner environment from scratch, so a fixture shim and its env contract need explicit pass-through — the Vertex passthrough pattern, generalised:

```bash
"$SCRIPT" -p --env "MY_FIXTURE=/path/world.json" --env "MY_LOG=$RUN_DIR/calls.log" \
    --path-prepend /path/to/shim-bin -- "prompt"
```

`--env KEY=VAL` (repeatable) passes one variable through the wall. `--path-prepend DIR` (repeatable) puts a directory first on the inner PATH, so a shim binary shadows nothing the caller leaks — the inner PATH stays minimal otherwise. Print mode terminates claude's option parsing with `--` before the prompt, so variadic flags (`--allowed-tools`, `--tools`) cannot swallow it. The boundary holds as ever: these punch *context* holes; the wall is not a security boundary, and an inner model can still read the host filesystem — one eval run demonstrably did (2026-08-05).

### Vertex setups

If the caller's environment has `CLAUDE_CODE_USE_VERTEX=1`, ardoise auto-detects it and passes the Vertex config (project, region, model ids) and gcloud ADC through the isolation wall — so it works on, and bills to, a Vertex setup. Without this the `env -i` scrub strips the Vertex config and either hard-fails (Vertex-only boxes have no `.credentials.json`) or silently falls back to Anthropic-API billing (dual-cred boxes). No flag needed.

### From Claude Code (OuterClaude calling InnerClaude)

```bash
# In a Bash tool call:
"$SCRIPT" -p --max-turns 1 "Your prompt here"
```

The `env -i` scrub removes `CLAUDECODE=1`, so the inner Claude doesn't know it's nested. No launch resistance.

## What the Ardoise Claude Sees

| Layer | Visible? |
|-------|----------|
| Global CLAUDE.md | No |
| Project CLAUDE.md | No |
| Custom skills (plugin cache) | No |
| Built-in skills (simplify, loop, claude-api) | Yes — compiled into Claude Code |
| Hooks | No |
| MCP servers | No |
| Plugins | No |
| Host filesystem | Yes — context isolation, not security sandboxing |

## Key Discovery: The ~/.claude.json Symlink

Claude Code reads config from `$HOME/.claude.json` (a symlink in HOME root), not directly from `$HOME/.claude/claude.json`. Without this symlink in the temp HOME, Claude treats every launch as brand new and shows the onboarding wizard. The script creates this symlink automatically.

## Composing with Other Skills

| Skill | How they compose |
|-------|-----------------|
| **skill-forge** | Eval baselines — run prompts without the skill for A/B comparison |

## Anti-Patterns

| Anti-Pattern | Problem | Fix |
|-------|-----------|-----|
| Use Agent/Task tool for "naive" testing | Subagents inherit full parent context | Use this script via Bash tool |
| Pass `--system-prompt` and assume isolation | CLAUDE.md still loads | Use ardoise.sh |
| Use `--allowed-tools ""` for tool-free mode | Model burns turns trying tools | Pass `--tools ""` |
| Mount the real HOME | Context leaks | Let the script handle HOME |
| Fresh sandbox per step of a multi-step test | Loses marketplace/install state between calls | Use `--home DIR` to persist one sandbox |
| Forget the `~/.claude.json` symlink | Onboarding wizard every time | Script handles this automatically |

