Set workingDir in the claude-code adapter config so agents have access to your actual codebase. Covers permissions, .gitignore, and safety boundaries.
Configure the claude-code adapter properly so agents can read and write files in your project, understand what the agent has access to, and set safety limits so it doesn't do unexpected things.
workingDir is the root directory the agent operates inside. When the agent runs:
Read("src/routes/users.ts") → reads /your/project/src/routes/users.tsWrite("src/routes/users.ts", ...) → writes to /your/project/src/routes/users.tsBash("npm test") → runs in /your/project/The agent cannot escape workingDir. Paths like ../../etc/passwd are blocked by Claude Code's own sandboxing.
The claude-code adapter reads its config from two places: the .env file (for secrets and paths) and the adapter config object in source (for behaviour tuning).
// apps/server/src/adapters/claude-code/index.ts (simplified)
import { claudeCodeAdapterConfig } from './config';
export const claudeCodeAdapter: Adapter = {
async invoke(task: AdapterTask): Promise<AdapterResult> {
const { workingDir, timeoutMs } = claudeCodeAdapterConfig;
const result = await runClaudeCode({
prompt: buildPrompt(task), // combines issue title + description + context
workingDir,
timeoutMs,
env: {
ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY,
},
});
return {
output: result.summary,
changedFiles: result.changedFiles,
cost: result.cost,
};
},
};
The agent only knows what's in the prompt plus what it reads from files. You can improve results significantly by adding a CLAUDE.md file to your project root — Claude Code reads it automatically at the start of every session:
<!-- ~/projects/my-api/CLAUDE.md -->
# Project Context for Paperclip Agents
## Stack
- Node.js 20 + TypeScript
- Express 4 for routing
- Drizzle ORM + PostgreSQL
- Vitest for tests
## Key directories
- `src/routes/` — all Express route handlers
- `src/db/schema.ts` — Drizzle schema (source of truth for all tables)
- `src/db/queries/` — reusable query functions
- `tests/` — Vitest test files
## Conventions
- All route files export a single Express Router
- Every new endpoint needs a test in `tests/<route>.test.ts`
- Use `db.query.<table>.findMany(...)` not raw SQL
- TypeScript strict mode is on — no `any`
## Running tests
npm test # all tests
npm test -- --watch # watch mode
A good
CLAUDE.mdis the most effective way to improve agent output quality. Think of it as onboarding documentation for your AI team members.
You can configure the adapter to limit agent permissions:
// config.ts
export const claudeCodeAdapterConfig = {
workingDir: process.env.AGENT_WORKING_DIR ?? '',
timeoutMs: 300_000,
// Prevent the agent from running shell commands (file read/write only)
disableBash: process.env.AGENT_DISABLE_BASH === 'true',
// Paths the agent must NOT modify (relative to workingDir)
readOnlyPaths: [
'.env',
'.env.production',
'secrets/',
'certs/',
],
// File extensions the agent can write to (undefined = all)
writeableExtensions: ['.ts', '.tsx', '.js', '.json', '.md', '.css'],
};
Add to .env:
# For read-only exploratory agents:
AGENT_DISABLE_BASH=true
If you want different agents working on different projects, configure per-agent workingDir by storing it on the agent record itself:
-- Add workingDir to agent config (stored in the `config` JSONB column)
UPDATE agents
SET config = jsonb_set(
COALESCE(config, '{}'),
'{workingDir}',
'"/Users/you/projects/my-api"'
)
WHERE slug = 'backend-dev-agent';
Then in the adapter, read from the agent config first, falling back to the global env:
const workingDir =
task.agent.config?.workingDir ??
process.env.AGENT_WORKING_DIR ??
'';
This lets you hire a "frontend agent" pointing at your React app and a "backend agent" pointing at your API — both running in the same Paperclip instance.
workingDir control, and can the agent escape it?