@chamvi/coding
Coding tools for chamvi agents and the coding backend contract. The public API of packages/coding/src/index.ts.
npm install @chamvi/coding @chamvi/sandbox @chamvi/core ai --save@chamvi/core, @chamvi/sandbox and ai are peer dependencies. See Workspaces & Coding for the behaviour.
codingTools
function codingTools(workspaces: CodingWorkspaces): ToolSet;
type CodingWorkspaces = Pick<IWorkspaceManager, 'get'>;Throws InvalidAgentDefinitionError when workspaces has no get. Returns read_file, write_file, edit_file, grep, list_files, bash and git_diff, each a defineTool() tool that resolves its workspace through workspaces.get(context.run.runId, input.workspace).
| Tool | Input | Result |
|---|---|---|
read_file | path, offset? (1-based, default 1), limit? (default and maximum 2000) | ReadFileResult |
write_file | path, content | WriteFileResult |
edit_file | path, oldString, newString, replaceAll? | EditFileResult |
grep | pattern (POSIX ERE), path?, ignoreCase?, limit? (default 100, at most 500) | GrepResult |
list_files | path?, limit? (default 1000, at most 5000) | ListFilesResult |
bash | command, cwd?, timeoutMs? (default 300 000, at most 1 800 000) | ExecResult from @chamvi/sandbox |
git_diff | staged?, path? | GitDiffResult |
Every tool also takes workspace?, the id from create_workspace. A path is relative to the workspace root or starts with /workspace/. Input the model can correct (a bad path, an oldString that is missing or ambiguous) is a ValidationError tool error; a missing or oversized file and any other sandbox failure a SandboxError tool error.
/*
* Copyright (c) 2026.
* Author Peter Placzek (tada5hi)
* For the full copyright and license information,
* view the LICENSE file that was distributed with this source code.
*/
import type { IWorkspaceManager } from '@chamvi/sandbox';
/** What the coding tools need of a workspace manager: the run's workspaces by id. */
export type CodingWorkspaces = Pick<IWorkspaceManager, 'get'>;
export type ReadFileResult = {
/** Relative to `/workspace`. */
path: string;
content: string;
/** 1-based, inclusive. */
startLine: number;
endLine: number;
totalLines: number;
/** True when `content` was cut at `READ_MAX_CHARS`. */
truncated: boolean;
};
export type WriteFileResult = {
path: string;
bytes: number;
};
export type EditFileResult = {
path: string;
replacements: number;
};
export type GrepMatch = {
path: string;
line: number;
text: string;
};
export type GrepResult = {
matches: GrepMatch[];
/** True when more matches exist than were returned. */
truncated: boolean;
};
export type ListFilesResult = {
files: string[];
truncated: boolean;
};
export type GitDiffResult = {
/** `git status --short`. */
status: string;
diff: string;
truncated: boolean;
};const READ_MAX_LINES: 2_000;
const READ_MAX_CHARS: 65_536;
const SEARCH_MAX_RESULTS: 500;
const LIST_MAX_RESULTS: 5_000;
const LINE_MAX_CHARS: 500;ICodingBackend
The contract for something that solves a coding task in a workspace with its own tool loop. Only the contract ships; backends (the own tools in a nested loop, Claude Code) are planned.
/*
* Copyright (c) 2026.
* Author Peter Placzek (tada5hi)
* For the full copyright and license information,
* view the LICENSE file that was distributed with this source code.
*/
import type { IWorkspace } from '@chamvi/sandbox';
export type CodingBudget = {
maxSteps?: number;
maxTokens?: number;
timeoutMs?: number;
};
export type CodingTask = {
/** The workspace to work in; the backend never disposes it. */
workspace: IWorkspace;
/** What to do, in plain language. */
task: string;
budget?: CodingBudget;
signal?: AbortSignal;
};
export type CodingResult = {
/** `done` when the task is solved, `stuck` when the backend gave up. */
status: 'done' | 'stuck';
summary: string;
/** The workspace's changes as a unified diff. */
diff: string;
};
/**
* Something that solves a coding task in a workspace with its own tool loop
* (the own coding tools, Claude Code, ...).
*/
export interface ICodingBackend {
code(task: CodingTask): Promise<CodingResult>;
}