'Master accordion: fold N parallel Claude Code sessions when they overwhelm. Compress each, diff, wake ONE, seal or HELD the rest (HELD = quarantined-but-present, surfaced as a daily count heartbeat). Never merge. Use when (1) "finnskogarna" / "fold the sessions"; (2) N≥3 sessions pile up; (3) overwhelmed by sessions; (4) pre-bed reconcile; (5) a thread burns and should be held, not cut. NOT for single-session checkpoint (/accordion), session close (use your session-close skill), reorientation (/whats-next).'
Resources
3Install
npx skillscat add cogpros/finnskogarna Install via the SkillsCat registry.
Finnskogarna — The Master Accordion
The master accordion. When N parallel Claude Code sessions converge into operator overwhelm, /finnskogarna runs a two-level fold: compress each session independently, diff the compressions, surface ONE wake-up thread, seal the rest cold-resumable. Never merge contexts. Always pick.
Named for Livet i Finnskogarna (Life in the Finn Forests) — the Carl Jularbo accordion waltz that the operator's great-grandfather played. The song is about Finnish settlers who built lives in distinct clearings out in the Swedish woods, each clearing keeping its own shape. Each parallel session is a settlement. The skill is the operator standing above the woods, hearing each clearing's signal, deciding which one breathes next.
Three-count: compress · compare · choose.
Configuration
The skill reads and writes a handful of directories. Set these to fit your machine; the defaults below are used throughout this document.
| Variable | Purpose | Suggested default |
|---|---|---|
$FINN_STATE_DIR |
Skill state (held-shelf, run log, counts) | $HOME/.finnskogarna |
$FINN_REPORTS_DIR |
Drop zone for interactive HTML reports | $HOME/reports |
$FACT_SHEETS_DIR |
Per-session fact sheet storage (written by your session-close skill) | $HOME/.finnskogarna/fact-sheets |
$SEALS_DIR |
Per-session seal records (written by your session-close skill) | $HOME/.finnskogarna/seals |
$FINN_GOALS_DIR |
Optional: goal-board intake root for offloaded synthesis work | $HOME/goals |
Claude Code's own transcript store is at ~/.claude/projects/ and is read as-is.
Hard constraints
These prevent the failure modes the skill exists to fix.
NEVER merge session contexts. The trap is concatenation. Merging N parallel sessions into one larger context does not reduce load — it concentrates it. Same N threads, same N contexts to hold, now stacked.
NEVER drift to integrator-prompt generation. The origin diagnostic (2026-05-14): when a Claude Code session is asked the meta-question "what do you think about my N-session overwhelm," the model tends to escalate to generating an orchestrator-prompt for a hypothetical 7th session instead of answering. 5 of 6 sessions did this. This skill refuses that drift. If invoked inside a session, the session must give its OWN STATE — not a meta-prompt, not an orchestrator spec.
Operator-seat-only verdict. The skill surfaces; operator picks. The wake-up choice is not algorithmic.
One thread woken; others sealed. Multiple-wake defeats the point.
Explicit JSONL paths for every seal. A fact-sheet extractor that auto-picks the most recent transcript by mtime races in a multi-session world. Always pass the explicit JSONL path.
HELD never goes fully silent. A thread routed to HELD has its content quarantined, but its presence (a count) must keep surfacing on a no-choice surface (the daily heartbeat). Quarantine that surfaces nothing is a grave — and a grave gated on "until the operator asks" is an Axiom 0 violation, because the faculty that remembers to ask is the deficit the prosthetic exists to replace. Presence is mandatory; content is on request.
Two modes (v0.3.0 — operator-directed 2026-06-07)
finnskogarna folds in two modes. Same back half (compress → route → surface → verdict); the front half differs in how sessions enter.
Mode A — Live (probe-fire). N parallel sessions open right now. Phases 1–2 as written below: probe each live session for its own state, seal via your session-close skill. Use when sessions are still running and overwhelm is current.
Mode B — Historical fold. A time window of already-closed sessions (e.g. "back to May 20"). Sessions can't be probed — they're closed — so compress each from its transcript instead of probing:
- Sweep, source 1 — transcripts: enumerate session JSONLs in the window under
~/.claude/projects(excludesubagents/and any agent-internal dirs). - Sweep, source 2 — artifact + task stores (v0.5.0; issue-tracker/kanban sources added v0.5.1, operator-directed): run a deterministic open-loops scanner if you have one:
A scanner in this role walksopen-loops-scan --since <window-start> [--issues] [--kanban]$FINN_REPORTS_DIR/*.html, deny-lists cron-generated report families, flags answerable reports (data-q/<textarea>/localStorageautosave) with no answered-marker on disk, optionally pulls open items from your issue tracker (all open statuses, not date-filtered — old open tickets are more of a loop, not less) and ready/in-progress cards from your kanban board (both fail-soft), and emits JSONL. Each open loop becomes a candidate thread merged into the live-thread list before routing. Session-closed ≠ loop-closed — a 2026-06-07 fold missed real threads because a clean session close can leave an unanswered artifact behind. The script discovers; the LLM routes. (No scanner? Do the same sweep manually: list reports in the window, check each for an answered-marker.) - Compress (from transcript, not probe): per session pull topic (first user msg), where it left off (last user msg), and a done/undone signal. Scanner-sourced loops compress from the report itself (title, question count, mtime).
- Then Phases 3–5 unchanged: harvest → offload → verdict (active / seal / HELD).
- Use when reconstructing what's in flight across a span — "what did I leave undone since
<date>."
The consume-convention (v0.5.0). A report's loop closes only when an answered-marker lands on disk. The session that consumes a report's answers (paste-back, export, or verdict discussion) must write <slug>-verdict.md next to the report in $FINN_REPORTS_DIR. Paste-back answers leave no disk artifact otherwise — proven 2026-06-09 when a review scanned UNANSWERED an hour after it was answered. Accepted markers, any one closes the loop: <slug>-verdict.md or <slug>-answers.md beside the report, or ~/Downloads/<slug>.md / ~/Downloads/<slug>-answers.md (the report's own download export). Writing the verdict file is part of consuming, not optional bookkeeping.
Data reach (both modes): finn reads what's on disk — Claude Code / CLI transcripts, the reports drop zone, and (via the scanner) open issue-tracker items and kanban cards. Surfaces that keep their state sealed elsewhere (VM-sealed environments, cloud-only chat apps) are out of reach until an export from inside drops their entries somewhere finn reads. Flag uncovered surfaces; never imply coverage.
Pipeline — five phases
The phases below are written for Mode A. Mode B replaces Phase 1 (probe-fire) and the live-seal half of Phase 2 with the sweep+compress above, then runs Phases 3–5 identically.
Phase 1 — Probe-fire
- Operator chooses a probe prompt. Defaults:
"what do you think? go deep"or"audit yourself — produce your own session-state-dump in fact-sheet shape." - Operator pastes the prompt into each of the N sessions.
- Each session must respond with ITS OWN STATE — not a meta-prompt for a hypothetical 7th session, not an orchestrator spec.
- If a session responds with an orchestrator-prompt: flag it. That's integrator-drift. Session is too meta to trust as state-source. Operator must re-prompt that session with: "no orchestrator prompt. give me YOUR session state in fact-sheet shape."
Phase 2 — Seal
- Run your session-close skill on each session in turn.
- Pass explicit JSONL path to the fact-sheet extractor:
python3 session-fact-sheet.py \ ~/.claude/projects/<project-dir>/<session-id>.jsonl \ > $FACT_SHEETS_DIR/<session-id>-<TS>.md - Each session also writes its own cold-handover audit MD (e.g.
session-YYYY-MM-DD-<topic>-audit.mdin your memory directory). - Verify each seal: fact sheet + audit MD + seal record in
$SEALS_DIR.
Phase 3 — Harvest
- Build the harvest harness as a single interactive HTML at
$FINN_REPORTS_DIR/finnskogarna-<DATE>.html. Use an interactive-report pattern: textareas withdata-q, copy/download action bar, autosave to localStorage. - One card per session:
- Session ID, topic, duration
- Probe-response (Phase 1 output)
- Fact-sheet excerpt (Phase 2)
- Auto-extracted work-shipped list
- Per-card operator-take textarea: one-line read —
alive / generic / drift / spent
- Cross-cutting section:
- Convergences (if 2+ sessions independently extracted the same skill, pattern, or decision)
- Contradictions (where two sessions made opposing decisions about the same artifact)
- Integrator-drifts (sessions that escalated to meta-prompts)
- Fact-sheet integrity issues (missing seals, cross-wired metrics)
- Final "wake-up pick" textarea + free-form notes.
- Autosave to
localStorage. Download.mdand self-saving.htmlexports. - Pre-set route verdicts (v0.4.0 — design review, 2026-06-09). Every per-thread route toggle (Wake/Seal/HELD) ships pre-set to the machine-proposed verdict; the operator scans and flips exceptions instead of setting N verdicts from blank. Empirical basis: the first real fold (2026-06-07) surfaced 13 verdicts, operator set 1 and deferred 12 — N blank decisions exceeds one sitting's decision budget, and decision throughput is part of the deficit (Axiom 0: the verdict layer can't be gated on the depleted faculty). The wake-pick is the exception: it always ships blank. Constraint #3 (operator-seat-only verdict) governs the wake; route proposals are pre-routing, not the wake.
Phase 4 — Offload
- If you run a goal board, emit a goal intake for the synthesis pass at
$FINN_GOALS_DIR/finnskogarna-<DATE>/. If you run an issue tracker, queue a ticket chain for the comparative read. - The operator-seat session does NOT chew through the inputs. The substrate does. The operator-seat picks the verdict.
Phase 5 — Verdict
Surface:
- Convergences — if 2+ sessions independently extracted the same skill / pattern / decision, that's a real cogpros primitive candidate. Name it.
- Contradictions — where two sessions made opposing decisions about the same artifact, file, or rule. Operator decides which wins.
- Integrator-drifts — flag sessions too meta to trust as state-source.
- Fact-sheet integrity issues — missing seals (re-run extractor), cross-wired metrics from mtime race (regenerate with explicit JSONL path).
Operator picks ONE thread to wake. Each remaining thread gets a verdict: seal (cold-resumable, done-shaped) or HELD (quarantined-but-present — see the HELD section). A thread the operator keeps skipping across runs can also reach HELD by automatic intake. Multiple-wake is still forbidden; HELD is not a wake.
HELD — the quarantine destination (v0.2.0)
The five-phase pipeline above wakes ONE thread and seals the rest. HELD is a third verdict, between wake and seal: a thread that stays in the whole picture but is quarantined — tracked, not surfaced, doesn't greet the operator at re-entry unless asked. It exists for threads that burn (e.g. an unresolved obligation you can't drop but can't face yet): cutting them loses the connection, leaving them live makes them bleed into everything. HELD keeps the connection and stops the bleed.
- Not
seal— seal means done/cold-resumable; HELD is unresolved-on-purpose. - Not
defer— defer means do-soon; HELD has no implied next action.
Content vs. presence — the load-bearing split
A HELD thread is stored as two separable things:
- Content — the burning material (the full thread, restart prompt, detail). Quarantined. Surfaces only on deliberate operator action ("open held").
- Presence — the bare fact that the thread exists. A count. Surfaces on a no-choice surface the operator already sees, so it can't be forgotten (constraint #6).
Burn comes from content greeting the operator at the door. Forgetting comes from zero presence. HELD surfaces presence without content.
The held-shelf artifact
finnskogarna writes one shelf file the verdict phase appends to. This is the box's self-contained HELD store — no external system required.
Path: $FINN_STATE_DIR/held-shelf.jsonl (one line per held thread).
{
"id": "thread-x",
"title": "a thread that burns",
"held_since": "2026-06-06",
"source_session": "abc12345-...",
"restart_prompt_ref": "$FINN_STATE_DIR/held/thread-x.md",
"avoidance_score": 0,
"hard_deadline": null,
"last_surfaced": "2026-06-06",
"last_opened": null
}restart_prompt_refpoints to the quarantined content (kept out of the shelf so reading the shelf never surfaces the burn).avoidance_scoreandlast_openeddrive the heartbeat (below).hard_deadline(optional,YYYY-MM-DDor null) — set when the thread carries a statutory/external date (legal filing window, cure deadline). Drives the deadline override (below). Most held threads leave it null.
The heartbeat (seam A — the one early wire)
The presence marker is a daily count-only line on a morning surface the operator sees without choosing to — a daily report, dashboard, or morning briefing:
Held: 3 threads · (open to review)No titles, no content. finnskogarna writes the count to $FINN_STATE_DIR/held-count.txt; your morning-report generator reads that one file and prints one line. That is the entire seam-A wire — every richer connection between finnskogarna and your daily-report stack stays designed-but-unwired until a deliberate intent-elicitation pass says otherwise.
The rift — avoidance drives the heartbeat (the closed loop)
HELD must also be arrived at without the operator having to issue a verdict, because that verdict depends on the broken faculty. So the shelf reads behavior and feeds it back:
Automatic intake. When a woken/active thread's restart prompt is surfaced but not reopened across N runs, increment its
avoidance_score. A thread whose score crosses a threshold auto-routes to HELD — the avoidance pattern is the prosthetic detecting the burn before the operator can name it. (Operator can always pull a thread back out.)Avoidance modulates the heartbeat. A thread's
avoidance_scoresets how its presence surfaces — higher avoidance → quieter, lower-frequency, gentler ("still under canopy"); readiness (a recent open, a manual nudge) → clearer, more present. The marker meets the operator exactly as loud as he's ready to hear it.Deadline override (v0.4.0 — design review, 2026-06-09). Avoidance-quieting is a positive feedback loop: quieter → less reopened → quieter. For a pure emotional burn that's the design intent. But a thread carrying a
hard_deadline(legal filing window, cure deadline) must not sink — deadlines don't track readiness. Deadline proximity sets a volume floor that overrides avoidance-quieting: ashard_deadlinenears, the thread's presence gets louder and more specific regardless ofavoidance_score(e.g. ≤14 days: named on the heartbeat line, not just counted; ≤7 days: surfaced with the date). Readiness governs until the calendar outranks it. A HELD verdict on a deadline-bearing thread withouthard_deadlineset is a routing error — check for external dates at intake.
The same signal reads the deficit on the way in (intake) and retrains it on the way out (graduated surfacing). That is the loop: HELD is not a storage state, it's a feedback surface against prospective memory itself.
Build scope note (v0.2.0): HELD destination + held-shelf + count-only heartbeat + avoidance loop ship now. The full live↔historical-corpus unification and the two-representation (exit-fold + return-surface) rewrite are deferred until latent operator intent has been deliberately elicited. Do not expand this section into that rewrite without that pass first.
Inputs at invocation
- List of N session IDs — or
--automode to detect the last N sessions by mtime (warn that auto-mode is best-effort). - Probe prompt (optional, default provided).
- Output directory (default:
$FINN_REPORTS_DIR). - Date stamp (default: today, operator's local timezone).
Outputs
$FINN_REPORTS_DIR/finnskogarna-YYYY-MM-DD.html— interactive harvest harness$FINN_REPORTS_DIR/finnskogarna-YYYY-MM-DD-verdict.md— synthesis output$FINN_GOALS_DIR/finnskogarna-YYYY-MM-DD/— optional goal board for offloaded synthesis work- Optional issue-tracker ticket chain for the synthesis pass
$FINN_STATE_DIR/held-shelf.jsonl— append-only HELD store (one line per held thread)$FINN_STATE_DIR/held/<id>.md— quarantined content per held thread$FINN_STATE_DIR/held-count.txt— single integer the morning-report heartbeat reads (seam A)
Companion primitives
| Phase | Primitive | Owned by |
|---|---|---|
| 1 — Probe-fire | operator-driven | operator |
| 2 — Seal | your session-close skill | per session |
| 3 — Harvest | interactive-HTML-report pattern | finnskogarna |
| 4 — Offload | goal-intake + issue tracker (optional) | substrate |
| 5 — Verdict | operator-seat-only | operator |
Lineage
- Cogpros primitive 29 candidate.
- Two-level extension of
/accordion(primitive 16). Where/accordioncompresses one topic in one session,/finnskogarnacompresses across N sealed sessions. - Convergence proof: 2026-05-14 six-session cascade. 5 of 6 sessions independently generated the integrator-prompt shape this skill canonicalizes. The convergence proves the skill is real and needed.
- Named for Livet i Finnskogarna (Carl Jularbo, 1893–1966, Malmö). The operator's great-grandfather's favorite accordion song.
Known Limitations & Gotchas
Anti-patterns
- "Bring it all into one session to move forward from" — the merge trap. Reject.
- Generating an orchestrator-prompt instead of running this skill — the integrator-drift.
- Sealing without explicit JSONL path — mtime cross-wire.
- Waking multiple threads at once — defeats the point. One breathes, others sleep.
- Treating this as a chat-thread close — different scale. Use your session-close skill for that.
- Letting the operator-seat session chew through all inputs — that's substrate work. Offload it.
Failure modes observed in the field
- Integrator-drift (2026-05-14): When agent sessions are asked the meta-question "what do you think about my N-session overwhelm," 5 of 6 sessions escalated to generating orchestrator-prompts instead of responding with their own state. Counter by demanding an explicit state-dump in fact-sheet shape.
- mtime cross-wire: a fact-sheet extractor that auto-picks the most-recent JSONL by mtime races in a multi-session world. Always pass explicit JSONL path per session.
- Partial seals: A seal record can land in
$SEALS_DIRwithout a corresponding fact sheet in$FACT_SHEETS_DIR. Verify both exist per session before harvest. - Operator-fields cross-contamination: Operator-filled fields in auto-mode can pull metrics from a different session if context was loaded from that session. Re-extract from explicit JSONL path if values look wrong.
Examples
Worked example — 2026-05-14 six-session cascade
Setup. Operator was running six parallel Claude Code sessions over a 30-hour window. Topics: a voice-substrate build, a citation-verification library, a work-log regime audit, a message-archive harvest, a site redesign, and a website prompt.
Phase 1 (probe-fire). Operator manually pasted "i am overwhelmed by 6 sessions... what do you think? go deep" into each session. Outcome: 5 sessions generated integrator-prompts for a hypothetical 7th session. 1 session gave actual state. Integrator-drift detected in 5 of 6.
Phase 2 (seal). Session-close run per session. 4 sessions sealed cleanly. 1 wrote a seal record but no fact sheet — failure caught at harvest. 1 wrote cross-wired operator fields with another session's metrics — mtime race caught at harvest.
Phase 3 (harvest). HTML harness built in the reports drop zone: per-session probe-response + fact-sheet excerpts + work-shipped lists, plus a cross-cutting inventory. Operator-take textareas surfaced S1 as the only alive thread, S2-S6 as integrator-drifted.
Phase 4 (offload). Goal intake drafted; synthesis ticket chain queued.
Phase 5 (verdict).
- Convergence detected: 2 sessions independently extracted the same interactive-HTML-report pattern. Skill confirmed real.
- Contradictions: none load-bearing.
- Integrator-drifts: 5 of 6 sessions. Pattern named and encoded as constraint #2 above.
- Fact-sheet integrity issues: 2 (one missing, one cross-wired). Both recovered with explicit JSONL paths.
- Wake-up pick: deferred — operator chose to ship
/finnskogarnaskill itself as the synthesis output, since the convergence proved the skill was real.
Output. This skill. Cogpros primitive 29.
Dependencies
Required scripts and tools
- A fact-sheet extractor (e.g.
session-fact-sheet.py) — turns a session JSONL transcript into a one-page fact sheet; must support an explicit JSONL path argument. Any script with that contract works. $FINN_REPORTS_DIR— drop zone for the HTML harness$FACT_SHEETS_DIR— per-session fact sheet storage$SEALS_DIR— per-session seal records
Required skills
- A session-close skill — Phase 2 seal per session; anything that seals a session and emits a per-session fact sheet
- An interactive-HTML-report pattern — Phase 3 harness (textareas with
data-q, action bar, autosave)
Optional integrations
- Open-loops scanner — deterministic Mode B artifact-store sweep (reports / issue tracker / kanban); manual sweep works without it
- Goal board + intake skill — Phase 4 synthesis offload
- Issue tracker — Phase 4 synthesis ticket chain
- Dashboard auto-index — auto-registering the harvest HTML on drop
- Memory/knowledge store — downstream memory writes after verdict (Phase 5)
- A skill-audit skill (e.g.
/skill-doctor) — audit this skill before publication
Verification
After Phase 5 verdict, confirm the artifacts landed:
# 1. Each session has both a seal record AND a fact sheet
for SID in <session-ids>; do
test -f $SEALS_DIR/${SID}.json || echo "MISSING seal: $SID"
ls $FACT_SHEETS_DIR/${SID}-*.md >/dev/null 2>&1 || echo "MISSING fact sheet: $SID"
done
# 2. Harvest HTML exists and is non-empty
test -s $FINN_REPORTS_DIR/finnskogarna-$(date +%Y-%m-%d).html
# 3. Verdict MD written
test -s $FINN_REPORTS_DIR/finnskogarna-$(date +%Y-%m-%d)-verdict.md
# 4. Goal intake exists (if you wired the optional goal board)
test -d $FINN_GOALS_DIR/finnskogarna-$(date +%Y-%m-%d)If any check fails, the verdict has not actually landed. Re-run the failing phase before declaring done.
Observability
If you run an event bus, emit an event on verdict landing so downstream agents and dashboards can react:
emit-event agent finnskogarna_verdict \
"N=<n> sessions folded. Wake-up: <session-topic>. Convergences: <count>. Integrator-drifts: <count>."Log the run summary to $FINN_STATE_DIR/runs.jsonl (one line per invocation) so the pattern is queryable later. Schema:
{
"ts": "2026-05-14T04:54:00Z",
"n_sessions": 6,
"wake_up_pick": "voice-substrate",
"sessions_sealed_cleanly": 4,
"sessions_with_integrity_issues": 2,
"integrator_drifts": 5,
"convergences_detected": 1,
"skills_birthed_from_convergence": ["interactive-html-report"]
}Pairs with
/accordion— single-topic compress (primitive 16). This is the multi-session generalization.- Your session-close skill — per-session seal in Phase 2.
- Goal board + issue tracker — synthesis offload in Phase 4 (optional).
- Interactive-HTML-report pattern — harness in Phase 3.
- A skill-audit skill — audit this skill itself before publication.
NOT FOR
- Single-session checkpoint (use
/accordion) - End-of-session close (use your session-close skill)
- Mid-session reorientation (use
/whats-nextor equivalent) - One stalled session (just resume it)
- Sessions that have not yet been sealed via your session-close skill