Redline Growthredline
growth

Multi-client ops · field-tested

Clay Workspace Isolation

How we run one machine, one agent setup, and many clients' Clay workspaces without ever letting a command land in the wrong one. A short guide for humans, a copyable instruction block for agents, and a skill that deploys it into any harness.

The problem

Clay's agent tooling is a CLI (clay), and clay login stores one global session — a single Clay workspace at a time, shared by every project on the machine. If you serve multiple clients, each with their own Clay workspace, that global session is a loaded gun: switch clients without switching the login and every table read, workflow edit, and credit spend silently lands in the previous client's workspace. Nothing errors. It just quietly bleeds one client's account into another's.

Agents make this worse, not better — they'll happily run clay workflows list for Client B against Client A's session and report success.

The solution

The mechanism

The Clay CLI keeps its session under $XDG_CONFIG_HOME/clay. So we give each client its own config directory holding its own login session, and prefix every command with the matching environment variable. That's the entire trick — no wrapper scripts, no re-logins when switching clients, and multiple workspaces stay signed in concurrently.

Use the skillorHuman · once

mkdir -p ~/.clay-isolated/<client> then XDG_CONFIG_HOME=~/.clay-isolated/<client> clay login — and pick that client's workspace in the browser OAuth flow.

One directory per client. Or run the isolated-clay-instances skill (below): it does the terminal steps, pauses for you at the browser moment, then verifies and records the workspace id.

Agent · always

Prefix every clay call with XDG_CONFIG_HOME=~/.clay-isolated/<client>, where <client> comes from the folder being worked in.

The bare global session is never used for client work.

Agent · verify

Before the first Clay call in a session, run clay whoami under the client's config dir and check workspace.id against the client's recorded id.

Check the id, never a display name — names are ambiguous, ids aren't.

Two gotchas that cost us real debugging time

Do

One config dir per client · prefix every call · verify by workspace.id · API keys in the client's own .env, created while viewing that client's workspace.

Don't

Use the global session for client work · borrow a key across clients · trust a bare whoami to verify a key · configure Clay as an MCP server (removed in CLI 0.6.0+).

Agent instructions (copy this block)

Paste this into your agent's instruction file verbatim. It's harness-agnostic — plain markdown, no tool-specific syntax. Replace ~/.clay-isolated if you prefer a different location, and adapt the "client folder" convention to however your repo names clients.

## Clay — per-client workspace isolation (CLI only)

Clay is driven through the `clay` CLI. Do NOT configure a Clay MCP server —
`clay mcp` was removed (CLI 0.6.0+); an entry in MCP config can never start.

The default `clay login` session is ONE global credential: a single Clay
workspace at a time, shared machine-wide. NEVER use it for client work —
switching clients would silently switch workspaces and bleed one client's
Clay account into another's.

Each client has its own config dir holding its own login session:

1. One-time setup per client is done via the `isolated-clay-instances` skill
   (or by a human, since it ends in a browser OAuth flow):
     mkdir -p ~/.clay-isolated/<client>
     XDG_CONFIG_HOME=~/.clay-isolated/<client> clay login   # picking THAT client's workspace
   If the dir for the current client does not exist, STOP and ask the human
   to run the skill. Never fall back to the global session or another
   client's dir.

2. Prefix EVERY `clay` command run for a client with its config dir:
     XDG_CONFIG_HOME=~/.clay-isolated/<client> clay workflows list
   `<client>` is derived from the client folder currently being worked in.

3. Before the first Clay call of a session, confirm the pinned workspace:
     XDG_CONFIG_HOME=~/.clay-isolated/<client> clay whoami
   Check `workspace.id` against the client's recorded workspace id. Verify
   the id, never a display name. If it doesn't match, stop and report.

Rules:

- A LOGIN SESSION is required for workflow work (`clay workflows …`).
  API keys cannot drive it (auth_forbidden). When both a session and
  CLAY_API_KEY exist in one config context, the session wins.
- Any Clay API key a client needs (for scripts hitting Clay's REST API)
  lives in that client's own secrets file (client-root `.env`) — never in
  shared config, never borrowed across clients. It must be a Clay PUBLIC
  API key (UUID-shaped), created at Clay → Settings → Account → API keys
  while VIEWING that client's workspace; the key is scoped to whatever
  workspace was active at creation.
- To verify which workspace a key belongs to, do NOT run a bare
  `CLAY_API_KEY=<key> clay whoami` — a saved login session silently
  shadows the key and reports the session's workspace instead. Use an
  empty config dir so nothing can shadow it:
     XDG_CONFIG_HOME=$(mktemp -d) CLAY_API_KEY=<key> clay whoami
  Sanity-check first: the same command with an all-zeros key must fail
  with auth_invalid.
- The CLI contract moves between versions. Before trusting any `clay`
  line copied from a runbook, run `clay <command> --help`. An
  `upgrade_required` error on every command means update the CLI
  (`clay update`), not re-login.
- General credential isolation applies: if no Clay credential exists for
  the current client context, stop and ask rather than borrowing one.

Deploying into a harness

Primary path: use the skill. We packaged the whole setup as an agent skill, isolated-clay-instances — a folder containing a SKILL.md (the procedure) and references/agent-instructions.md (the canonical copy of the block above). Drop the folder into your repo's skills directory (.claude/skills/isolated-clay-instances/ for Claude Code; for other harnesses, point the agent at its SKILL.md as instructions — it's written to work either way), then tell the agent: "set up Clay for <client>". It runs the terminal steps, pauses for you at the browser OAuth step, verifies and records the workspace id, and installs the agent-instruction block into the right instruction file for your harness — idempotently, so re-running it just verifies.

Download the skill (.zip)

Contains isolated-clay-instances/SKILL.md + references/agent-instructions.md. Unzip into .claude/skills/.

One thing no instruction file — or skill — can fully do: the browser OAuth click-through in clay login. The skill runs the command and pauses for you at that moment; picking the right workspace in the picker is the one decision that stays human. Everything after — prefixing, verifying, refusing to fall back — is the agent's job.

I'll do it myself

Manual deployment

No skill support, or you'd rather wire it by hand: every mainstream coding-agent harness reads a plain-text instruction file from the repo. Drop the block above into whichever file your harness loads; the content is identical everywhere.

HarnessWhere the block goes
Claude CodeCLAUDE.md at the repo root — or, if clients live under one folder (e.g. clients/), a CLAUDE.md inside that folder so it loads exactly when client work is happening. ~/.claude/CLAUDE.md makes it machine-global.
CodexAGENTS.md at the repo root. Nested AGENTS.md files are also read, so a copy in the clients folder scopes it the same way.
CursorAGENTS.md at the repo root, or a rule file under .cursor/rules/ set to always apply.
Gemini CLIGEMINI.md at the repo root (or set contextFileName to reuse your existing AGENTS.md).
Anything elsePaste the block into the system prompt / custom instructions. It has no tool-specific syntax, so it survives any harness.

Manual setup checklist (what the skill does, once per client)

  • Create the dir and log in: mkdir -p ~/.clay-isolated/<client> && XDG_CONFIG_HOME=~/.clay-isolated/<client> clay login, choosing that client's workspace in the browser.
  • Record the workspace id: XDG_CONFIG_HOME=~/.clay-isolated/<client> clay whoami, and note workspace.id in the client's context docs so the agent has something to verify against.
  • If the client needs an API key for scripts: create a Clay Public API key while viewing that client's workspace, put it in the client's root .env (gitignored), and verify it with the empty-config-dir whoami shown above.

Why this design