# API
```rust
use std::{collections::BTreeMap, path::PathBuf, time::Duration};
use kcode_k1_accounting::{Accounting, UsageValue};
use serde_json::Value;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ErrorKind {
InvalidInput,
Unavailable,
Timeout,
Protocol,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Error { /* private fields */ }
impl Error {
pub const fn kind(&self) -> ErrorKind;
pub fn message(&self) -> &str;
}
impl std::fmt::Display for Error;
impl std::error::Error for Error;
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Clone, Debug, PartialEq)]
pub struct ToolRun {
pub input: String,
pub tool_name: String,
pub tool_description: String,
pub input_schema: Value,
}
#[derive(Clone, Debug, PartialEq)]
pub struct ToolRunResult {
pub arguments: Value,
pub thread_id: String,
pub turn_id: String,
pub usage: BTreeMap<String, UsageValue>,
}
#[derive(Clone)]
pub struct CodexTerra { /* private fields */ }
impl CodexTerra {
pub fn new(
accounting: Accounting,
executable: impl Into<PathBuf>,
working_directory: impl Into<PathBuf>,
timeout: Duration,
) -> Result<Self>;
pub async fn run(&self, run: ToolRun) -> Result<ToolRunResult>;
}
```
`CodexTerra::new` accepts a nonempty executable path and a nonzero complete-operation timeout. It performs no I/O. The executable and working directory are immutable and reused by every run.
`ToolRun::input` is any UTF-8 string, including empty text, and is sent byte-for-byte as the sole text input. The tool name must match `[A-Za-z0-9_-]{1,64}`, and the description must be nonempty. `input_schema` must be an object containing a schema accepted by the JSON Schema validator; `$schema` selects a supported draft and omission uses the validator default. All caller-input validation occurs before app-server startup.
Each `run` starts one owned Codex app-server process, one fresh ephemeral thread fixed to `gpt-5.6-terra`, and exactly one turn. It exposes exactly one dynamic function and places the fixed one-call requirement in the developer-instruction field, never in caller input. Web search, MCP, shell, apps, browser, computer use, image generation, multi-agent operation, plugins, and approvals are disabled; the sandbox is read-only. A valid call is acknowledged with the fixed text `ok` so the same turn can finish. Returned arguments have passed the supplied schema. Assistant prose is discarded and the API exposes no continuation.
Normal thread, turn, item, model-safety, and token-usage notifications and the dynamic-tool request may interleave with responses. They are retained in wire order until response-derived identifiers are known, then scope-checked and processed once. A mismatched response identifier is `Protocol`. An unexpected request or event, model reroute, built-in or wrong tool, zero or multiple dynamic calls, malformed or schema-invalid arguments, failed or interrupted turn, mismatched scope, invalid or nonmonotonic usage, or missing terminal usage is also `Protocol`. Invalid configuration, metadata, or schema is `InvalidInput`; process or transport failure is `Unavailable`; expiry is `Timeout`. Error messages are diagnostics, not a stable matching interface.
The library starts at most one process, thread, and turn and never restarts or resubmits them. The Codex executable's built-in OpenAI transport may internally retry HTTP or stream failures under its own policy; this library neither controls nor observes those internal attempts. The timeout covers startup, thread and turn work, tool acknowledgement, terminal usage, and normal process shutdown. A success or error reached before expiry explicitly shuts down and reaps the process; an original operation error takes precedence over a simultaneous shutdown error. Expiry or cancellation relies on transport kill-on-drop rather than synchronously reaping before return. No path leaves a resumable thread owned by this library.
`run` must be polled within a Tokio runtime with process and time drivers. Dropping its future cancels the run at the next Tokio scheduling opportunity.
Every run that successfully writes `turn/start` appends exactly one process-local accounting event, including later timeout, cancellation, or error. Earlier failures append none. The event source is `gpt-5.6-terra`, operation is `run tool`, and an empty usage map means unknown usage rather than zero. Valid partial usage is retained on failure. Successful results and events contain exactly these case-sensitive keys:
- `input tokens`: all uncached input, including prompt-cache writes;
- `cached input tokens`;
- `output tokens`: non-reasoning output;
- `reasoning tokens`.
Units and API-equivalent estimated prices are exact decimals in cents. A provider round with at most 272,000 total input tokens prices ordinary uncached input at 200 cents, cache-write input at 250 cents, cached input at 20 cents, and output or reasoning at 1,200 cents per million tokens. A round above 272,000 uses 400, 500, 40, and 1,800 cents respectively for the entire round. Cache-write units remain part of `input tokens`, while that key's price combines ordinary and cache-write rates. Every nonduplicate cumulative update must be monotonic; latest-round counts must equal cumulative deltas, preventing double counting across the two rounds around the tool call. Success requires two nonduplicate reconciled provider-round usage updates: the round before the tool request and the round after its response.
Cloned clients have no shared provider lock and run independently. Accounting serialization is limited to the ledger's brief in-memory record operation. Each run owns one subprocess and performs JSONL subprocess I/O; provider networking belongs to the executable. There is no remote-latency guarantee.
Construction uses work and peak allocation linear in the two path lengths. The reference canary `cargo test --release --test terra local_construction_canary` constructs 10,000 clients with paths below 4 KiB in under one second on stable Rust, Linux x86-64, four 3.0 GHz or faster cores, and 8 GiB RAM. For `run`, schema work follows the selected schema; client-owned serialization and parsing are linear in their JSON records. Peak client memory is linear in input, schema, arguments, queued records, and the current inbound line; lines above 8 MiB fail. The reference canary `cargo test --release --test terra local_run_canary` completes one fake operation with 64 KiB input in under five seconds on the same environment. These canaries exclude remote work; the configured timeout is the owned completion bound.