How Paperclip Execution Workspaces Manage Project Directories, Git Worktrees, and Runtime Services
Paperclip execution workspaces isolate every agent run inside a dedicated, transient directory using Git worktrees to create cheap, reproducible snapshots of project directories, while launching coordinated runtime services—including a Vite HTML renderer, agent container, and task watchdog—within the same process group.
Paperclip execution workspaces provide the foundational isolation layer that enables safe, concurrent AI agent runs against precise repository states. According to the paperclipai/paperclip source code, each workspace is initialized as a Git worktree pointing to a specific commit, ensuring that parallel agent executions never interfere with each other or the main repository checkout.
Git Worktrees and Project Directory Isolation
Every Paperclip execution workspace begins as a unique directory under the configured WORKSPACES_ROOT, defined in server/src/worktree-config.ts. When an agent request arrives, the server performs three atomic steps to establish the project directory view:
- Creates a unique workspace folder using a generated ID that includes timestamps and random suffixes for collision resistance.
- Initializes a Git worktree pointing at the company's project repository URL (stored in the company-scoped
projectstable). - Checks out the exact commit referenced in the run payload, or defaults to the latest
origin/mainif no commit is specified.
The Git worktree mechanism is central to Paperclip's isolation strategy. Because worktrees share the same underlying Git object store while maintaining independent working directories, Paperclip can spin up dozens of workspaces for the same repository with minimal disk overhead. Only the checked-out files consume space—not the entire Git history.
import { execSync } from 'child_process';
import { join } from 'path';
import { WORKSPACES_ROOT, REPO_PATH } from './worktree-config';
// 1️⃣ Generate a unique workspace folder
const workspaceId = `ws-${Date.now()}-${Math.random().toString(36).slice(2)}`;
const workspacePath = join(WORKSPACES_ROOT, workspaceId);
execSync(`mkdir -p ${workspacePath}`);
// 2️⃣ Add a git worktree pointing at the desired commit
const commitSha = payload.commitSha ?? 'origin/main';
execSync(
`git -C ${REPO_PATH} worktree add --detach ${workspacePath} ${commitSha}`
);
Runtime Services Architecture
Once the file tree is ready, Paperclip spins up four distinct runtime services that operate inside the workspace boundary. All services run within the same OS process group but remain logically separated through environment variable scoping and port isolation.
Vite HTML Renderer
The Vite HTML Renderer (server/src/vite-html-renderer.ts) serves the web UI for each run, providing file browsers and live log streaming. It starts a dedicated Vite development server per workspace, binding to an available system port and serving static assets from ui/public/ alongside the compiled UI bundle.
import { createServer } from 'vite';
import { workspacePath } from './workspace-manager';
async function startRenderer() {
const server = await createServer({
root: workspacePath,
server: { port: 0 }, // pick a free port
// ...other Vite options
});
await server.listen();
return server;
}
Agent Runtime Container
The Agent Runtime Container executes the actual AI agent code (Claude, Claude-3, and other adapters). Implementation details reside in packages/adapter-utils/, while the container itself launches via the internal Docker runner specified in doc/spec/agents-runtime.md. The agent runs as a child process with environment variables including WORKSPACE_PATH and PROJECT_ID, communicating with the server through a local WebSocket RPC channel for real-time log streaming.
import { spawn } from 'child_process';
import { workspacePath } from './workspace-manager';
function runAgent(agentName: string, args: string[]) {
const env = { ...process.env, WORKSPACE_PATH: workspacePath };
const child = spawn('node', [`./agents/${agentName}.js`, ...args], { env });
child.stdout.on('data', (data) => {
// forward logs to the UI via WebSocket
broadcastLog(data.toString());
});
child.on('close', (code) => {
// cleanup after the run
console.log(`Agent exited with code ${code}`);
});
}
Task Watchdog
The Task Watchdog (server/src/task-watchdog.ts) monitors run health, enforces budget caps, and writes structured activity logs as specified in doc/spec/agent-runs.md. It operates as a supervisory process that can terminate the agent container if resource limits are exceeded.
File-Browser Service
The File-Browser Service provides UI-driven read/write access to workspace files, anchored strictly to the worktree root. UI components for this service are defined in ui/storybook/stories/workspace-file-browser.stories.tsx, ensuring users can navigate the isolated project directory without escaping the workspace boundary.
Workspace Lifecycle and Cleanup
When an agent run completes, Paperclip executes a deterministic teardown sequence:
- Collects logs and artifacts from the workspace directory, including stdout captures, file outputs, and generated screenshots.
- Archives the workspace optionally compressing it for later inspection or rerun debugging.
- Deletes the Git worktree using
git worktree removefollowed bygit worktree pruneto reclaim disk space while keeping the shared object store intact.
This lifecycle ensures that transient workspaces never accumulate indefinitely, even when runs fail or hang.
Concurrent Execution and Reproducibility
Because each run receives its own Git worktree, Paperclip can execute multiple agents against different commits of the same repository simultaneously. The shared Git object store means the overhead remains minimal—each workspace only stores the checked-out tree snapshot, not the full .git history.
The exact commit SHA is recorded in run metadata, enabling bit-for-bit reproducibility when retrying failed jobs. When a user reruns a specific job, Paperclip recreates the worktree at the identical commit, guaranteeing the agent operates on the same file states as the original execution.
Summary
- Paperclip execution workspaces are transient directories created under
WORKSPACES_ROOTfor every agent run. - Git worktrees provide isolated, cheap snapshots of project directories without duplicating repository history.
- Four runtime services operate inside each workspace: the Vite HTML Renderer (
vite-html-renderer.ts), Agent Runtime Container (adapter-utils/), Task Watchdog (task-watchdog.ts), and File-Browser Service. - Process isolation uses environment variables like
WORKSPACE_PATHand WebSocket RPC channels to separate agent logic from UI services while maintaining real-time communication. - Automatic cleanup archives artifacts and prunes worktrees after run completion, preventing disk exhaustion during high-concurrency scenarios.
Frequently Asked Questions
How does Paperclip isolate project directories for concurrent agent runs?
Paperclip creates a unique Git worktree for every agent run, configured in server/src/worktree-config.ts. Each worktree points to the shared Git object store but maintains an independent working directory, allowing dozens of runs to execute against different commits of the same repository without file conflicts.
What runtime services execute inside a Paperclip workspace?
Each workspace runs four services: the Vite HTML Renderer for UI serving (server/src/vite-html-renderer.ts), the Agent Runtime Container for AI code execution (packages/adapter-utils/), the Task Watchdog for resource monitoring (server/src/task-watchdog.ts), and the File-Browser Service for workspace file navigation.
How does Paperclip handle Git repository state management?
When initializing a workspace, Paperclip executes git worktree add --detach to create a detached HEAD at the specific commit SHA provided in the run payload. This ensures the workspace reflects an exact, immutable snapshot of the repository state, with the commit hash recorded in run metadata for reproducibility.
What happens to workspace data after an agent run completes?
Paperclip collects logs and artifacts, optionally archives the workspace directory for debugging, then removes the Git worktree using git worktree remove and prunes the shared repository. This teardown occurs regardless of exit status, ensuring transient workspaces do not consume disk space indefinitely.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →