Files
paperclip-adapter-claude-k8s/CLAUDE.md
T
2026-04-16 07:56:25 -04:00

60 lines
3.9 KiB
Markdown

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
This is a Paperclip adapter plugin that runs Claude Code agents as isolated Kubernetes Jobs instead of inside the main Paperclip process. It uses the `@kubernetes/client-node` library to interact with the K8s API.
## CI/CD
Build and publish are handled by GitHub Actions on tag push — do **not** build locally. To release a new version, bump `package.json` with `npm version` and push the tag — CI handles the rest.
## Common Commands
```bash
npm run typecheck # Type-check without emitting (local dev only)
npm test # Run tests (vitest run)
npm run test:watch # Run tests in watch mode
npm run coverage # Run tests with coverage
```
Do not run `npm run build` locally — it's run by the CI pipeline. To release: bump version (`npm version`), push, and CI publishes automatically.
Single test file: `npx vitest run src/server/execute.test.ts`
## Architecture
### Entry Point
`src/index.ts` exports `createServerAdapter()` which returns a `ServerAdapterModule` with all adapter capabilities. It re-exports types, models, and the execute function.
### Server Module (`src/server/`)
- **`execute.ts`** — Core execution flow: checks for concurrent runs, creates a K8s Job, waits for pod scheduling, streams logs, waits for job completion, parses Claude's stream-json output, and returns the result. Also handles cleanup and retention.
- **`job-manifest.ts`** — Builds the K8s Job manifest. Key design: an init container (busybox) writes the prompt to an emptyDir volume, then the main `claude` container reads it via stdin. The shared PVC is mounted at `/paperclip` with `HOME=/paperclip` to enable session resume.
- **`k8s-client.ts`** — Wrapper around `@kubernetes/client-node`. Caches the KubeConfig and self-pod introspection (`getSelfPodInfo`) which discovers the container image, imagePullSecrets, DNS config, PVC claim name, and env vars to forward to Job pods.
- **`config-schema.ts`** — Returns the UI config schema (typed as `ConfigFieldSchema[]`) that Paperclip's web UI renders as a form.
- **`parse.ts`** — Parses Claude's `stream-json` output format to extract session IDs, token usage, cost, and summaries.
- **`session.ts`** — Session codec for session resume.
- **`skills.ts`** / **`models.ts`** — Implement `listSkills`/`syncSkills` and `listModels` for the `ServerAdapterModule` interface.
### CLI Module (`src/cli/`)
- **`format-event.ts`** — Formats Claude stream events for terminal output.
### UI Parser (`src/ui-parser.ts`)
- Parses adapter-specific UI configuration fields.
### Config Schema Note
The types in `config-schema.ts` (`ConfigFieldSchema`) must match what Paperclip's `SchemaConfigFields` component expects, since Paperclip's server calls `adapter.getConfigSchema()` and the UI reads the JSON at runtime.
## Key Design Decisions
1. **Pod introspection** — On first `execute()` call, `getSelfPodInfo()` reads the running pod's spec via K8s API and caches it. Every subsequent Job inherits the Deployment's image, secrets, DNS, and PVC without additional config.
2. **Concurrency guard** — Before creating a Job, `execute.ts` lists existing Jobs labeled with the agent ID and blocks if any are still running (prevents session conflicts on the shared PVC).
3. **Prompt delivery** — The prompt is written by a busybox init container to an `emptyDir` volume, then read by the main `claude` container via `stdin`. This avoids escaping issues with env vars containing complex characters.
4. **Log streaming** — Uses `k8s.Log` follow mode with automatic reconnection. If the follow stream ends before the job completes (API disconnect), a one-shot log read is used as fallback.
5. **Session resume** — Works via the shared `/paperclip` PVC mounted as `HOME`. The `runtimeSessionId` is passed via `--resume` to the Claude CLI.