Parsica Weave
Installs as theparsica-weave Claude Code plugin; Parsica Weave is the product name.
A mini-Parsica for the harness. Claude Code already persists the full chat to a
transcript JSONL; this skill chunks it, enriches it (deterministic tags), scrubs
it (credentials/PII), and re-injects the right pieces at the right moments. The
philosophy is retrieval over dumping: granular, tagged, provenance-stamped
recall beats re-reading history.
First time living on this system? Read ONBOARDING.md before this reference:
it carries the retrieval habit that makes everything below worth having.
The vocabulary
- Workspace - the entire Claude Code presence. The top-level container; the store.
- Project - one repo, keyed by its git root. Scopes the focus, never the self.
- Channel - a named lane of sessions (workspace-level registry).
- Session - one live conversation. The only boundary for live context.
The three layers
- Enriched chat mirror (
<ws>/mirror/<project-key>/<date>.<pid>.jsonl- one shard per writing window, so concurrent windows never share an append target; legacy<date>.jsonlfiles stay readable) - every turn, chunked and tagged (files touched, commands run, tools used, skill attribution, timestamp, session). Scrubbed before write. Retained by active days per calendar date (default 14 - quiet days don’t age out a project); older shards rotate toarchive/, never deleted. This is what you query. - Working set (
<ws>/working/<project-key> - Working Set.md) - PINNED FACTS (durable, never let them drift) + OPEN LOOPS (the live thread list), per project. You maintain this. It is re-injected at every SessionStart in that project - the part that survives everything. - Permanent journal + lessons (
<ws>/journal/<date>.md,<ws>/lessons.md) - the daily summary and your self-authored scars (lessons learned, re-read at boot, never auto-pruned). Workspace-level: one journal and one lessons file for every project you work in, each appended entry stamped(YYYY-MM-DD HH:MM UTC · session <sess8> · <project-key>). Journal pages past the active window (default 7 days) rotate tojournal/archive/; nothing is deleted.
<ws> = ~/.claude/parsica-weave/, one workspace for everything. Projects key on
the git root, so any subdirectory of a repo resolves to the same project.
Your responsibilities (the discipline)
The hooks do the capture; you keep the human-judgment layers sharp. Never edit the working set,lessons.md, or the journal directly - always pipe your content through the
note wrapper, which scrubs it for credentials/PII before it lands on disk. Hand-editing
these files bypasses the safety layer and writes a pasted secret straight to disk.
journal and lesson appends are stamped with time, session, and project; pass
--sess <sess8> so the stamp names your session (the checkpoint directive embeds it).
- Maintain the working set (pinned facts + OPEN LOOPS). When the branch, posture, a key
decision, or a hard constraint changes - or when you start/finish a thread - refresh it. Keep
it terse and true; stale pinned facts are worse than none. Pipe the full refreshed doc
(the wrapper replaces it in place):
- Write lessons (scars). When you hit a wall, get something wrong, or learn something
load-bearing, record a dated entry - what happened + the rule learned, one scar per entry.
This is what feeds judgment over time:
- Keep a journal. At each ~20-turn checkpoint (the hook prompts you), record a tight
~150-word entry - key decisions, current task/phase, open threads, next step:
Retrieving (retrieval-first)
Don’t re-read history - query the mirror. Run from the project dir:--workspace searches every project’s mirror; --archive folds in rotated
shards. Prefer pulling the relevant 2-3 chunks over reloading the whole conversation.
Enriching the mirror (semantic layer)
The mirror captures each turn deterministically (text + files/commands/tools). On top of that, add a semantic overlay so retrieval matches how a person actually searches - the difference between “I tagged the files” and “I can find the turn by what it was about.” When: at each ~20-turn checkpoint (the directive reminds you). The checkpoint way is autonomous: do NOT hand-author overlays - spawn the background enrichment swarm via the Workflow tool (seeAUTONOMOUS_ENRICHMENT.md) and let it work the pending queue. Enrich
in passes, never per turn.
How (the manual fallback, for when the swarm is unavailable):
python "${CLAUDE_PLUGIN_ROOT}/scripts/enrich.py" --list-pending-> chunks needing enrichment (id + text). Enrich from the returned chunk text - the stored, already-scrubbed record - not from raw session recall, so the overlay stays faithful to what was captured and cannot reintroduce content the capture scrub removed.- For each chunk, produce this JSON:
- Persist by piping the
{chunk_id: {...}}map through stdin - never write raw enrichment JSON to a workspace temp file (that’s an un-scrubbed disk surface):It scrubs the output, adds deterministic categories, stamps the spec version, and writes it in place.
- topic - 5-10 concept tags, lowercase snake_case. Tag the concept and its synonyms,
not just the literal token:
authenticationfor a JWT change,deploymentfor Kubernetes,cost_trackingfor a billing fix. Breadth over depth. - summary - one sentence that rephrases the turn in different vocabulary (adds search surface, doesn’t echo the text). Not a truncation.
- keywords - 8-15 phrases the way a person would actually type them into search.
- search_queries - 3 SPECIFIC questions that only this turn answers; embed the exact names (functions, files, decisions). Discriminative - they should NOT match a hundred other turns. This is the highest-leverage field for retrieval.
- facts - 1-5 atomic, standalone statements, or
[]. - Put any exact proper noun somewhere in
topicORsearch_queries.
decisions with your conviction-at-creation - value (0-1, how strongly
this should shape future behavior), domain, why, and would_weaken_if. This is your
authentic first-person signal, captured once and never overwritten on re-enrichment.
Later, when a decision proves out or fails, record it against its did (visible in the
stored overlay / query.py --full):
enrich.py scrubs every field before storage as defense-in-depth.
Safety
Everything is scrubbed before storage - credentials (key prefixes, PEM blocks, assignment-style secrets) always; PII (emails, phones, SSNs, cards) by default (configurable). Entropy-based redaction is deliberately off so git SHAs, file hashes, and version strings survive intact. Never paste a raw secret into the working set /lessons.md / the journal - but if one slips through, the
SessionStart re-inject is scrubbed again as defense-in-depth. Every producer (mirror,
notes, enrichment, calibration) reaches disk through a single write gateway in store.py,
so scrubbing happens by construction, not by each caller remembering to call it.
Refusal list (your own terms). Beyond the automatic secret/PII scrub, set refusal in config
to a list of words or phrases to fence: "refusal": ["ProjectX", "internal codename"]. Every match
renders as <redacted>, at two scopes: write-time scrub (capture, the note wrapper, enrichment
overlays, the calibration ledger) applies the union of the global and current-project refusal
lists; every OUTPUT sink (the SessionStart re-inject, hook injections, and all CLI output) applies
the workspace-wide union of every project’s refusal terms, so a term configured anywhere in the
workspace never surfaces anywhere. Matching is
case-insensitive and by SUBSTRING, so a term is caught anywhere it appears, including welded into a
word (media_ProjectX, codenamedProjectX, ProjectXClient). This deliberately over-redacts
(refuse mars and marsupial also goes) on the principle that a secrecy fence must never leak a
listed term; choose specific terms to limit collateral. This keeps capture running through
sensitive work with your terms held out, instead of skipping continuity entirely.
Configuration
~/.claude/parsica-weave/config.json (global) or
<ws>/projects/<project-key>/config.json (per-project override). Keys:
mirror_active_days (default 14; older shards rotate
to archive/), journal_active_days (7), checkpoint_every_n (20, per session),
scrub_pii (true), max_inject_bytes (12000), refusal (a list of your own
words/phrases to redact; see Safety), boot_recent_elsewhere (false; see below), and
agent_name + byline - set through their front door, the identity verb:
parsica-weave name --name <name> (show: bare name; states: --byline on|name-only|off;
clear: --reset; one name per workspace, config-only, never a store key). When a name is
set, open every response with [Name · <session-tag>] - the chosen name, visible on every
reply; byline_session_tag: false for name-only.
By default, Weave keeps live boot context project-scoped. The same agent can query
workspace memory on demand, but other projects’ recent live work is not automatically
injected. Set boot_recent_elsewhere=true to enable a small “Recent elsewhere” block at
SessionStart: a recap of recently captured turns from your other sessions (not awareness of
anything live - a recap of the recent past). Even enabled, it
is a snapshot, not a stream: a one-time boot digest of already-captured, already-scrubbed
chunks, never another session’s live context. Weave has no mode that shares a session’s live
window across projects. The on-demand capability (query.py --recent N) stays available
regardless of this setting.
Channels: the PARSICA_CHANNEL env var names the session’s lane; the registry is
workspace-level, chunks tag with an immutable channel id. Catch-up is deliberate:
pcx.py sync --hours N digests the whole workspace; registry: pcx.py channel --list.
PARSICA_ISOLATED=1 runs a zero-footprint session: full recall, nothing durable
written; every standalone writer refuses (note/promote/migrate, calibrate
event recording, and the enrichment pipeline enrich/enrich_prep/enrich_apply),
and query federation neither mints workspace identity nor emits a router trace. See
README.md for install + hook wiring.