Guidelines for AI agents working on this codebase.
This is a Clojure port of the GitHub Copilot SDK. The upstream repository is github/copilot-sdk.
We do NOT blindly copy the upstream implementation. Instead, we create an idiomatic Clojure library that:
- Leverages Clojure language features and idioms (immutability, functional programming, state-mangement and concurrency features)
- Would be natural to integrate in Clojure projects
- Would make sense to expert Clojure programmers
- Uses Clojure libraries appropriately, particularly:
- core.async for asynchronous operations
- clojure.spec for data validation and documentation
- other high-quality libraries as needed.
When porting features or investigating behavior:
- Primary reference: nodejs implementation (JavaScript/TypeScript)
- Secondary reference: python implementation for additional clarity
- Local upstream checkout: The upstream repo is available at
../copilot-sdk(relative to this repo). - CLI runtime: The CLI itself is useful for understanding protocol behavior, but the SDK source of truth is always the Node.js SDK, not the CLI protocol types.
This SDK must maintain strict API parity with the official Node.js SDK (@github/copilot-sdk).
-
Only expose what the official SDK exposes. The CLI protocol often defines more options than the SDK surfaces. Do NOT add config options or methods just because the CLI accepts them — only add them when the Node.js SDK's
SessionConfig,CopilotClient, etc. include them. -
When adding features, always verify against:
copilot-sdk/nodejs/src/types.ts— canonical type definitions (SessionConfig,ResumeSessionConfig,MessageOptions,CopilotClientOptions)copilot-sdk/nodejs/src/client.ts—CopilotClientmethods and what params are sent on the wirecopilot-sdk/nodejs/src/session.ts—CopilotSessionmethods
-
Experimental/CLI-only features may be kept if clearly marked as experimental in docstrings and docs, with a note that they are not part of the official SDK API. Example:
:large-outputis accepted by the CLI protocol but not exposed in the Node.js SDK. -
Clojure-only additions (convenience macros, core.async wrappers, internal tuning knobs) are fine as long as they don't conflict with the official API surface.
To check for upstream changes that may need porting:
- Review merged PRs: https://github.com/github/copilot-sdk/pulls?q=is%3Apr+is%3Aclosed
- Compare with recent commits in this repository
- For each upstream change, assess:
- Should it be ported? (code changes yes, docs/CI/language-specific changes usually no)
- If yes: Create a plan adapting it to Clojure idioms
- If no: Document why (e.g., "Python-specific", "CI tooling only")
# Unit tests only
bb test
# Full test suite including E2E tests (REQUIRED before committing)
COPILOT_E2E_TESTS=true bb testAll public API functions have clojure.spec fdefs defined in instrument.clj.
When github.copilot-sdk.instrument is required (which happens automatically during
integration tests), every public function call is validated against its spec at runtime.
This means integration tests run with full spec checking — any argument or return value that violates a spec will throw immediately. When adding new public functions:
- Add an
s/fdefinsrc/github/copilot_sdk/instrument.clj - Add the function to both
instrument-all!andunstrument-all!lists - Ensure the corresponding specs exist in
src/github/copilot_sdk/specs.clj - Run
bb test— if specs are wrong, instrumented tests will catch it
Examples are part of the test suite but run separately:
# Full testing includes all examples working (REQUIRED before committing)
./run-all-examples.shThis runs all Clojure examples.
In addition, all snippets and API descriptions in documentation *.md files should be checked for validity.
# Build JAR
clj -T:build jar
# Install to local Maven repo
clj -T:build installThis project uses 4-segment versioning: UPSTREAM.CLJ_PATCH (e.g., 0.1.22.0).
First 3 segments track the upstream copilot-sdk release, 4th is Clojure-specific.
# Sync to new upstream release (updates build.clj, README.md)
clj -T:build sync-version :upstream '"0.1.23"'
# Bump Clojure patch: 0.1.22.0 -> 0.1.22.1
clj -T:build bump-version- Run full CI:
bb ci:full(requires copilot CLI + auth)- This runs: E2E tests, examples, doc validation, and jar build
- If copilot CLI is not available, run
bb ci(unit/integration tests, doc validation, jar) - Run documentation validation:
bb validate-docs - Always ask for my review before committing - do not commit autonomously
- Do NOT deploy without explicit permission - the maintainer will deploy
- You may bump version numbers when needed (
clj -T:build bump-version)
This project emphasizes rigor and correctness, particularly for:
- Async code (core.async channels, go blocks)
- Protocol/wire code (JSON-RPC communication with CLI server)
- Sound process and resource management robust error handling and cleanup to avoid leaking resources
- Use
clojure.specfor data validation at API boundaries - Runtime validation with helpful error messages
- Function specs (
s/fdef) for public APIs ininstrument.clj
- Unit tests for pure functions
- Integration tests using mock server
- E2E tests against real Copilot CLI
- All examples serve as additional integration tests
src/github/copilot_sdk/
├── client.clj # Main client API (create-client, create-session, etc.)
├── session.clj # Session operations (send!, send-and-wait!, etc.)
├── helpers.clj # Convenience functions (query, query-seq!, query-chan, etc.)
├── specs.clj # clojure.spec definitions
├── instrument.clj # Function specs and instrumentation
└── util.clj # Internal utilities
All these must be updated as appropriate when making changes:
README.md- User-facing documentation and quick startdoc/index.md- Documentation hub / table of contentsdoc/reference/API.md- Detailed API reference - read this to understand the current API designdoc/getting-started.md- Step-by-step tutorial for new usersdoc/style.md- Documentation authoring style guidedoc/auth/index.md- Authentication guide (all methods, priority order)doc/auth/byok.md- BYOK (Bring Your Own Key) provider guidedoc/mcp/overview.md- MCP server configuration guidedoc/mcp/debugging.md- MCP debugging and troubleshootingCHANGELOG.md- Version history and changes (see below)AGENTS.md- update this file when significant changes happen (e.g. Project Structure)
Run bb validate-docs to check for broken links, unparseable code blocks, and structural issues.
Use /update-docs skill (.github/skills/update-docs/SKILL.md) to regenerate docs after source changes.
CHANGELOG.md follows Keep a Changelog conventions. When making changes:
- Always update the
[Unreleased]section — add entries underAdded,Changed,Fixed, orRemovedas appropriate. - Group related entries — use sub-headings like
### Added (CI/CD)when a batch of changes belongs to a theme. - Upstream sync annotations — when porting changes from an upstream copilot-sdk release, annotate
the sub-heading with the upstream version:
### Added (v0.1.24 sync). This groups ported changes by their upstream origin and makes it clear which upstream release they correspond to. Individual entries should also cite specific upstream PRs (e.g., "upstream PR #376"). Changes that are Clojure-specific (not ported from upstream) use other theme annotations like(CI/CD),(documentation), or no annotation. - Mark breaking changes with
**BREAKING**:prefix. - On release, the maintainer moves
[Unreleased]entries to a versioned section and updates comparison links at the bottom. The Clojure SDK version (UPSTREAM.CLJ_PATCH, e.g.,0.1.24.0) encodes which upstream release is included, so the sync annotations in the changelog and the release version together show upstream parity.