Skip to content

Context nodes

A context node takes a session and turns part of it into a portable text payload. That payload is how work moves between sessions without copy-paste.

Palette → nodes → context, or select messages in a transcript and extract them in place.


GlyphKindProduces
≡distilled-summaryAn AI-condensed brief of the whole transcript
❝transcript-excerptRaw conversation text, filtered
▤filesA manifest of the files the session touched

The transcript is rendered, then run through any provider CLI (default Claude) with a fixed brief: goal, current state, key decisions and why, files touched, unresolved issues, exact next steps. Markdown only. Pick provider + optional model on the context inspector.

FieldDefault
providerClaude Code
modelprovider default
extra instructionsempty. E.g. “focus on the API design decisions”

It runs as a job, so progress shows in the run log.

No model call. Just a filtered render.

FieldOptions
rolesuser · assistant (both on by default. System messages always pass)
tool callsnone · names only · full I/O
thinkingoff by default. Renders as a blockquote when on
max charsunlimited. Truncation appends […truncated]
rangemessage indices, inclusive. Cleared with clear

Set a range by selecting messages in the transcript view and extracting the selection: that drops a wired excerpt node labeled Excerpt 3–9.

A markdown table of operation | path for every file the session touched. snapshot file contents also inlines the text of written files (reads are skipped, and oversized or binary files are left as manifest rows only).


A context node is inert until it has a payload. The node subtitle says not materialized, or materialized · <first 8 of hash> once it does.

Wire a session in, open the inspector, press Materialize (Re-run to redo it). You get a token estimate chip and a preview of the payload.

During a ▶ or ≫ / CLI run, the same extract / distill / files step runs automatically when a session (or agent that emits one) is wired in. No manual press required. The resulting payloadHash is written back onto the node.

Payloads are content-addressed: the hash is sha256(kind, provider, sessionId, content) and the JSON lands under ~/.config/threadle/payloads/. Identical extracts collapse to one stored file, so re-running a deterministic excerpt is free.

Stored payloads appear in the palette’s library tab (❝) and can be dragged back onto any canvas as an already-materialized context node.


Detached / CLI / daemon jobs materialize mid-run the same way as the canvas: session or agent inbound → extract / distill / files → library payload → continue.

A context node with neither a payloadHash nor a session source is refused at readiness (wire a session source or materialize first). Library-only nodes (payload already set, no session) still work headless.

Portable graph exports deliberately strip payloadHash. A shared workflow arrives unmaterialized. The recipient wires a session (or drops a Library payload) before running.

Graph lint flags the same thing earlier: wire a session source or materialize first.


❯ Session ──▶ ❝ Context ──▶ ⟨/⟩ Agent ──▶ ⇤ Output
(extract) (inject)
  • session / subagent-run → context is the extract edge. It picks the source. The context node reads sessions, it never rewrites them.
  • context → agent prepends the payload to the agent’s prompt under a # Handed-off context heading.
  • context → session is the inject edge. During a canvas run an opencode target receives the payload as a synthetic message (inserted, no reply). Claude and Cursor targets are deliberately manual. Implicit forking would spawn a session on every run. So use the Inject button on the session node. The modal offers the modes that provider supports: resume-fork, new-session, continue, synthetic.
  • context → output is refused. Route through an agent or a converter instead.

Context edges render in their own lane color, distinct from text and session wires.