📄 build-your-workspace-once.md29/04/2026
Documents › workspaces

Build Your Workspace Once. Then Don't Touch the Foundation Again.

WORKSPACE_ROOT, VAULT_ROOT, and OUTPUT_ROOT side by side
Three roots, three jobs

The trigger

I spent a day rebuilding the foundation under every project I run.

The orchestration layer behind everything I do, every product, every brand, every active client, sits in one root. Last week I moved that root.

The move cost roughly two million tokens of Opus output, sixty-seven logged migration steps, and a purpose-built migration toolset. Worth it.

Here's why I did it, what changed, and the structure I wish I'd started with.

Why I did it

The old setup grew. Three years of layered decisions, each defensible in the moment, ended up nested three folders deep with the same name repeated in each. Not a typo. Three of them.

The path was a symptom. The real problems were structural.

Code, content, and config were braided together. Every workspace held source files, render outputs, plan documents, briefs, screenshots, and configuration in one tree. Backing up orchestration meant backing up renders. Reading briefs required mounting the encrypted code drive.

Hardcoded paths were everywhere. Tools, hooks, plugins, and native apps all assumed one specific absolute path. One move would have shattered the system.

The configuration was Claude Code specific. Hooks, settings, slash commands all baked into one agent's surface. If I wanted to run the same workspace through Codex or Gemini, the layer of plumbing I'd need to build was its own project.

Session state and canonical config lived in the same directory. Ten gigabytes of accumulated runtime state in .claude/ made the workspace feel heavy. Most of it was regenerable. None of it was sorted.

What changed

The migration introduced three roots, each with one job.

Workspace root holds orchestration only. Markdown briefs, YAML manifests, plans, decisions, content drafts, memory bank. No source code. Plain text. Version-control friendly. Readable by anything that can read files.

Vault root, an encrypted disk image, holds source code and proprietary assets. Mounted on demand. Unmounted by default for safety. Each project has its own .git repo inside.

Output root, an external SSD, holds generated artifacts. Renders, builds, exports, archived datasets. Disposable, regenerable, large.

The link between them is a per-workspace manifest.yaml and a links/ folder of generated symlinks. Hardcoding drops to zero. Moving any of the three roots requires updating one environment variable.

What it changed about the work

Cold start on a project compresses. The manifest tells me what's there, where the code lives, where output goes, and the project state. No spelunking.

Backups simplify. The workspace root is small enough to snapshot daily without thought. The vault encrypts and rotates separately. Output is reproducible and doesn't need protection.

The biggest shift is conceptual. The orchestration layer is now portable across agents.

Briefs, manifests, memory, and protocols sit in plain markdown and YAML. Codex CLI sees the same workspace root that Claude Code sees. So would Gemini, or any agent that can read files. The Claude Code specific layer (hooks, slash commands, settings) lives in .claude/ as an optional add-on. Strip it out and the workspace still functions. Hand it to a different agent and it still works.

This is the property I care about. My system isn't tied to one model family or one tool's lifespan. The agent is a worker. The workspace is the contract.

What "we" means in this story

I made the architectural call. The agent did the heavy lift across one continuous Opus session. Building the migration toolset. Copying with integrity verification at every step. Rewriting paths across thousands of files. Generating manifests for each workspace. Regenerating links. Surfacing every decision with evidence before acting.

Sixty-seven steps logged. Zero destructive operations on the source. Old workspace untouched, new workspace built clean.

The collaboration is the point. I architect. The agent implements. The workspace structure makes both roles legible to each other and to whichever agent I bring in next.

The structure to copy

If you're starting a new workspace today, this is the foundation that would have saved me a day and a couple million tokens.

1. Three roots, three jobs

WORKSPACE_ROOT   orchestration (markdown, manifests, briefs, memory)
VAULT_ROOT       source code and proprietary assets (encrypted)
OUTPUT_ROOT      renders, builds, exports (external, disposable)

Export them in your shell profile so every shell sees them.

2. Per-workspace manifest

schema_version: 1
workspace: <name>
type: code | content | utility | hybrid
brand: <brand>
code_root: ${VAULT_ROOT}/<brand>
projects:
  - name: <project>
    code_path: <relative to code_root>
    repo_url: <github>
    output_paths:
      builds: ${VAULT_ROOT}/<...>
      renders: ${OUTPUT_ROOT}/<...>

The manifest is the contract. Tools read it to know where things live.

A small script reads each manifest and writes links/code, links/renders, links/repo.url inside the workspace. Symlinks for live filesystem objects. URL files for remote resources. Re-run the script after any move. Everything stays connected.

4. Env-var paths in code

Every script references os.environ['WORKSPACE_ROOT'] or your equivalent. Never hardcode. If a literal default is unavoidable for tool-importability, env var first, hardcoded fallback second.

5. Small canonical config, large regenerable runtime

Split your agent's local directory into two categories from the start.

Canonical config: settings, slash commands, custom skills. Source of truth. Migrate on move.

Runtime state: sessions, worktrees, breakouts, logs, tasks. Regenerable. Skip on move.

If you keep them entangled, every migration is ten times bigger.

6. Memory as a plain markdown index

Auto-memory in your agent's project memory directory with a one-line MEMORY.md index pointing at individual <topic>.md files. Stable slug per workspace. Index entries under 150 characters. Categorized by type: user, feedback, project, reference.

7. Agent-agnostic by construction

The Claude Code specific bits live behind one isolated entry point: .claude/. Everything outside is plain markdown, YAML, and code with env-var paths. A new agent walking into the workspace sees a readable system, not a Claude-shaped puzzle.

The takeaway

Build the workspace as if you'll change agents three times in the next two years. Because you will. Models change. CLIs change. The entire tooling layer churns.

The orchestration root, written in plain text with explicit env-var paths and per-workspace manifests, outlasts all of it.

Do this from day one. The migration tax compounds.

Per-workspace manifest template Symlink generator script

📌 Files attached