@volter-ai-dev/supercode-harness-sdk
v0.3.13
Published
TypeScript client for Supercode's harness.v1 session and runtime service
Downloads
3,371
Readme
Supercode harness SDK
This zero-dependency Node client launches supercode harness serve and exposes
the versioned persisted-session, local inventory, transfer, and live-runtime
primitives. The original low-level request methods remain available; managed
objects add cleanup, aborts, typed async iteration, and sequence-gap recovery.
import { SupercodeHarnessClient } from '@volter-ai-dev/supercode-harness-sdk';
const client = new SupercodeHarnessClient();
const { harnesses } = await client.listHarnesses({ workspace: process.cwd() });
const { next_cursor, sessions } = await client.discover({
limit: 50,
query: 'release',
workspace: process.cwd(),
});
const mirror = client.session(sessions[0].locator);
const { session, window } = await mirror.loadWindow({
inline_media: 'metadata',
message_tail: 200,
});
const controller = new AbortController();
for await (const event of mirror.follow({
signal: controller.signal,
view: {
tailMessages: 500,
maxMessageChars: 16_000,
includeSubagents: false,
displayHistory: true,
},
})) {
// initial/full snapshots, append events, unsequenced `runtime_state`
// lifecycle events, and recoverable watch errors
console.log(event);
}
const runtime = await client.startManagedRuntime({
harness: 'codex',
cwd: process.cwd(),
policy: 'yolo',
});
// Open the same live runtime in a terminal without exposing its bearer token.
const { launch } = await runtime.terminalInstructions();
runtime.on('event', (event) => console.log(event.type, event.raw));
await runtime.sendInput('Explain this screenshot.', {
imageUrls: ['data:image/png;base64,...'],
});Hosts that provide their own terminal or tmux transport can start a new native interactive session without duplicating harness command-line knowledge:
import { createNativeStartLaunch } from '@volter-ai-dev/supercode-harness-sdk';
const launch = createNativeStartLaunch({
harness: 'codex',
cwd: process.cwd(),
prompt: 'Inspect the current build and explain any failures.',
policy: 'default',
});
await terminalHost.launch(launch); // spawn(program, arguments), never a shell command stringThe initial prompt remains one argv element even when it contains shell metacharacters. Native interactive start currently covers Claude Code and Codex; unsupported harnesses fail explicitly.
A discovered session that is running right now carries live_status.
Claude Code publishes busy/idle and a messageable cc-peer:v1:…
live_endpoint. Stock Codex exposes no peer endpoint or turn activity, so the
local host reports the narrower running state only while a Codex process
holds that exact rollout open:
const outcome = await client.messageSession(sessions[0].locator, 'rebase onto main, please');
if (outcome.delivered_to_bus) console.log('handed to', outcome.target.name);
else console.log('refused:', outcome.refusal.reason, outcome.refusal.message);
const advisory = outcome.inbound_controls?.advisories[0];
if (advisory) {
console.warn(advisory.message);
// Only after an explicit user decision:
await client.configureHarness(
'claude-code',
[advisory.recommendation.change],
outcome.inbound_controls.revision,
);
}A refusal (harness_unsupported, not_live, identity_mismatch,
delivery_failed) is a normal result, not a thrown error. delivered_to_bus
is deliberately the strongest claim available: the text reached the receiving
session's inbox, that session's own inbound-message controls decide whether it
is read, and it shows up in the mirror through the followed transcript — often
seconds later — rather than as a turn you own. Delivery spawns a one-shot
headless Claude restricted to the two documented cross-session tools; Supercode
does not write the receiver's Unix socket, whose wire frame is undocumented.
harnessSettings('claude-code') provides the same user-level preflight report
without sending. Managed, project, or command-line policy may still override
the user setting for a particular target process. Choosing accept trusts
messages from the user's other Claude Code sessions; the receiving session's
ordinary tool and permission controls still apply.
Discovery covers Claude Code, Codex, Gemini CLI, Grok, OpenCode, Pi, and
Supercode's native store. query is case-insensitive across harness, id,
title, workspace, and model; next_cursor is opaque and may be supplied as
cursor on the next call. loadWindow bounds message history and can replace
inline data URLs with media_reference metadata. message_tail cannot be
combined with message_offset or message_limit. Every bounded result also
returns a full-session summary, so first/last message and completion state do
not change merely because older message bodies were omitted from the window.
The window's older_items/newer_items count omitted normalized conversation
and tool entries, allowing a renderer to disclose truncation exactly.
Managed runtime iterators end when the native transport closes or when the
parent client is closed. Terminal transport errors arrive through the common
event stream (and the non-special runtimeError event); native EOF is a
typed closed event. A closed managed runtime rejects further input.
For an ACP agent, pass a stable harness id, protocol: 'acp', and a launch
command. OpenCode can join a running TUI/server only when that process was
started on a known URL; pass it as base_url. Persisted continuation is
resumeRuntime; attachExistingRuntime is reserved for a genuine live
endpoint attach and reports unsupported capability honestly.
listHarnesses() is passive by default. Session counts are also opt-in because
some users have thousands of transcripts: pass { include_sessions: true } or
use supercode harnesses list --sessions. { probe: 'handshake' } opens an
empty protocol session, observes its transport through startup stabilization,
and closes it without submitting a model prompt or spending model tokens.
load() and follow() are read-only, so they report the same fidelity +
residue pair on the session itself and default to viewing at semantic
fidelity: a Claude Code transcript that has been compacted or resumed across
files routinely contains a live record whose parentUuid was pruned, and a
mirror needs to render it, not refuse it. The stitched-together view names
every dangling uuid in session.residue and reports
session.fidelity === 'semantic' — never continue from one. Pass
{ fidelity: 'byte_lossless' } to get the strict refusal instead; every
continuation/transfer method below is lossless-only and has no view mode.
Frontends should also pass view: it bounds the trailing message window and
each individual text field, avoids eagerly attaching Claude Code's child
transcript tree, and keeps human-visible Codex history across model-context
compaction. Omitting view preserves the complete legacy read contract.
Import/export/translate/branch/handoff methods return typed artifacts with an
explicit fidelity classification and named residue. Same-format
line-oriented exports replay captured native bytes; logical stores such as
OpenCode SQLite are classified separately and carry a recovery member. Claude
Code subagent and Grok bundle files appear in files; cross-format exports
preserve the portable conversation but cannot
claim that target schemas retain every source-native record. Structured
launches are argument arrays, never shell-quoted command strings. A handoff
artifact names its actual wire format, which can differ from
the destination harness: Grok handoff returns Claude Code JSONL because that is
the supported input to Grok's official importer. The artifact gets a fresh
target UUID; read the importer result's session ID and substitute it for
{imported_session_id} in the structured launch.
reduceSession() is the rate-limit-rescue primitive. It strictly loads the
source, creates a bounded view with the core reversible reduction engine, and
writes the complete sidecar, reduction log, and working view to Supercode's
session store. The service reloads those files, verifies every pointer, and
byte-exactly inverts the view before returning a ReductionReceipt and target
bootstrap prompt. A small or non-lossless source is refused; no optimistic
fallback is returned.
