Skip to content

Commit 4248b90

Browse files
committed
docs(core): add package metadata
Committed the package-specific README and LICENSE files under packages/core as provided.
1 parent 48c8227 commit 4248b90

File tree

2 files changed

+237
-0
lines changed

2 files changed

+237
-0
lines changed

packages/core/LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2025 headless-coder-sdk Contributors
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

packages/core/README.md

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
# headless-coder-sdk
2+
> Unified SDK for headless AI coders (Codex, Claude, Gemini)
3+
4+
[![npm version](https://img.shields.io/npm/v/@headless-coder-sdk/core.svg)](https://www.npmjs.com/package/@headless-coder-sdk/core)
5+
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
6+
[![Build Status](https://github.com/OhadAssulin/headless-coder-sdk/actions/workflows/ci.yml/badge.svg)](https://github.com/OhadAssulin/headless-coder-sdk/actions)
7+
8+
---
9+
10+
**Headless Coder SDK** unifies multiple *headless AI-coder SDKs* - OpenAI Codex, Anthropic Claude Agent, and Google Gemini CLI - under one consistent interface.
11+
It standardizes threads, streaming, structured outputs, permissions, and sandboxing, allowing you to build AI coding tools or autonomous agents that switch backends with a single line of code.
12+
13+
---
14+
15+
## 🚀 Why use it?
16+
- Avoid vendor lock-in between AI-coder SDKs
17+
- Unified threads and streaming API
18+
- Structured output and sandbox enforcement
19+
- Works in Node, Electron, or CI pipelines
20+
- Extensible - add your own adapters easily
21+
22+
---
23+
24+
## 📦 Packages
25+
26+
- `@headless-coder-sdk/core` – Shared types and the `createCoder` factory
27+
- `@headless-coder-sdk/codex-adapter` – Wraps the OpenAI Codex SDK
28+
- `@headless-coder-sdk/claude-adapter` – Wraps Anthropic Claude Agent SDK
29+
- `@headless-coder-sdk/gemini-adapter` – Invokes the Gemini CLI (headless mode)
30+
- `@headless-coder-sdk/examples` – Example scripts demonstrating runtime wiring
31+
32+
---
33+
34+
## 🧭 Quickstart
35+
36+
```bash
37+
npm i @headless-coder-sdk/core @headless-coder-sdk/codex-adapter
38+
```
39+
40+
```ts
41+
import { registerAdapter, createCoder } from '@headless-coder-sdk/core';
42+
import { CODER_NAME as CODEX, createAdapter as createCodex } from '@headless-coder-sdk/codex-adapter';
43+
44+
registerAdapter(CODEX, createCodex);
45+
46+
const coder = createCoder(CODEX);
47+
const thread = await coder.startThread();
48+
const result = await thread.run('Write a hello world script');
49+
console.log(result.text);
50+
```
51+
52+
---
53+
54+
## ▶️ Basic Run (Codex)
55+
56+
```ts
57+
import { registerAdapter, createCoder } from '@headless-coder-sdk/core/factory';
58+
import { CODER_NAME as CODEX_CODER, createAdapter as createCodexAdapter } from '@headless-coder-sdk/codex-adapter';
59+
60+
registerAdapter(CODEX_CODER, createCodexAdapter);
61+
62+
const coder = createCoder(CODEX_CODER, { workingDirectory: process.cwd() });
63+
const thread = await coder.startThread();
64+
const result = await thread.run('Generate a test plan for the API gateway.');
65+
console.log(result.text);
66+
```
67+
68+
---
69+
70+
## 🌊 Streaming Example (Claude)
71+
72+
```ts
73+
import { registerAdapter, createCoder } from '@headless-coder-sdk/core/factory';
74+
import { CODER_NAME as CLAUDE_CODER, createAdapter as createClaudeAdapter } from '@headless-coder-sdk/claude-adapter';
75+
76+
registerAdapter(CLAUDE_CODER, createClaudeAdapter);
77+
78+
const claude = createCoder(CLAUDE_CODER, {
79+
workingDirectory: process.cwd(),
80+
permissionMode: 'bypassPermissions',
81+
});
82+
83+
const thread = await claude.startThread();
84+
for await (const event of thread.runStreamed('Plan end-to-end tests')) {
85+
if (event.type === 'message' && event.role === 'assistant') {
86+
process.stdout.write(event.delta ? event.text ?? '' : `\n${event.text}\n`);
87+
}
88+
}
89+
90+
const resumed = await claude.resumeThread(thread.id!);
91+
const followUp = await resumed.run('Summarise the agreed test plan.');
92+
console.log(followUp.text);
93+
```
94+
95+
---
96+
97+
## 🧩 Structured Output Example (Gemini)
98+
99+
```ts
100+
import { registerAdapter, createCoder } from '@headless-coder-sdk/core/factory';
101+
import { CODER_NAME as GEMINI_CODER, createAdapter as createGeminiAdapter } from '@headless-coder-sdk/gemini-adapter';
102+
103+
registerAdapter(GEMINI_CODER, createGeminiAdapter);
104+
105+
const gemini = createCoder(GEMINI_CODER, {
106+
workingDirectory: process.cwd(),
107+
includeDirectories: [process.cwd()],
108+
});
109+
110+
const thread = await gemini.startThread();
111+
const turn = await thread.run('Summarise the repo in JSON', {
112+
outputSchema: {
113+
type: 'object',
114+
properties: {
115+
summary: { type: 'string' },
116+
components: { type: 'array', items: { type: 'string' } },
117+
},
118+
required: ['summary', 'components'],
119+
},
120+
});
121+
122+
console.log(turn.json);
123+
```
124+
125+
> ⚠️ Gemini CLI resume support is pending upstream ([PR #10719](https://github.com/google-gemini/gemini-cli/pull/10719)).
126+
127+
---
128+
129+
## 🔁 Resume Example (Codex)
130+
131+
```ts
132+
import { registerAdapter, createCoder } from '@headless-coder-sdk/core/factory';
133+
import { CODER_NAME as CODEX_CODER, createAdapter as createCodexAdapter } from '@headless-coder-sdk/codex-adapter';
134+
135+
registerAdapter(CODEX_CODER, createCodexAdapter);
136+
137+
const codex = createCoder(CODEX_CODER, {
138+
workingDirectory: process.cwd(),
139+
sandboxMode: 'workspace-write',
140+
skipGitRepoCheck: true,
141+
});
142+
143+
const session = await codex.startThread({ model: 'gpt-5-codex' });
144+
await session.run('Draft a CLI plan.');
145+
146+
const resumed = await codex.resumeThread(session.id!);
147+
const followUp = await resumed.run('Continue with implementation details.');
148+
console.log(followUp.text);
149+
```
150+
151+
---
152+
153+
## 🔄 Multi-Provider Workflow
154+
155+
For a full multi-coder workflow (Codex + Claude + Gemini), see [examples/multi-provider.ts](packages/examples/src/multi-provider.ts).
156+
157+
---
158+
159+
## ⚙️ Development
160+
161+
**Install**
162+
```bash
163+
pnpm install
164+
```
165+
166+
**Build**
167+
```bash
168+
pnpm build
169+
```
170+
171+
**Test**
172+
```bash
173+
pnpm test
174+
```
175+
176+
**Run examples**
177+
```bash
178+
pnpm run examples
179+
```
180+
181+
---
182+
183+
## ⏹️ Handling Interrupts
184+
185+
All adapters support cooperative cancellation via `RunOpts.signal` or thread-level interrupts:
186+
187+
```ts
188+
import { AbortController } from 'node-abort-controller';
189+
190+
const coder = createCoder(CODEX_CODER, { workingDirectory: process.cwd() });
191+
const controller = new AbortController();
192+
const thread = await coder.startThread();
193+
const runPromise = thread.run('Generate a summary of CONTRIBUTING.md', { signal: controller.signal });
194+
195+
setTimeout(() => controller.abort('User cancelled'), 2000);
196+
```
197+
198+
When aborted, streams emit a `cancelled` event and async runs throw an `AbortError` (`code: 'interrupted'`).
199+
200+
---
201+
202+
## 🧱 Build Your Own Adapter
203+
204+
Want to support another provider?
205+
Follow the [Create Your Own Adapter guide](docs/create-your-own-adapter.md) - it covers exports, registry usage, event mapping, and sandbox permissions.
206+
207+
---
208+
209+
## 💬 Feedback & Contributing
210+
211+
Contributions welcome!
212+
Open an [issue](https://github.com/OhadAssulin/headless-coder-sdk/issues) or submit a PR.
213+
214+
---
215+
216+
© 2025 Ohad Assulin - MIT License

0 commit comments

Comments
 (0)