npm package: @nendlabs/hargness
Description: Define nested agent-facing CLIs in TypeScript or YAML and compile them into Bun executables with generated skill docs.
Latest version: 0.1.2

# hargness

Hargness turns a typed command definition into:

- a Bun CLI executable that agents can invoke
- a generated `SKILL.md` that explains how to use that CLI
- optional per-invocation trace manifests and artifacts

Use it when you want to expose a bounded set of application or repo operations
to agents through a validated command tree instead of open-ended shell access.

## Install

```bash
bun add -d @nendlabs/hargness
```

Run the build CLI without installing it into a project:

```bash
bunx @nendlabs/hargness build --source ./cli.ts
```

Install or refresh the Hargness Codex skill without a global install:

```bash
bunx @nendlabs/hargness codex install
```

This writes the package skill to `~/.hargness/SKILL.md` and links it into
`${CODEX_HOME:-~/.codex}/skills/hargness/SKILL.md`, so future installs can
update the stable Hargness-owned file without changing the Codex skill path.

## Definitions in TypeScript

Author a CLI by wrapping existing functions with `defineAction(...)` and nesting
them with `defineGroup(...)`.

```ts
import { createCli, defineAction, defineGroup } from "@nendlabs/hargness";

async function deploy(args: { env: "staging" | "prod"; version: string }) {
	return {
		ok: true,
		env: args.env,
		version: args.version,
	};
}

export default createCli({
	name: "appctl",
	description: "App operations for agents.",
	build: {
		version: "0.1.0",
	},
	trace: {
		enabled: true,
	},
	commands: [
		defineGroup({
			name: "deploy",
			description: "Deployment commands.",
			commands: [
				defineAction({
					name: "run",
					description: "Deploy a version.",
					args: {
						env: {
							type: "enum",
							values: ["staging", "prod"] as const,
							required: true,
							description: "Target environment.",
						},
						version: {
							type: "string",
							required: true,
							description: "Version to deploy.",
						},
					},
					run: deploy,
				}),
			],
		}),
	],
});
```

The declared `args` schema is the runtime source of truth for parsing,
validation, help, generated docs, and trace redaction.

## Definitions in YAML

YAML definitions are useful for shell-backed commands:

```yaml
name: fs
description: Filesystem helpers for agents.
build:
  version: "0.1.0"
trace:
  enabled: true
commands:
  - name: file
    description: Read file contents.
    commands:
      - name: read
        description: Read a file and cap output to maxBytes.
        args:
          path:
            type: string
            required: true
            description: File path to read.
          maxBytes:
            type: number
            default: 4096
            description: Maximum bytes to return.
        sh: |
          head -c {{maxBytes}} {{path}}
```

Shell placeholders like `{{path}}` must reference declared args. Hargness
validates them and shell-quotes values at runtime.

## Build

Build a Hargness CLI definition into a distributable directory containing the
executable and its generated skill. The source file should export a
`CliDefinition` or `CliRuntime`, or be a Hargness YAML definition.

```bash
hargness build --source ./cli.ts
```

YAML definitions use the same flag:

```bash
hargness build --source ./cli.yaml
```

By default this writes:

```text
~/.hargness/<cli-name>/dist/<version>/
  <cli-name>
  SKILL.md
```

Pass `--outdir` to choose the directory explicitly:

```bash
hargness build --source ./examples/fs.ts --outdir ./dist/fs
```

The programmatic API is the same:

```ts
import { buildCli } from "@nendlabs/hargness";

await buildCli({
	source: "./examples/fs.ts",
	outdir: "./dist/fs",
});
```

## Run

After building, give agents the executable and generated `SKILL.md`:

```bash
./dist/fs/fs dir list --path ./src --session-id agent-session-123
./dist/fs/fs file read --path ./README.md --maxBytes 256 --session-id agent-session-123
```

`--session-id` is optional, but agents should pass a stable value across related
invocations so traces can be correlated.

## Traces

Set `trace: { enabled: true }` in the CLI definition to write invocation
records under:

```text
~/.hargness/<cli-name>/trace/<build-hash>/<run-id>/
  manifest.json
  artifacts/
```

List recent trace manifests for a CLI:

```bash
hargness trace list --cli fs
```

Show the latest trace manifest, or a specific manifest:

```bash
hargness trace show --cli fs
hargness trace show --cli fs --buildHash <build-hash> --runId <run-id>
```

Use `--dir <trace-root>` when a CLI definition writes traces to a custom
`trace.dir`.

Args marked `secret: true` are redacted in manifests and generated examples.