agent-director
v0.5.1
Published
TypeScript/Bun client for the agent-director CLI. Shares the Go API surface 1:1. The `Client` spawns the bundled `agent-director` CLI binary as a subprocess per verb call — no FFI, no network hop.
Readme
agent-director
TypeScript/Bun client for the agent-director CLI. Shares the Go API
surface 1:1. The Client spawns the bundled agent-director CLI
binary as a subprocess per verb call — no FFI, no network hop.
Install
bun add agent-directorRequires Bun >=1.0.21. The package ships the prebuilt CLI binary for
each supported platform via optional dependencies — they install
automatically on bun add. The Client resolves the host's binary
at construction time via import.meta.resolve('@agent-director/<host>/package.json')
and spawns it for every verb call.
On install, a postinstall script copies the install-agent-director skill body into ~/.claude/skills/install-agent-director/ so claude /install-agent-director is immediately discoverable in Claude Code. The postinstall only writes under ~/.claude/skills/; it does not touch PATH, ~/.agent-director/, or your Claude Code settings.
Bun blocks dependency postinstalls by default. Trust this package so the skill copy can run:
bun pm trust agent-directorOr pre-declare it in your package.json before bun add:
{
"trustedDependencies": ["agent-director"]
}Verbose install logs
Set AD_POSTINSTALL_VERBOSE=1 (also accepts true / yes, case-insensitive) before bun add to see what the postinstall resolved and decided. The default is quiet — five lines maximum.
Skipping the postinstall
bun add --ignore-scripts agent-director installs the library without running the postinstall. The skill is not copied. To get skill discoverability after the fact, either:
cp -r node_modules/agent-director/skills/install-agent-director ~/.claude/skills/or, once the library is on disk, invoke claude /install-agent-director from any Claude Code session — the install skill copies itself into ~/.claude/skills/ as a side effect of running.
How the postinstall decides whether to overwrite
The skill body carries a version: field in its YAML frontmatter. On every install the postinstall reads the bundled version and the version already on disk:
- Same version — no filesystem changes, no output.
- Older or missing on disk — overwrite, leaving a timestamped
install-agent-director.bak.<unix-ts>sibling under~/.claude/skills/. - Newer on disk — leave it alone, single-line warning to stderr.
The authoritative behavior contract lives in Idea Bee b.fg3.
Supported platforms
Supported — install + library + skill all work:
linux/x64(Linux on x86_64)darwin/arm64(Apple Silicon Mac)
Refused at install time by npm/bun — the umbrella's os/cpu fields fail resolution and no postinstall runs:
- Windows (any architecture)
- FreeBSD, OpenBSD, and other non-Linux/non-Darwin OSes
- any architecture not in
[x64, arm64](e.g.ia32,mips,arm)
Refused by the postinstall after npm/bun admits the install — the umbrella runs but the postinstall exits non-zero with an agent-director: unsupported host message before any filesystem write:
darwin/x64(Intel Mac)linux/arm64
The refusal is two-layered because npm/bun's os and cpu fields are a cross-product, not a per-pair set: the coarse gate cannot distinguish "supported pair" from "supported OS plus supported arch in any combination." The postinstall's host-pair check catches the two cross-product members that should not actually install.
See Idea Bee b.fg3 for cross-platform expansion status.
Quick start
using block (preferred):
using client = new Client({});
const v = await client.version({});
console.log(v.version);Explicit try/finally (portable fallback):
const client = new Client({});
try {
const v = await client.version({});
console.log(v.version);
} finally {
client.close();
}All constructor options are optional. Omitted fields fall back to the CLI binary's own three-tier default resolution (config.toml value, then hardcoded fallback such as ~/.agent-director/state.db) — the CLI is the single source of truth for defaults. Tilde expansion (~ → home directory) is handled automatically before paths are forwarded to the CLI subprocess. The using form calls client.close() automatically at block exit and requires Bun >=1.0.21 (or a TypeScript project with "lib": ["ESNext.Disposable"]).
ClientOptions overrides forward verbatim to the CLI subprocess as global flags:
storePath→--store-pathhome→--hometmuxCommand→--tmux-command
Set them only when the consumer needs to override the CLI's default for that field.
Verb examples
spawn
Launch a tracked Claude Code instance in a new tmux session.
agent-director spawn --cwd ~/my-projectconst result = await client.spawn({ cwd: "~/my-project" });
console.log(result.claude_instance_id);status
Get the current lifecycle state of a Spawn.
agent-director status --claude-instance-id <id>const result = await client.status({ claude_instance_id: "<id>" });
console.log(result.state);list
Query Spawns with optional filters.
agent-director list --state waitingconst result = await client.list({ state: ["waiting"] });
for (const spawn of result.spawns) {
console.log(spawn.claude_instance_id, spawn.state);
}sendKeys
Send text to a Spawn's tmux pane.
agent-director send-keys --claude-instance-id <id> --text "what is 2+2?"await client.sendKeys({ claude_instance_id: "<id>", text: "what is 2+2?" });kill
Terminate a Spawn's tmux session.
agent-director kill --claude-instance-id <id>await client.kill({ claude_instance_id: "<id>" });makeTemplate
Save a reusable spawn preset. Pass overwrite: true to atomically replace an existing template; omit the field to keep the default rejection on collision.
agent-director make-template --name dev --cwd /repos/widget --overwriteawait client.makeTemplate({ name: "dev", cwd: "/repos/widget", overwrite: true });Versioning
The library version equals the agent-director release tag — released in lockstep:
| npm package | CLI binary |
|---|---|
| [email protected] | agent-director CLI v0.5.0 |
Supported Bun versions
Minimum: >=1.0.21 (set in engines.bun). Tested on Bun 1.3.x as of this release. The using block syntax (Explicit Resource Management) requires Bun 1.0.21+.
Errors
Every error thrown by this package extends AgentDirectorError. A typed subclass is generated for each err_name in the shared catalog so you can catch by subclass:
import { Client, ErrSpawnNotFound } from "agent-director";
try {
await client.status({ claude_instance_id: "bogus" });
} catch (e) {
if (e instanceof ErrSpawnNotFound) {
// recover
} else {
throw e;
}
}The full err_name catalog is in ../../pkg/api/errnames/catalog.json.
Architecture
See ../../docs/architecture.md for the internal design. Dedicated subsections cover: Client lifecycle, the subprocess call recipe, Per-platform packaging, Error mapping, TS smoke-test harness, and TS envelope-diff regression.
