Skip to content

Library: init and run

These exports run the CLI from code and perform the work behind init. run is the whole command line behind one function. initializeHarnesses is the linking step init performs, without the option parsing or the output. initCommand, harnessCommand, and activate let another CLI mount the commands.

import { activate, harnessCommand, initCommand, initializeHarnesses, run } from 'buddy-agent-harness'
import type { InitializeOptions, InitializeResult } from 'buddy-agent-harness'
function run(argv: string[]): Promise<number>

Parses argv against every buddy-agent-harness command and runs the one it names. It takes the whole argv, the runtime and script path included, the same shape as process.argv.

It resolves to the exit code instead of writing process.exitCode, and it never reads process.argv, so a caller that is not the process can act on the result:

CodeMeaning
0The command did what was asked, or reported no code
the command’s codeThe command returned one, such as 1 when init fails
2The invocation was rejected or could not be parsed

A failure goes to stderr as error: <message>, never to stdout, which carries the report an agent parses. The command’s own report still goes to stdout.

const code = await run([process.execPath, 'buddy-agent-harness', 'doctor', '--format', 'json'])
function initializeHarnesses(options: InitializeOptions): InitializeResult

Links the canonical <root>/.agents/skills directory into every enabled harness that cannot read it directly. It is the function behind init, and it shares that command’s conflict behavior: it checks every target before changing any, and it throws when a conflict is not covered by force.

It creates <root>/.agents/skills and <root>/.agents/references when they are absent. It records nothing else about the run; the returned result is the only report.

const result = initializeHarnesses({ root: process.cwd(), harnesses: ['codex'] })
console.log(result.linked)

It throws when:

  • a conflicting target is not covered by force, and force named no target;
  • force names a target that no enabled harness projects.
FieldTypeMeaning
rootstringThe repository or package directory to initialize
harnessesHarnessName[]Harnesses to enable in addition to Claude Code and Cursor and to the harnesses detected under root. Defaults to []
copybooleanCopy the canonical skills directory instead of linking it. Defaults to false
forceboolean | readonly string[]Replace conflicting targets. true replaces every conflict. A list names the targets to replace, as repository-relative or absolute paths; a conflict it does not name is skipped and reported, not replaced. Defaults to false

Where a link fails and nothing occupies the target, the directory is copied instead, even when copy is false.

FieldTypeMeaning
rootstringThe root it was given
harnessesHarnessName[]Every enabled harness
nativeHarnessName[]Enabled harnesses that read .agents/skills directly, so nothing was written for them
linkedHarnessName[]Enabled harnesses that received a projection
skippedHarnessName[]Enabled harnesses left untouched because their target conflicts and force did not name it
deprecated{ name: HarnessName; replacedBy: HarnessName }[]Enabled harnesses whose name has been superseded, with the name that replaces each
skillsnumberThe number of canonical skills
referencesnumberThe number of references the project tier holds
copiedbooleanWhether copying was requested
const initCommand: cli.Command

The init command as a clibuilder command object. Its run calls initializeHarnesses with the parsed options and returns the result, which clibuilder prints in the requested format. It exits 0 on success and 1 on failure, writing the failure to stderr.

const harnessCommand: cli.Command

A clibuilder command group named agent-harness that holds init, doctor, reference, and governance. It is named agent-harness, not harness, because repobuddy mounts every plugin into one namespace.

function activate(host: { addCommand(command: typeof harnessCommand): void }): void

Adds harnessCommand to a host CLI through its addCommand. This is how installing the package alongside repobuddy mounts the commands as buddy agent-harness init and buddy agent-harness doctor.

activate({ addCommand: (command) => commands.push(command) })