Agent skill

Harness

by skillsynchq in skillsynchq/txcript

Integrate a new AI coding-agent harness into txcript — native Body types, Codec, TextCodec, Store, wiring, and tests.

Apache-2.0Auto-check passed

Install Harness

skills CLI
$ npx skills add skillsynchq/txcript --skill harness -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install skillsynchq/txcript harness --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/skillsynchq/txcript.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/harness .claude/skills/harness && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
harness
GitHub stars
153
Token cost
~4.2k tokens
SKILL.md length
2,240 words
Files
2 (incl. references)
Skills in repo
3
Repo updated
First seen
Licence
Apache-2.0

At a glance

Integrate a new AI coding-agent harness into txcript — native Body types, Codec, TextCodec, Store, wiring, and tests.

  • Works in 8 steps: Recon: the bytes are the spec → Choose the Body shape → Native record rules → …
  • Integrate a new harness
  • SKILL.md covers Inputs, The two fidelity contracts…, Phase 0 — Recon: the bytes are… and Phase 1 — Choose the Body shape, plus 6 more sections
  • Calls cargo, opencode and claude

What it does

Harness is an agent skill from skillsynchq/txcript. Integrate a new AI coding-agent harness into txcript — native Body types, Codec, TextCodec, Store, wiring, and tests. Use when asked to add or integrate a new harness or transcript format. Takes the harness name, its format docs (URL or path), and one real local session id to anchor implementation and verification on.

Its SKILL.md is about 4.2k tokens, which your agent loads only when the skill is triggered. The skill folder holds 2 other files, including reference files (for example `references/patterns.md`).

It works with Rust, Model Context Protocol and WebAssembly. The repository describes itself as: Pandoc for AI chats. Move ai chats across harnesses: Claude Code, Codex, OpenCode, Cursor, and more. Rust library, CLI, and WASM. The licence is Apache-2.0.

When your agent uses it

  • Integrate a new harness
  • Transcript format

Example prompts

  • “/harness”

Workflow steps

8 steps, taken from the step headings in SKILL.md.

  1. Recon: the bytes are the spec
  2. Choose the Body shape
  3. Native record rules
  4. Codec
  5. TextCodec + Store
  6. Wiring checklist
  7. Tests
  8. Verification gates

What it can do on your machine

Read from SKILL.md and the folder at commit 8cd3b0e. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • cargo
    • opencode
    • claude

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Harness loads about 4.2k tokens when it runs, and up to ~8.1k if it reads all its reference files. Until then it costs about 82 tokens; SKILL.md has 2,240 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~82
When it runs · the whole SKILL.md, loaded when a task matches
~4.2k
With references · SKILL.md plus every file in references/, read only if the agent opens them
~8.1k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from skillsynchq/txcript at commit 8cd3b0e, republished under its Apache-2.0 licence (© skillsynchq). 2,240 words, ~4,226 tokens.

Download SKILL.mdSave it as .claude/skills/harness/SKILL.md (or your agent's skills folder). This skill also uses 1 other file; get the full folder from GitHub.
name
harness
description
Integrate a new AI coding-agent harness into txcript — native Body types, Codec, TextCodec, Store, wiring, and tests. Use when asked to add or integrate a new harness or transcript format. Takes the harness name, its format docs (URL or path), and one real local session id to anchor implementation and verification on.
argument-hint
<name> <docs-url-or-path> <sample-session-id>

Integrate a new harness

You are adding a harness to txcript, the transcript converter in this repo. The work is one flat file src/harness/<name>.rs plus wiring and tests, but the quality bar is set by two fidelity contracts (below) and by the fact that the output must actually resume in the native app — a session that loads but shows an empty conversation is a failed integration.

Inputs

$ARGUMENTS: <name> <docs> <sample-session-id>

  • name — the harness (e.g. gemini, amp). Derive the snake_case id from it.
  • docs — URL or file path describing the native transcript format.
  • sample-session-id — a real session of that harness on this machine. This is your ground truth. If any input is missing, ask before starting.

The two fidelity contracts (non-negotiable, from src/lib.rs)

  1. Native ↔ disk is record-lossless. The Body holds a faithful typed representation; Store/TextCodec round-trip it without loss. This is value-level, not byte-level: serde_json is built without preserve_order, so key order canonicalizes — tests assert record equality, never string equality of the file.
  2. Through Common is semantically lossless. to_common may canonicalize representation (so the thread works in another harness) but must never discard what a same-harness round trip needs. The testable form is the fixpoint: to_common(from_common(c)) == c for any c in the harness-representable subset of Common.

Corollary: from_common must be pure and deterministic — synthetic ids are UUIDv5 over a fixed namespace and stable keys like "{session_id}:{i}:{j}", never Uuid::new_v4() (sole exception: generating a session id when meta.id is empty), never clock reads.

Phase 0 — Recon: the bytes are the spec

Before writing any Rust:

  1. Read the docs at <docs>.
  2. Find the sample session on disk. Probe the harness's storage root (~/.<name>/…, XDG data dirs, an SQLite DB, app-support dirs) until you locate the file/rows for <sample-session-id>.
  3. Dump the raw session into the scratchpad. Catalog every record/blob kind you observe: which carry conversation (user/assistant/tool records), which are bookkeeping (headers, token counts, snapshots, titles, model changes), which are opaque (binary, protobuf).
  4. Check how the native app resumes a session (CLI flag, id format, sidecar files it validates). The consumer defines correctness, not the schema.
  5. Interrogate the consumer by bisection. Find the harness's cheapest read-only replay of a session (<name> export, sessions list, a --print resume) and use it as a load oracle: copy the sample under a fresh id, then delete files/records until it stops loading. What survives deletion is bookkeeping; what breaks the load is the regeneration contract for from_common — learned before writing any code, at zero model cost.
  6. Mint the bytes the sample lacks. One session won't cover every record kind you must emit (file edits, images, errored calls, aborts). Don't guess from docs — run the harness itself headlessly in a scratch dir with prompts engineered to exercise each gap, and probe its input flags (a --prompt-json-style flag reveals content-block encodings). The same trick answers optionality questions: to learn whether the native parser treats a field as optional, load a session without it.
  7. For multi-file/dual-log formats, write down the exclusive carrier of each semantic field: timestamps, images, or stop reasons may exist only in the display log while reasoning tokens exist only in the model log. to_common is then a join across carriers and from_common a fan-out — knowing the carrier map is most of the codec design.

Where docs and bytes disagree, model the bytes. Keep the dump — it becomes your test fixture material and the final verification anchor. Copy the sample session out of the live root NOW: save() derives its path from Meta, so converting a session back into its source harness reuses the original id and silently overwrites your ground truth.

Phase 1 — Choose the Body shape

Pick the closest existing codec as your reference and re-read it before implementing (don't work from memory of it):

Native formatReferenceBody pattern
JSONL, one envelope kindcodex.rsSingle Line { timestamp, type, payload: Value, #[serde(flatten)] extra }
JSONL, a few typed kindsclaude_code.rs, pi.rsEnum with manual serde via From<Value> dispatch on the type tag; parse failure → Other(Value); tagged() helper re-inserts the tag on render
One JSON export documentopencode.rsBody = the harness's own export/import shape; typed two-level envelope, everything inside stays Value, navigated with .get()
SQLite with opaque blobscursor.rsBody = raw rows (Vec<u8> blob bytes with hex serde + meta rows); losslessness at the blob level; only parse what you understand
Session directory, multiple logsgrok.rsBody = struct of per-file fields (typed model log, raw Vec<Value> display/telemetry logs, Option<Value> sidecars); "text" is a JSON bundle of the directory
Sibling of an existing harnesscampfire.rsThin delegate: reuse the donor's pub(crate) helpers, change only identity and storage root

Details and per-harness idioms: read references/patterns.md in this skill directory now.

Phase 2 — Native record rules

  • Type only what the codec must interpret; keep messy payload unions as raw Value inside a typed envelope.
  • Every typed record struct: #[serde(flatten)] extra: Map<String, Value> for unknown keys, and #[serde(default, skip_serializing_if = "Option::is_none")] on every optional field — absent must not round-trip as null.
  • The type tag lives outside the struct (stripped on parse, re-inserted on render), or it duplicates into extra.
  • Any classification/parse failure demotes to a raw-Value variant (Record::Other(v)) — never an error, never a dropped line. One corrupt line must not sink the session (jsonl::parse already skips unparseable lines for the line-based path).
  • Do NOT put deny_unknown_fields on harness record types. It exists only on the canonical tool-arg structs in common.rs, where it forces the lossless Tool::Raw fallback.

Phase 3 — Codec

to_common
  • Claude Code is the canonical convention. Write a normalize_tool(name, input) that maps native tool names and argument keys onto it (bash→Bash, path→file_path, …), then call Tool::from_canonical. Its deny_unknown_fields→Raw fallback is the safety net — never bypass it, never pre-drop keys. mcp__* passes through. Write denormalize_tool at the same time; they must be a real inverse pair, including shape changes (e.g. pi's multi-hunk edit → Edit/MultiEdit by hunk count).
  • Tool results ride on Role::User messages (Anthropic convention). Errored calls → is_error: true; in-flight calls → ToolUse with no result.
  • Skip bookkeeping records and harness-injected scaffolding (environment preambles, <user_query>-style wrappers — strip on read, re-wrap on write). Skip empty/whitespace-only blocks and messages that end up empty. Unknown block types drop from Common — they still live in the native body.
  • Turn-level attribution (model, usage, stop reason) often lives in bookkeeping records far from the message: do a stateful pass with per-turn maps and backfill onto the right assistant message (typically the last text message of the turn).
  • Dual-log formats (protocol log + display log): pick the canonical record per kind, mark fallback mirrors, dedup by call id in a post-pass so file order doesn't matter.
  • Pairing without ids: key on serialized semantic content, tolerate both arrival orders, use a deterministic synthetic id as last resort.
  • Timestamps: parse per-record with fallback to meta.timestamp; never error.
from_common
  • Regenerate every field the native app validates on resume — even as explicit null (codex refuses sessions missing model_provider/ base_instructions keys). Regenerate both logs of a dual-log format, and any internal structures the app needs (Cursor's protobuf turn graph, sidecar meta.json). The failure mode here is silent: the app starts a fresh or empty session. Only end-to-end resume testing catches it.
  • Write only field shapes you have observed the native app write. This is the loud failure mode, dual to the silent one: native parsers are strict, and one field of an unobserved type fails the WHOLE session load ("invalid type: sequence, expected a string"). Structural pass-through is the lossless instinct for reading and exactly wrong for writing — where Common is richer than the observed slot (structured ToolOutput::Json into a string field, an image block into a text-only log), flatten to the observed shape (block arrays → joined text, other JSON → compact string, image → its display-log carrier plus a placeholder) and document the loss.
  • Carry a tool_use_id → native tool name map while emitting tool calls so redundant result fields can be reconstructed; give orphans a fallback.
  • Fabricate required-but-derivable fields plausibly (provider from a model-id prefix, zero cost objects, totalTokens) and comment that they are best-effort historical reconstruction.
  • Option-vs-zero trap: never serialize a default that parses back as Some(default) (e.g. omit an all-zero cache object entirely).
  • Some Common detail may have no native slot (thinking signatures, replace_all, StopReason::Other). Accept the loss, document it in the module doc, and keep the fixpoint fixture inside the representable subset.
Show full SKILL.md (867 more words)Show less
Meta

meta_from_records: per-field fallback chains with explicit keep-first or last-wins semantics (e.g. latest model_change wins; custom-title beats summary). Filter placeholder titles. Leave id empty when the text has none — the Store fills it from the filename/row. Timestamp fallback: Utc::now().

Phase 4 — TextCodec + Store

  • TextCodec is pure text↔records, zero I/O — it is the WASM boundary. For a DB-backed harness, "text" is a JSON dump of the Body (binary as hex), not anything the native tool emits; it must round-trip to an identical Body.
  • Store: default_root() returns Option<Self> honoring env overrides then $HOME paths (match the pattern in pi::resolve_sessions_dir). discover() is tolerant: missing root → Ok(vec![]), unreadable files silently skipped, and sniff the format (e.g. first record must be the session header) — extension alone doesn't identify a harness. load() backfills an empty meta.id from the file stem (jsonl::file_id). save() derives a deterministic path from Meta — copy the native app's directory encoding exactly (Claude maps both / and . to -; pi wraps --{cwd}--; Cursor uses md5(cwd)). fingerprints() is cheap: "{mtime_nanos}:{len}" or a MAX(time) query; failures → empty string, never an error.
  • New native dependency (SQLite etc.): make it a cargo feature (dep: only), keep the codec and Body compiling featureless, and stub the Store without the feature (empty discover, Unconvertible load/save). Open another tool's DB READ_ONLY; prefer delegating writes to the harness's own CLI importer if one exists (opencode import pattern) over reverse-engineering schema defaults.

Phase 5 — Wiring checklist

Every item, in order; the exhaustive matches make most omissions compile errors:

  1. src/harness/<name>.rs — the whole harness, one flat file, module doc explaining format + known losses.
  2. src/harness/mod.rs — pub mod <name>;
  3. src/transcript.rs — HarnessId variant, ALL array (bump its length), as_str, FromStr with friendly aliases.
  4. src/bin/cli.rs — resume_command default, a discover_all block, a load_common arm, a save_target arm.
  5. src/wasm.rs — both dispatch matches (parse_to_common, render_from_common) and the doc-comment harness list.
  6. Cargo.toml — feature entry if a new dep; keep it out of the wasm build.
  7. README.md — supported-harness list, string id, WASM text-format note.
  8. tests/integration/<name>.rs (declared in tests/integration/main.rs), a new hop in tests/integration/cross_harness.rs, and a new assert_fixpoint line in tests/integration/properties.rs — see tests/README.md for the taxonomy.

Repo style: hierarchical imports — import modules and qualify (common::Tool, jsonl::parse), never flatten items to the crate root. Clippy pedantic is on and unwrap/expect/panic are denied in src/ (allowed in tests via the file-top #![allow]).

Phase 6 — Tests

Standard invariants, one test each, named as behavior sentences. Fixtures are inline json! + tempfile — no checked-in fixture files. Build the native fixture from the real sample session's shapes (anonymized), covering every record kind you cataloged in Phase 0, including one unmodeled record that must survive.

  1. store_round_trip_is_lossless_on_disk — load→save→load, record equality including unknown records; assert the save path shape.
  2. discover_extracts_metadata — every populated Meta field.
  3. to_common_… — faithful extraction: typed tools with renamed keys, bookkeeping skipped, result pairing, usage/stop backfill, message count asserted exactly.
  4. codec_fixpoint_through_common_loses_nothing — to_common(from_common(c)) == c. Shape the Common fixture at the harness's native granularity (message grouping, which fields are mandatory, result timestamps) — this is the direction that holds; from_common ∘ to_common need not be byte-identical.
  5. from_common_is_deterministic — two runs serialize identically.

Plus one test per quirk you handled (error results, pending calls, legacy shapes, format sniffing), and extend the cross_harness.rs chain with the new harness so the block signature survives the extra hop. Store tests that need the native dep go #[cfg(feature = …)] inside the gated module against a real temp DB — never mocks.

Phase 7 — Verification gates

All must pass before you call it done:

  1. cargo test and cargo test --no-default-features.
  2. cargo clippy --all-targets — pedantic-clean, no unwrap/expect in src/.
  3. Real-session anchor: load <sample-session-id> through the new Store, to_common, and inspect the conversation end to end — no dropped turns, no scaffolding leaking in as user text, tools typed where expected. Then run the fixpoint on this real transcript, and convert it to claude_code and back, checking the cross-harness block signature.
  4. Resume in the native app (the only gate that catches missing-required-header and missing-display-log bugs): write the converted session with txcript continue <id> --with <name> --no-resume (or --out plus a copy into the live root), then resume it with the harness's own CLI and confirm the conversation renders and the session continues. Also do the reverse direction: sample → claude_code, resume with claude --resume. Two rules learned the hard way:
    • The sample round trip is the weakest resume test — it only exercises the subset of Common the sample happens to use, and it passes trivially. Also convert a kitchen-sink source: a real session from the richest other harness (or a synthetic Common) carrying structured JSON tool results, images, thinking, errored calls, and an aborted turn. Write-side shape bugs (the "loud" from_common failure) only surface here.
    • Verification writes get a fresh session id (set meta.id before from_common) so they can't collide with — and overwrite — real sessions; clean them out of the live roots afterward. Order the resume work by cost: the read-only export/list oracle first (validates the display log), then one headless -p-style resume turn (validates the model log actually carries the context), then the TUI.
  5. README and module docs updated; known representational losses documented in the module doc.

Report the result with: record kinds handled vs passed-through, tool mappings, known losses, and the resume verification outcome for both directions.

© skillsynchq, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 1 other file (references) in .claude/skills/harness of skillsynchq/txcript.

  • SKILL.md
  • references/patterns.md

Open the folder on GitHubat commit 8cd3b0e

Compare with similar skills

Harness next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Harness compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Harness this skillskillsynchq/txcript153—~4.2kAutomated safety check: PassApache-2.0
Webapp Buildersidequery/sidemantic129—~5.5kAutomated safety check: PassAGPL-3.0
Build And Profilingpikax/verter112—~4.3kAutomated safety check: PassMIT
Service App CreatorPeiiii/nextclaw260—~1kAutomated safety check: PassMIT
Nextclaw App CreatorPeiiii/nextclaw260—~1.6kAutomated safety check: PassMIT
Creating Zed Extensionspr-pm/prpm122—~3.1kAutomated safety check: NotesMIT

Similar skills

  • Webapp Builder

    sidequery/sidemantic

    Build interactive analytics webapps, demos, dashboards, or embedded app surfaces from Sidemantic semantic models using copyable component primitives and deterministic query inspection.

    129 GitHub stars~5.5k tokensUpdated today
    DatabasesAuto-check passed
  • Build dependency chains, rebuild sequences, profiling with MCP, and Analysis MCP server setup for Verter

    112 GitHub stars~4.3k tokensUpdated today
    Agent WorkflowsAuto-check passed
  • Service App Creator

    Peiiii/nextclaw

    Create or update the Service component of a NextClaw Mini App, choosing between Portable Rust/WASI Components and native-process MCP services.

    260 GitHub stars~1k tokensUpdated yesterday
    Auto-check passed
  • Nextclaw App Creator

    Peiiii/nextclaw

    Create or update complete NextClaw Mini Apps by first choosing a Panel-only, Service-only, or Panel + Service composition, then choosing Portable WASI or native-process only when a Service exists.

    260 GitHub stars~1.6k tokensUpdated yesterday
    Auto-check passed
  • A skill your agent uses when creating Zed extensions with custom slash commands, language support, themes, or MCP servers - provides Rust/WASM extension structure, slash command API…

    122 GitHub stars~3.1k tokensUpdated yesterday
    Agent WorkflowsAuto-check: notes
  • Lean Ctx Review

    yvgude/lean-ctx

    Review how the lean-ctx ctx MCP tools performed in the current session and file upstream issues for confirmed problems.

    3.9k GitHub stars~1.6k tokensUpdated today
    Agent WorkflowsAuto-check passed

More from skillsynchq/txcript

  • Release

    skillsynchq/txcript

    Cut a txcript release — dispatch the prepare-release workflow, approve the plan, watch the tag publish to crates.io, npm, and GitHub Releases, and verify.

    153 GitHub stars~775 tokensUpdated 8 days ago
    Auto-check passed
  • Corpus Check

    skillsynchq/txcript

    Validate a txcript parsing, discovery, or search change against every real agent session on this machine — old-vs-new parity, no panics, and release-build timings.

    153 GitHub stars~827 tokensUpdated 8 days ago
    Auto-check passed

Questions about Harness

What does Harness do?

Integrate a new AI coding-agent harness into txcript — native Body types, Codec, TextCodec, Store, wiring, and tests. Harness is an agent skill from skillsynchq/txcript. Integrate a new AI coding-agent harness into txcript — native Body types, Codec, TextCodec, Store, wiring, and tests.

When should I use Harness?

Harness fits situations like: integrate a new harness; transcript format.

How do I install Harness in Claude Code?

Run `npx skills add skillsynchq/txcript --skill harness -a claude-code`. Or copy the skill folder (.claude/skills/harness in skillsynchq/txcript) into .claude/skills/harness in your project. Claude Code loads it when a task matches its description.

How do I install Harness in Codex?

Run `npx skills add skillsynchq/txcript --skill harness -a codex`. Or copy the skill folder (.claude/skills/harness in skillsynchq/txcript) into .agents/skills/harness in your project. Codex loads it when a task matches its description.

Can I use Harness in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add skillsynchq/txcript --skill harness -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/harness, .gemini/skills/harness, .github/skills/harness and .opencode/skills/harness in your project.

What does Harness need to run?

Going by SKILL.md and its folder, Harness needs the command-line tools its instructions call (cargo, opencode and claude).

Does Harness access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Harness safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Harness use?

Harness is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Harness use?

About 4.2k tokens (SKILL.md is roughly 17k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 3.9k tokens, read only when the agent opens those files.

What are the alternatives to Harness?

Skills that share tags, products or a category with Harness: Webapp Builder (sidequery/sidemantic, 129 stars), Build And Profiling (pikax/verter, 112 stars), Service App Creator (Peiiii/nextclaw, 260 stars) and Nextclaw App Creator (Peiiii/nextclaw, 260 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Harness?

skillsynchq (a GitHub organization) maintains it in skillsynchq/txcript, which has 153 GitHub stars. The repository holds 3 skills in this directory. The repository was last updated on September 29, 2026.

Source: skillsynchq/txcript on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.