Skip to content

coding-tools

@alexkroman1/aai/coding-tools — the workspace tool set for an agent that edits code.

A FACADE. The subpath resolves here rather than at coding-tools.ts, which buys two things the direct form could not. That module can be SPLIT as it grows without moving the published entry point — the path an implementation file happens to have is not a thing to promise anyone — and a name it gains next reaches the public surface only when a line is added below, rather than the moment it is written.

Named re-exports rather than export * for the second half of that: the wildcard form re-exports whatever arrives, and needs a noReExportAll suppression the escape-hatch ratchet only lets move down.

What is deliberately NOT here is the machinery UNDER the tools — the edit matcher, the workspace grep, the capped child-process runner. This subpath’s promise is the tool SET a host installs and a model calls, and every name on it is one an agent author writes. Of the three, only the RUNNER is published at all (@alexkroman1/aai/host-internal, no semver promise), and only because the guest harness spawns npm and the CLI bundler through it; the other two have no consumer outside coding-tools.ts and publishing them would be a surface with no reader.

createCodingTools<N>(options): Record<N, ToolDef>

Build a coding agent’s tool set over one directory.

The result is keyed by the name the model calls, so it goes onto a definition through withTools (a resolved registry) rather than through tools/ files: every tool here closes over THIS workspace, and a host serving more than one builds the set per workspace for exactly that reason.

N extends CodingToolName = CodingToolName

CodingToolsOptions<N>

Record<N, ToolDef>

CodingToolName = "list_files" | "read_file" | "glob" | "grep" | "write_file" | "edit_file" | "delete_file" | "bash" | "todo_write"

Every tool createCodingTools can build, by the name the model calls.


CodingToolsOptions<N> = object

What createCodingTools takes.

Generic in the tool NAMES so the result is a record with literal keys rather than an index signature: a tools/read_file.ts that default-exports codingTools.read_file has to type-check as a ToolDef, and under noUncheckedIndexedAccess a Record<string, ToolDef> hands back ToolDef | undefined. Nothing has to name the parameter — it is inferred from CodingToolsOptions.only, and defaults to every tool.

N extends CodingToolName = CodingToolName

optional afterWrite?: (rel) => Promise<string | undefined>

Text appended to a successful write_file / edit_file result — the seam a host hangs diagnostics on. Answer undefined when there is nothing to add.

string

Promise<string | undefined>

optional descriptions?: Partial<Record<CodingToolName, string>>

Per-tool description overrides, merged over CODING_TOOL_DESCRIPTIONS.

dir: string

Absolute path of the workspace root. Nothing outside it is reachable.

optional env?: NodeJS.ProcessEnv

The bash child’s environment. Defaults to this process’s own.

optional only?: readonly N[]

Build only these tools. Defaults to all nine.

A host that has a better tool of its own for one of these jobs names the rest here, rather than building the full set and deleting a key — which reads as an accident at the call site and cannot be type-checked.

optional validate?: (rel, content) => Promise<string | undefined>

Refuse a write before it lands: answer a message to REJECT the content, or undefined to let it through. The message is returned to the model verbatim, so say what to do about it and not only what is wrong.

string

string

Promise<string | undefined>

const BASH_TIMEOUT_MAX_MS: number


const BASH_TIMEOUT_MS: number

Default and maximum wall-clock for one bash command.


const CODING_TOOL_DESCRIPTIONS: Readonly<Record<CodingToolName, string>>


const GLOB_LIMIT: number

Max glob results before the list is truncated, newest first.


const READ_LIMIT: number

read_file paging default and hard cap, in lines.