agentleFS
tandregbgtandregbg/core-claude-skills/skills/insights/SKILL.md

insights

Skill4 starsChanged 11 days agoMITView on GitHub

Knowledge extraction manager and skill evolution engine. Backfills _insights.yaml from historical corpus, compiles execution feedback into patterns, and proposes SKILL.md improvements.

14 other projects use a version of this.

Adopted by

Most recently taken up by

The file

Show its rules and text

We split this skill into the rules it gives an agent

32 rules. 0 are common, 6 are distinctive, and 26 are very specific to this project.

  • 0

    Common

    Most of the 8 edited versions we read keep these.

  • 6

    Distinctive

    This author's own choices. Worth a look.

  • 26

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Additive only: Never removes or modifies existing insights (except scan-claude-md which replaces stale CLAUDE.md-sourced entries, and the …

    line 18
  2. Very specific:

    Demotion: when a correction entry contradicts a rule (same primary tag, opposing summary keyword), the rule's confidence flips back to …

    line 35
  3. Very specific:

    If enabled: false, all subcommands exit immediately with a message.

    line 143
  4. Distinctive:

    If folder path: resolve to that single folder (must contain CHANGELOG.md)

    line 161
  5. Very specific:

    If all: scan vault recursively for all folders containing CHANGELOG.md (max depth 6, skip .archive/, .handoff/, clones/)

    line 162
  6. Very specific:

    If since YYMMDD: same as all, but with date filter applied in step 4

    line 163
  7. Very specific:

    Build dedup set: If _insights.yaml exists, load it and collect all source.file values into a set

    line 167
  8. Very specific:

    If since YYMMDD target: additionally skip files whose filename date prefix is before the given date

    line 172
  9. Distinctive:

    Read the file content

    line 177
  10. Very specific:

    If file exists: add new entries inside insights:, before the top-level next_id key, then update next_id and last_updated.

    line 196
  11. Very specific:

    If file does not exist: create with version: 2, context set from folder name or CHANGELOG context

    line 197
  12. Distinctive:

    All files already processed (dedup)

    line 212
  13. Very specific:

    If _insights.yaml already has entries with source.file: "CLAUDE.md" AND the CLAUDE.md file has not been modified since last_updated in the …

    line 228
  14. Very specific:

    If CLAUDE.md is newer: remove all existing source.file: "CLAUDE.md" entries from _insights.yaml (preserving transcript-sourced insights), …

    line 229
  15. Very specific:

    Filter by date: if since YYMMDD is specified

    line 365
  16. Distinctive:

    Split before promoting (CR-098): When a candidate group turns out to hold two or more distinct claims, split it and apply the threshold to …

    line 442
  17. Distinctive:

    Why not a word-overlap threshold: before CR-094 this step required ≥60 % token overlap.

    line 449
  18. Very specific:

    Dedup: if the canonical entry already has confidence: rule, only append new (not-already-listed) confirmations and update …

    line 491
  19. Very specific:

    Never touch entry content (summary/rationale text) -- structure and vocabulary only.

    line 585
  20. Very specific:

    Write the judgement as a plan file (entries: {id: {type, voice, confidence}}, confirmations: {id: {source: voice}}) in the session's …

    line 601
  21. Very specific:

    Add a one-line CHANGELOG entry in the folder (- YYMMDD: Migrate _insights.yaml to the podcast profile -- N entries retyped, M voiced …

    line 612
  22. Very specific:

    Load the corpus: every _insights.yaml (skip .archive/, .transcripts/, .handoff/, clones/), entries with status: active.

    line 632
  23. Very specific:

    Verticals boundary: if the topic matches a registered workflows.verticals doc, the article LINKS to the vertical for org-operational state …

    line 639
  24. Very specific:

    If false (default): save proposal file, report to user

    line 701
  25. Very specific:

    If true: apply the change to SKILL.md directly, log in CHANGELOG with [AUTO-EVOLUTION] tag, save proposal as record

    line 702
  26. Very specific:

    If specific file: Read the proposal, apply the change to the target SKILL.md

    line 742
  27. Very specific:

    metric vs learning (CR-046): remove the number from the summary.

    line 837
  28. Very specific:

    Threshold: Only non-obvious, durable, specific insights.

    line 839
  29. Very specific:

    Before writing any entry, apply the write-time vocabulary guard defined in /transcript Step 3.5: canonical type values only, confidence …

    line 857
  30. Very specific:

    When processing Swedish-language content, ALL Swedish words MUST use correct å, ä, ö characters.

    line 861
  31. Very specific:

    Before writing any entry to _insights.yaml where the summary, rationale, or context field is in Swedish (detected by presence of any å/ä/ö …

    line 865
  32. Distinctive:

    If no violations, proceed with the write

    line 872

“Common” is measured: kept by at least 6 in 10 of the 8 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Insights Skill -- Knowledge Extraction & Skill Evolution

Extract and backfill durable insights from existing transcripts and CLAUDE.md files into _insights.yaml. Compile execution feedback (edge cases, corrections) into patterns and propose SKILL.md improvements.

This skill complements the forward-looking extraction in /transcript Step 3.5 and /ops Step 5.5 by processing the historical corpus and closing the feedback loop.

Design Principles

  • No duplication of extraction logic. The authoritative definition of insight types, thresholds, and _insights.yaml format lives in /transcript Step 3.5. This skill references it and includes a quick-reference copy for convenience.
  • Dedup by source.file. Processing the same file twice never creates duplicate entries.
  • Additive only. Never removes or modifies existing insights (except scan-claude-md which replaces stale CLAUDE.md-sourced entries, and the promotion/demotion passes in compile which mutate confidence, confirmation_count, status, and superseded_by fields per CR-013).
  • Silent accumulation, active loading. Insights are written by /transcript, /ops, and this skill. Promoted rules (per CR-013 lifecycle below) are read back by /ops and /transcript as a context preamble before each run. Hypotheses remain silent; only rules surface. Consensus (CR-123) never surfaces as an instruction either: it is knowledge, shown by status and synthesize, never loaded.
  • Profiles (CR-123). Which types exist, which are promotable, how confirmations are counted and what a promotion produces come from the folder's resolved profile (skills/ops-config/profiles.py). Without profile: everything below is the meeting behaviour, unchanged.

Confidence Lifecycle (CR-013)

Each insight has an optional confidence field:

  • hypothesis (default when absent) — observation that needs more confirmation. Not loaded into other skills' context.
  • rule — confirmed pattern. Loaded as a preamble by /ops and /transcript when working in the rule's folder chain.
  • consensus (CR-123, profiles with promotes_to: consensus, i.e. podcast) — a claim confirmed by at least consensus_threshold (default 3) independent voices and contradicted by none. Never loaded into any skill's context: a recurring claim among guests is knowledge about the conversation, not an instruction to the assistant. A reader that does not know the value reads it as hypothesis, never as rule.

Two lifecycle transitions, both performed by /insights compile:

  • Promotion: when ≥ compile_threshold (default 3) semantically similar hypothesis entries exist in one folder, the canonical (earliest) entry is promoted to confidence: rule. Non-canonical entries are marked status: superseded, superseded_by: <canonical-id>. The canonical entry's confirmation_count is set to the number of distinct dates in the group (CR-098) and confirmations[] is populated with each merged entry's source. A person's review recorded in promotion_review (CR-100) is honoured, but never replaces the contradiction check.
  • Demotion: when a correction entry contradicts a rule (same primary tag, opposing summary keyword), the rule's confidence flips back to hypothesis, the correction's source is appended to contradicted_by[], and confirmation_count is reduced by 1 (floor 1).

Under a consensus profile (CR-123) the promotion pass works per entry, not per group: an entry reaches consensus when independent_count >= consensus_threshold, contradicted_by is empty, its type is in the profile's promotable_types (never quote) and it is active. A point only the owner voice (the host) raised can never reach it, however often: the host chooses the guests. So under the podcast profile consensus means recurring among guests, not generally accepted. When a contradiction arrives later, or a recount falls below the threshold, the entry goes back to hypothesis (the script lists it under consensus_stale).

confidence and status are orthogonal:

  • status (active / superseded / archived) is the curation/archival lifecycle.
  • confidence (hypothesis / rule / consensus) is the maturity lifecycle.

A rule can be archived. A hypothesis can be superseded by a more specific hypothesis. Both fields coexist.

Schema fields added in v2 (all optional, additive):

confidence: hypothesis | rule       # default: hypothesis
confirmation_count: 1                # integer, default 1
confirmations:                       # list, populated on promotion
  - source: <relative-path>
    date: YYMMDD
contradicted_by:                     # list, populated on demotion
  - source: <relative-path>
    date: YYMMDD

Insights schema 3 (CR-123, all optional, additive). v1/v2 readers ignore the new fields.

voice: guest                         # who raised it in the SOURCE unit: one of the profile's voices
independent_count: 3                 # distinct units where a voice other than owner_voice raised it
owner_count: 1                       # distinct units where owner_voice raised it
confirmations:
  - source: <relative-path>
    date: YYMMDD
    voice: guest                     # who raised it in that unit
    note: "one line: how this unit said it"
original_date: YYMMDD                # the unit's Originally published date, when it has one
themes: [T07]                        # CR-124, projects with themes enabled
confidence: consensus                # third value; never loaded as an instruction

Counting rules:

  • Units, not dates, under count_by: unit. confirmation_count, independent_count and owner_count count distinct source units, the origin included. Re-published back-catalogue material and same-day live or bonus episodes share a publication date; counting dates (CR-098) would collapse them into one confirmation. The meeting profile keeps count_by: date.
  • both counts for both counts. A sighting with no voice counts for neither, and is reported as unlabelled until a voice is set.
  • A confirmation never extends rationale (every profile): it adds an item with its own one-line note. Appended clauses turned rationales into logs of over a thousand characters.
  • Voice labels are a model's judgement from the summary and transcript. Where a confirmation is a paraphrase that cannot be placed, the writer uses both, so owner voice is probably undercounted; treat the split between voices as indicative.

promotion_review (CR-100, optional, additive). A person's judgement of a candidate group, recorded on the group's canonical (earliest) entry by a review surface. It is an observation -- this group was judged, on this date -- not a lifecycle transition: only compile writes confidence.

promotion_review:
  decision: approved          # approved | rejected
  date: YYMMDD
  by: dashboard               # which surface recorded it
  group: [12, 47, 83]         # the entry ids judged together, canonical first
  group_key: <sha256>         # from promotion_candidates.py at review time
  split_from: <sha256>        # only when `group` is a subset: the key of the group it was split from
  reason: null                # required when rejected: topic-only tags | contradiction |
                              #   not a standing instruction | split | other: <text>

The group key is computed by skills/insights/promotion_candidates.py (recipe in its docstring). Any change to a judged entry, or a member added to the group, changes the key and makes the review stale. The block stays on the canonical after promotion as the record of who approved it.


String Resolution

Template strings marked as {strings.section.key} are resolved at runtime.

Resolution order:

  1. Config strings section (if loaded)
  2. Language-matched defaults from base.yaml:
    • swedish -> strings_sv
    • english -> strings
    • input -> match detected transcript language
  3. Hardcoded strings already in template (fallback)

Configuration

Reads workflows.knowledge_extraction from base.yaml (or config override):

KeyDefaultDescription
enabledtrueMaster switch for extraction
min_insights1Minimum qualifying insights to write file
types[decision, preference, learning, opportunity, pattern]Insight types to extract
max_per_meeting10Cap per source file

If enabled: false, all subcommands exit immediately with a message.


Subcommands

reprocess [target] -- Extract insights from existing transcripts

Trigger: /insights reprocess <target>

Targets (all three supported):

  • Folder path: /insights reprocess _contacts/bob-smith or /insights reprocess _projects/acme/meetings/management
  • all: /insights reprocess all -- all folders containing a CHANGELOG.md
  • since YYMMDD: /insights reprocess since 260201 -- only files dated after the given date, across all folders with CHANGELOG.md

Steps:

  1. Resolve target folders:
    • If folder path: resolve to that single folder (must contain CHANGELOG.md)
    • If all: scan vault recursively for all folders containing CHANGELOG.md (max depth 6, skip .archive/, .handoff/, clones/)
    • If since YYMMDD: same as all, but with date filter applied in step 4
  2. For each target folder, list YYMMDD-*.md files (transcript files matching the 6-digit date prefix pattern)
  3. Build dedup set: If _insights.yaml exists, load it and collect all source.file values into a set
  4. Filter files:
    • Skip files already in the dedup set (already processed)
    • Skip standup files: filename contains standup or daily-standup, OR file is <500 words with no qualifying insights
    • If since YYMMDD target: additionally skip files whose filename date prefix is before the given date
  5. Sort remaining files chronologically (oldest first, for consistent ID ordering)
  6. Process each file:
    • Read the file content
    • Apply the same extraction logic as /transcript Step 3.5:
      • Scan for decisions with rationale, stated preferences, learnings, opportunities, and patterns
      • Apply threshold: only non-obvious, durable, specific insights
      • Respect max_per_meeting cap
      • Respect configured types list
    • For each qualifying insight, create an entry with:
      • id: next available ID (from next_id in existing file, or starting at 1)
      • type: one of the configured types
      • date: extracted from the filename prefix (YYMMDD)
      • summary: one sentence
      • rationale: one sentence context
      • source.file: the transcript filename
      • source.section: the section heading where the insight was found
      • tags: max 5 keywords
      • status: active
      • superseded_by: null
  7. Write/append to _insights.yaml in the same folder as the CHANGELOG.md:
    • If file exists: add new entries inside insights:, before the top-level next_id key, then update next_id and last_updated; re-read and confirm they landed in the list (CR-096)
    • If file does not exist: create with version: 2, context set from folder name or CHANGELOG context

Progress output:

Processing =bob-smith (8 files, 6 new)... Extracted 4 insights
Processing acme/meetings/management (52 files, 52 new)... Extracted 28 insights
...
Reprocessing complete.
Processed 186 files across 14 folders.
Extracted 89 insights (89 new, 0 already existed).

Skip conditions:

  • Folder has no CHANGELOG.md
  • All files already processed (dedup)
  • File is a pure standup (<500 words, no qualifying insights)

scan-claude-md -- Extract knowledge from CLAUDE.md files

Trigger: /insights scan-claude-md

Steps:

  1. Scan vault subfolders for CLAUDE.md files (max depth 4, skip .archive/, .handoff/, clones/)
  2. For each CLAUDE.md, find nearest parent folder with CHANGELOG.md as target for _insights.yaml. If no CHANGELOG.md exists in any parent (up to vault root), skip this CLAUDE.md with a note.
  3. Check freshness:
    • If _insights.yaml already has entries with source.file: "CLAUDE.md" AND the CLAUDE.md file has not been modified since last_updated in the insights file, skip (already current)
    • If CLAUDE.md is newer: remove all existing source.file: "CLAUDE.md" entries from _insights.yaml (preserving transcript-sourced insights), then re-extract
  4. Extract insights using type mapping:

    Signal in CLAUDE.mdInsight type
    "Chose X over Y", "Using X because", "Beslut:", "Decision:"decision
    "NEVER", "MUST", "Always", "Alltid", "Aldrig"preference
    "Avoid", "Don't", "Undvik", "Learned:", "Lärdom:"learning
    Rules, conventions, naming patterns, routing tables, format specificationspattern

    Note: opportunity type is not mapped for CLAUDE.md -- these files contain established decisions and conventions, not future opportunities. Opportunities are only extracted from transcripts via reprocess.

  5. Set source metadata:
    • source.file: "CLAUDE.md"
    • source.section: the ## heading under which the insight was found
  6. Skip sections that contain only:
    • Bare directory listings (pure file trees without commentary)
    • Pure glossaries (term: definition lists without rationale)
    • Metadata-only content (version numbers, dates, links without context)
  7. Write to _insights.yaml following the same format. Assign IDs continuing from next_id.

Output:

Scanning CLAUDE.md files...
  acme/CLAUDE.md -> acme/ (12 insights, replaced 8 stale)
  _contacts/bob-smith/CLAUDE.md -> _contacts/bob-smith/ (3 insights, new)
  bravo/CLAUDE.md -> skipped (no CHANGELOG.md in parent)
...
Scan complete.
Processed 14 CLAUDE.md files.
Extracted 42 insights (34 new, 8 replaced).
Skipped 3 files (no CHANGELOG.md parent).

status -- Show current insights state

Trigger: /insights status

Steps:

  1. Print the compile backlog first (CR-175): python3 ~/.claude/skills/insights/compile_status.py <vault>. One line -- ledgers, entries, never compiled, stale, current -- then the folders behind each count, never and stale listed apart because a setup gap and a cadence gap have different fixes. status answered for the folder in hand; this is the answer for the corpus, and it is the number a person is actually deciding on. Unreadable files are named here rather than dropped: a ledger that cannot be parsed is outside the loop entirely, which is worse than being stale and is invisible in every per-folder count.
  2. Scan vault for all _insights.yaml files
  3. Scan vault for all folders with CHANGELOG.md (potential insight targets)

Output:

Insights Status
===============

_insights.yaml files: 14
Total insights: 186

By type:
  decision:    52
  preference:  38
  learning:    41
  opportunity: 28
  pattern:     27

By status:
  active:      172
  superseded:  11
  archived:    3

By confidence:
  hypothesis:  168
  rule:        4
  consensus:   0        # CR-123: its own count; the line is omitted when no folder has a consensus profile

Top folders:
  acme/meetings/management    42 insights
  _contacts/bob-smith                  18 insights
  _contacts/david-ekberg          15 insights
  ...

Reprocessing opportunities:
  12 folders have CHANGELOG.md but no _insights.yaml
  3 folders have _insights.yaml older than newest transcript
  Total: ~340 unprocessed transcript files

Confidence Lifecycle (CR-013)
─────────────────────────────
  Hypotheses:  142          (illustrative figures -- see CR-094 for a measured baseline)
  Rules:       18 (most recent promotion: 260505)
  Recent demotions: 2 (last 30 days)

  Top 5 hypotheses near promotion (count, type, summary):
    2  preference  "Carol prefers async updates over sync standups"
    2  pattern     "Marketing meetings run 10-15 min over scheduled time"
    2  learning    "GA4 events take ~24h to surface in dashboards"
    2  decision    "Use _projects/ for time-boxed initiatives"
    2  pattern     "Bob wraps board prep with risk callout"

Skill Evolution
───────────────
  Execution feedback: 23 entries (18 edge_case, 5 correction)
  Compiled patterns: 3 skill_pattern entries
  Pending proposals: 2 in <proposals_path>/
  Applied proposals: 1 in <proposals_path>/.applied/
  Config: auto_apply=false, compile_threshold=3, propose_threshold=5,
          demote_on_contradiction=true

Status implementation notes:

  • "Hypotheses" count = entries with confidence: hypothesis OR missing confidence field, AND status: active.
  • "Rules" count = entries with confidence: rule AND status: active.
  • "Most recent promotion" = max date across rules where the rule was promoted (track via the most recent entry in confirmations[], since that is when the threshold was crossed).
  • "Recent demotions" = count of entries with non-empty contradicted_by[] whose latest demotion date is within the last 30 days.
  • "Top 5 hypotheses near promotion" = hypotheses with the highest confirmation_count, ties broken by recency. Show count, type, and summary.

compile -- Compile execution feedback into patterns and run lifecycle passes

Trigger: /insights compile or /insights compile since YYMMDD

Performs three passes in order: skill-pattern compilation, hypothesis-to-rule promotion, rule-to-hypothesis demotion.

Pass 1: skill_pattern compilation (existing)

Reads execution feedback entries (edge_case, correction) across _insights.yaml files and compiles recurring patterns into skill_pattern entries.

  1. Scan all _insights.yaml files in the vault for entries where source.skill is set (execution feedback)
  2. Filter by date if since YYMMDD is specified
  3. Group by similarity -- cluster entries by tags, summary keywords, and source.skill + source.step
  4. Apply compile threshold -- only groups with compile_threshold (default: 3) or more entries become patterns. Read threshold from workflows.knowledge_extraction.evolution.compile_threshold in config.
  5. For each qualifying group, create a skill_pattern entry in the most relevant _insights.yaml:
    - id: [next_id]
      type: skill_pattern
      date: YYMMDD          # today
      summary: "Pattern description synthesized from N occurrences"
      detail: "Dates, contexts, and common resolution across occurrences"
      source:
        skill: insights/compile
        entries: [list of source entry IDs and their _insights.yaml locations]
      tags: [synthesized, from, source, entries]
      status: active
  6. Dedup -- if a skill_pattern entry already covers the same cluster (by matching source.entries), update it instead of creating a duplicate
  7. Name-candidate roll-up (CR-095) -- a report, never a write. While clustering, collect the entries in the proper-noun family (the edge_case entries /transcript and /ops log for an unresolved or near-miss name -- CR-016, CR-017). Identify them by tag, in either language: proper-noun, egennamn, namnverifiering, namnupplösning, asr-variant, stavning, cr-016 -- the family is logged in the vault's working language, and an English-only match finds a fraction. Extract the flagged name from each summary/detail, and count occurrences across folders. Skip the flag marker itself (Namn att verifiera, Name to verify) -- it is quoted in the entries and is not a name. Drop any name that already resolves: a people[].canonical or alias in any _ops.yaml / .claude/ops-config.yaml, a team[] name or alias, or a contact's display_name/aliases in _contacts/*/_meta.yaml. Report every remaining name flagged twice or more, with a one-line guess at what it is (recurring person without a contact folder / ASR variant of a domain term / mishearing of a company name).

    It never edits a config. A roster entry is a claim about who someone is, and that claim needs a person: an automated identity claim would propagate a wrong spelling into every later summary -- the failure CR-016 exists to prevent. The report is printed in the run's output only, because the names come from vault data; it is never written to a file in this repo.

    Why here and not in /transcript: one transcript run sees one occurrence, and one occurrence is not evidence of a recurring person. The recurrence is only visible in aggregate, which is where compile already operates. Before CR-095 the flags had no reader at all -- one measured vault held 98 proper-noun flags over 40 folders and four months, against an empty people[] roster.

Pass 2: hypothesis → rule promotion (CR-013)

For each folder's _insights.yaml, find clusters of confirmed hypotheses and promote the canonical entry to a rule.

The arithmetic is a script (CR-100). Steps 1-3's deterministic gates -- candidate filter, type, the tag gate, threshold, distinct dates, single-session -- are computed by skills/insights/promotion_candidates.py <folder>, which prints the candidate groups as JSON with a group_key and a review_state each. Use its output rather than re-deriving the gates; a review surface uses the same script, so both see the same candidates. The script never judges: semantic agreement, topic tags (unless insight_topic_tags is configured), splitting and the contradiction check below stay judged. Its groups are connected components of the tag gate, so a group may hold more than one claim -- that is what split before promoting is for.

Profiles (CR-123). The script resolves each folder's profile and reports it under profiles. It reads promotable_types instead of the four meeting types, reports distinct_units beside distinct_dates and a confirmation_count by the profile's count_by, and names the target in promotes_to. When the target is consensus the pass is per entry: the script lists consensus_candidates (with independent_count, owner_count and the units behind each) and consensus_stale. For each candidate, compile writes confidence: consensus and the recounted fields (by targeted edit, CR-122); for each stale entry, it writes confidence: hypothesis and says why. The group steps below still run for the group-shaped cases (several entries making one claim): merge them into the earliest, as below, and then judge the merged entry against the consensus gate. A consensus pass never writes rule.

  1. Filter to candidates: entries where confidence is hypothesis (or absent) AND status: active AND type is one of the profile's promotable_types -- for the meeting profile decision | preference | learning | pattern (skip opportunity, quote, metric, edge_case, correction, skill_pattern); for the podcast profile claim | practice | tool_tip | prediction. metric is never promotable (CR-046): the same measurement recurring three times is a time series, not a standing instruction. Trend questions belong in /analytics.
  2. Group by similarity within the folder (CR-094):

    • Same type
    • At least two shared tags, or one shared tag when it is the primary tag (first in tags[]) of both entries
    • Semantic agreement on the claim, judged rather than counted: two summaries group when they assert the same thing about the same kind of subject, even with no shared vocabulary. Paraphrase is the norm, not the exception -- the corpus is model-written, and each entry is phrased freshly even when the observation recurs.
    • Token overlap is not a gate. It may break a tie when an entry could join more than one group.
    • A shared tag that names a topic is not evidence of a shared claim (CR-098). When the tags two entries share are subject areas (seo, payments, architecture, a supplier name) rather than properties of the claim, the tag overlap carries no weight -- decide on the summaries alone. A group that survives only on topic tags is not a group.
    • Split before promoting (CR-098). When a candidate group turns out to hold two or more distinct claims, split it and apply the threshold to each part. A six-entry group that is really four-plus-two yields one promotion, not one rule with two claims in it.
    • Conservative bias is kept through the tag requirement and the threshold: prefer false negatives over false promotions. A promoted rule becomes a standing instruction in every later run, so a wrong promotion costs more than a missed one.

    Why not a word-overlap threshold: before CR-094 this step required ≥60 % token overlap. On one mature vault (2 585 entries, 1 892 promotable hypotheses, 1 404 candidate pairs) the highest overlap anywhere was 0.50, so the gate could not fire and the rule layer held 5 entries -- the rules-walk in /ops and /transcript loaded an almost empty preamble every run. Baseline for comparison: 5 rules before the change.

  3. Apply threshold: groups with size ≥ compile_threshold (default 3, from workflows.knowledge_extraction.evolution.compile_threshold) qualify. A group whose entries all share one date is skipped as single session: it is one observation, however many entries it produced (CR-098). 3a. Honour recorded reviews (CR-100). Read each group's review_state from the script:

    • approved (the key still matches): promote this group as judged -- but step 3b still runs. An approval does not bypass the contradiction check; a reversal is exactly what a reviewer can miss. A group that fails 3b is reported needs review: contradiction (approved <date>) and not promoted.
    • stale (a judged entry changed, a member was added or superseded since): the old approval or rejection no longer describes the group. Do not act on it; report review stale and treat the group as unreviewed.
    • rejected (the key still matches): skip; report it with the recorded reason. It is not re-offered until the group changes, which makes the review stale.
    • A valid subset review under subset_reviews (a split, split_from equal to the current key): that subset is a group of its own, with its own canonical; the remainder is re-evaluated against the threshold.
    • unreviewed: with workflows.knowledge_extraction.evolution.promotion_review: optional (the default), judge the group as below. With required, do not promote it; report it as awaiting review. 3b. Contradiction check (CR-098). Before promoting, read the group for entries that reverse or negate each other -- a decision and its later reversal, a pattern and an entry saying it no longer holds. Such a group must not be promoted on the earliest entry, because the earliest is the superseded one. Either:
    • mark the superseded entry status: superseded, superseded_by: <later id> and re-apply the threshold to what remains, or
    • skip the group and report it as needs review: contradiction.

    A reversal shares more vocabulary with what it reverses than two paraphrases of one principle share with each other, so no similarity measure catches this -- not token overlap, not tags. It has to be read.

  4. For each qualifying group:
    • Pick the earliest entry by date as canonical.
    • Set canonical.confidence: rule.
    • Set canonical.confirmation_count to the number of distinct dates in the group, not the number of entries (CR-098). Entries written from one session are one observation however many were extracted. Every entry still goes into confirmations[] -- the provenance is kept, only the count is honest.
    • Append each non-canonical entry's source to canonical.confirmations[].
    • Mark each non-canonical entry status: superseded, superseded_by: <canonical-id>.
  5. Dedup: if the canonical entry already has confidence: rule, only append new (not-already-listed) confirmations and update confirmation_count (distinct dates).
  6. Report every skipped group with its reason (CR-098) -- topic-only tags, contradiction, split: below threshold, single session, and the review states from 3a (rejected: <reason>, review stale, awaiting review, needs review: contradiction (approved <date>)) -- not just the promotions. Keep promotion_review on a promoted canonical: it records who approved it. A promotion pass that reports only its successes cannot be audited. Measured when CR-098 was written: of the ten largest candidate groups on one vault, one was promotable as-is, so single-digit promotions per run is the expected order of magnitude, not a sign the pass is broken.

Pass 3: rule → hypothesis demotion (CR-013)

Skipped if workflows.knowledge_extraction.evolution.demote_on_contradiction is false. Default: true.

  1. Find all rules: entries with confidence: rule AND status: active, across the folder chain (current folder and parents per CR-011 walking resolution).
  2. For each rule, scan for targeting corrections: correction entries newer than the rule's most recent confirmation, that:
    • Share the rule's primary tag (first tag in tags[]).
    • Contain an opposing keyword in summary (heuristic: rule says "always X" and correction says "do not X" or "X was wrong"; rule says "prefers Y" and correction says "does not prefer Y").
  3. For each rule with at least one targeting correction:
    • Set rule.confidence: hypothesis.
    • Append each correction's source to rule.contradicted_by[].
    • Reduce rule.confirmation_count by the number of contradictions, floor at 1.
  4. Do not delete confirmations. History is preserved in confirmations[] for audit.

Output:

Compiling execution feedback and running lifecycle passes...

Pass 1 (skill_pattern compilation):
  Scanned 14 _insights.yaml files, found 23 execution feedback entries.
  Compiled 3 patterns.
  Skipped 8 entries below compile threshold (3).

  Roster candidates (flagged 2+ times, in no people[] roster, team[] or contact):   (CR-095)
    "Ravee"     4 flags   3 folders   → recurring person, no contact folder
    "Kubernetis" 3 flags   2 folders   → likely ASR variant of a domain term
    "Acmee"     2 flags   1 folder    → likely mishearing of a company name
  Add the ones that are people to people[] in the org config; the flags stop for them.

Pass 2 (hypothesis → rule promotion):
  Scanned 142 active hypotheses across 14 folders.
  Promoted 4 rules:
    - meetings/management/_insights.yaml#17 [preference] "Bob prefers concise weekly summaries" (3 confirmations)
    - _contacts/bob-smith/_insights.yaml#8 [pattern] "Bob raises customer-success topics last in 1-on-1s" (4 confirmations)
    - meetings/board/_insights.yaml#5 [decision] "Board updates use English for India team" (3 confirmations)
    - meetings/marketing/ppc/_insights.yaml#12 [learning] "PMax campaigns underperform below $500/day budget" (3 confirmations)
  Marked 8 superseded entries (canonical's mergees).
  Skipped 6 groups:                                                        (CR-098)
    - meetings/marketing/_insights.yaml [learning] "seo" (6)        topic-only tags
    - projects/app/_insights.yaml [decision] "architecture" (4)     contradiction -- needs review
    - projects/app/_insights.yaml [pattern] "estimation" (5)        single session (1 date)
    - ...

Pass 3 (rule → hypothesis demotion):
  Scanned 18 active rules.
  Demoted 1 rule:
    - meetings/management/_insights.yaml#11 [preference] "Always include Risk Assessment section"
      contradicted by 260507-summary.md (Bob asked to skip risk section for routine weeks)

Compile freshness stamp (CR-020)

After all three passes, write last_compiled: YYMMDD as a top-level field in every _insights.yaml the run scanned (additive; v1/v2 readers ignore it). This makes compile-staleness detectable: /insights status and /ops check flag when the newest entry in a file is >30 days newer than its last_compiled (or when the field is absent entirely -- i.e. compile has never run). Insights are write-heavy by design; the stamp is what keeps the synthesis half of the loop honest.


migrate -- One-shot schema migration for drifted _insights.yaml files (CR-020; was normalize)

Renamed in v1.79.0 (CR-089); /insights normalize was removed in v1.81.0. An old name is not recognised: say that it is now /insights migrate, and do not run it.

Trigger: /insights migrate [path] [--dry-run] (no path = whole vault; --dry-run is the DEFAULT — writing requires explicit --apply)

Brings legacy and drifted _insights.yaml files up to the current schema. Complements /ops normalize (which fixes Swedish characters); this fixes structure and vocabulary.

What it fixes, per entry:

DriftFix
ISO date "2026-03-09"→ 260309 (YYMMDD)
String ids (bp-017, board-003)→ sequential integers preserving order; record old id as legacy_id
Missing type→ infer from content; if ambiguous, set the most likely type and append type-inferred to tags for review
Non-canonical types (decision-pattern, principle, outcome, design, ...)→ map to nearest canonical (pattern, learning, learning, decision)
Non-canonical confidence (high, confirmed, supported)→ hypothesis + confirmation_count: 2 (the writer evidently meant "confirmed once more")
Non-canonical confidence (medium, low)→ hypothesis (count unchanged)
Legacy fields (added: → date, string source: → source.file)→ rename/restructure
superseded_by set but status: active→ status: superseded
Entries below the top-level next_id key -- orphans (CR-096)→ re-indent into insights, renumber from max(id)+1 to avoid collisions, splice before next_id, then bump it. Report the recovery with its count -- an orphan means some writer appended at end-of-file. Detect by reading the raw text, not the parsed file: an orphan either breaks the parse or is invisible to it
Missing top-level version/next_id/last_updated→ add (version: 2, next_id: max(id)+1, last_updated from newest entry). Recover orphans first -- max(id) over the parsed list ignores them, and repairing next_id around invisible entries collides with their ids
Tags > 5→ truncate from the tail

Process:

  1. Scan target for _insights.yaml files (skip .archive/, .transcripts/, .handoff/, clones/)
  2. Report every proposed change grouped by file (dry-run output = a unified change list with counts per drift class)
  3. On --apply: write files atomically, add a one-line CHANGELOG entry in each affected folder (- **YYMMDD: Normalize** _insights.yaml -- N schema fixes (CR-020))
  4. Never touch entry content (summary/rationale text) -- structure and vocabulary only; content remediation stays with /ops normalize

migrate --profile <name> -- move a corpus to a profile (CR-123)

Trigger: /insights migrate --profile podcast <folder> [--apply] (dry run by default). Refused when the folder's resolved profile is meeting: set profile: in its config first.

An existing v2 corpus that adopts a profile needs four changes. Two are judgements, two are arithmetic, and they are kept apart:

  1. Judge, per entry, and show it as a table before anything is written: the new type (from the wording of the entry: learning/pattern become claim, practice or tool_tip, a statement about the future prediction; borderline cases are named), the voice of the source unit and of each confirmation (from the summaries; both when a paraphrase cannot be placed), and whether an existing rule is really a claim (then consensus or hypothesis) or an instruction the user wrote (then it stays rule, and the type keeps a meeting value).
  2. Write the judgement as a plan file (entries: {id: {type, voice, confidence}}, confirmations: {id: {source: voice}}) in the session's scratch space, never in the vault.
  3. Apply and recount with the script: python3 ~/.claude/skills/insights/profile_migrate.py <folder> --plan <plan.yaml> prints the table with the recounted confirmation_count, independent_count and owner_count; --apply writes by targeted line edits, sets version: 3, then re-parses and compares: every entry must be equal except for the fields set, and the count of å/ä/ö must be unchanged, or nothing is written. A plan that would create a rule is refused.
  4. python3 ~/.claude/skills/insights/profile_migrate.py <folder> --recount [--apply] recounts only, after voices are labelled by hand or by later sessions.

Add a one-line CHANGELOG entry in the folder (- **YYMMDD: Migrate** _insights.yaml to the podcast profile -- N entries retyped, M voiced (CR-123)).


synthesize -- Render insight clusters into the knowledge wiki (CR-027)

Trigger: /insights synthesize [topic|all] (no argument = all clusters above threshold)

Turns the accumulated _insights.yaml corpus into a curated wiki: readable, crosslinked topic articles plus a master index. This is the synthesis layer the atomic entries feed — compile promotes rules (machine-facing context), synthesize produces articles (human- and session-facing knowledge). Clustering here is semantic and vault-wide (cross-folder, by topic), deliberately unlike compile Pass 2 (per-folder, gated by type and shared tags): prose summaries rarely repeat verbatim, so neither token overlap nor a single folder can build this layer. Pass 2 judges agreement semantically too since CR-094, but only inside one folder.

Config (workflows.knowledge_synthesis in base.yaml or org/vault config):

KeyDefaultMeaning
enabledtrueMaster switch
article_threshold5Minimum insights in a topic cluster to warrant an article
wiki_path.knowledge/wikiArticle location, vault-relative

Process:

  1. Load the corpus: every _insights.yaml (skip .archive/, .transcripts/, .handoff/, clones/), entries with status: active. Types quote and opportunity are supporting material (quotes illustrate; opportunities go in an article's open-questions section) — they never drive cluster selection alone.
  2. Cluster by topic, vault-wide: group semantically related insights across folders (shared tags are the seed; semantic judgment merges synonymous tags and splits overloaded ones). A cluster ≥ article_threshold (or an explicitly requested <topic>) gets an article.
  3. Write/update the article at <wiki_path>/<topic-slug>.md:
    • Topic-named, not dated — articles are living documents (like rolling plans), never YYMMDD- prefixed.
    • Frontmatter: sources: (list of file#id for every insight used), updated: YYMMDD, related: [slugs].
    • Body: synthesized prose — what has been learned, how thinking evolved, points of tension between insights, and an open-questions section. Verbatim quote entries may be quoted with attribution. Obsidian [[wikilinks]] to related articles. Language per the vault language policy; names allowed (CR-020 reusability note applies — this wiki is private).
    • Vocabulary is canonicalized at synthesis: known ASR-legacy terms in source insights are written correctly in articles (source entries stay untouched — the wiki is the cleaned layer).
    • Verticals boundary: if the topic matches a registered workflows.verticals doc, the article LINKS to the vertical for org-operational state instead of duplicating it.
  4. Idempotent refresh: re-running updates an article only from insights not yet in its sources:, appending/reworking sections as needed and bumping updated:. An article containing <!-- human-edited --> is NEVER auto-updated — report it and ask (flag once, respect the answer).
  5. Maintain <vault>/.knowledge/INDEX.md: one line per article — [[slug]] — one-sentence hook (updated YYMMDD) — grouped by theme; plus an Osorterat section listing loose notes at the .knowledge/ root (legacy notes are never modified or moved by this skill).
  6. Report: articles created/updated/skipped(human-edited), clusters below threshold (with counts, so growth toward threshold is visible).

Theme pages (CR-124): /insights synthesize --themes <project>. For a project with themes.enabled, the registry (<project>/_themes.yaml) is the cluster definition instead of semantic clustering: one article per theme with at least article_threshold units, written to <wiki_path>/themes/<id>-<slug>.md and listed in INDEX.md under the project's name. No second mechanism: the same frontmatter, refresh, human-edited and INDEX rules apply. Each page holds, in order: a table of units per quarter by original date (python3 ~/.claude/skills/ops/themes.py quarters <project> --theme <id>), core messages, where voices disagree, phases over time (breadth is handled by phases, not by splitting a broad theme), who raises it (by voice, never by name), gaps, and a unit table (date, unit, role, note). It says what it was built from. After writing, set the theme's synthesis: path in the registry by targeted edit.

How the wiki is USED (the no-RAG contract): a session answering a knowledge question reads INDEX.md first, then opens only the relevant article(s). No vault-wide scanning, no retrieval infrastructure. The INDEX is maintained by this subcommand only — never hand-edited by other skills.


propose -- Generate SKILL.md improvement proposals

Trigger: /insights propose

Reads compiled skill_pattern entries and generates concrete SKILL.md improvement proposals.

Steps:

  1. Scan all _insights.yaml files for skill_pattern entries
  2. Apply propose threshold -- only patterns with propose_threshold (default: 5) or more underlying occurrences generate proposals. Read threshold from workflows.knowledge_extraction.evolution.propose_threshold in config.
  3. For each qualifying pattern: a. Read the target SKILL.md file (determined by source.skill) b. Identify the relevant step or section c. Generate a concrete proposed change as a markdown file
  4. Save proposals to workflows.knowledge_extraction.evolution.proposals_path — default docs/proposals/generated/ inside this repo, gitignored until reviewed (CR-083).

    This reverses CR-028's "never inside the skill repo". The reason CR-028 gave was privacy: proposals derive from vault data. But a proposal is an instruction — it says how a skill should work — and instructions belong where the skill lives, or they are reviewed nowhere the repo can see. Written into the vault they never entered the index and no session reading the repo could find them.

    The privacy requirement is unchanged and is met differently: a generated proposal is written name-free, the same rule every CR since CR-047 follows, and the pre-push guard scans it on the way out. Evidence stays in the vault — a proposal may say observed in one vault; it never needs the names to be right.

    A vault may still override the path, but nothing in this repo assumes it does. Format:

    # Proposal: [Short title]
    
    **Based on:** [N] occurrences of [pattern summary]
    **Target:** skills/[skill]/SKILL.md
    **Pattern entry:** [reference to skill_pattern in _insights.yaml]
    
    ## Proposed change
    
    **In section:** [Step or section name]
    **Action:** [Add/Modify/Remove]
    
    > [Exact text to add or replace, written in the same style as the target SKILL.md]
    
    ## Rationale
    
    [Why this change addresses the pattern, with references to specific occurrences]
  5. Check auto_apply setting from workflows.knowledge_extraction.evolution.auto_apply:
    • If false (default): save proposal file, report to user
    • If true: apply the change to SKILL.md directly, log in CHANGELOG with [AUTO-EVOLUTION] tag, save proposal as record

Output (auto_apply: false):

Generated 2 proposals:

1. <proposals_path>/260404-transcript-name-disambiguation.md
   Target: skills/transcript/SKILL.md (Step 1)
   Based on: 7 edge_case entries across 4 contacts

2. <proposals_path>/260410-ops-short-call-threshold.md
   Target: skills/transcript/SKILL.md (Step 4)
   Based on: 5 skill_pattern entries

Review proposals and run /insights propose apply to accept.

Output (auto_apply: true):

Auto-applied 2 proposals:

1. skills/transcript/SKILL.md -- added name disambiguation pre-check (Step 1)
   [AUTO-EVOLUTION] Based on 7 edge_case entries

2. skills/transcript/SKILL.md -- added short-call skip for task import (Step 4)
   [AUTO-EVOLUTION] Based on 5 skill_pattern entries

Changes logged in CHANGELOG.md. Review with: git diff HEAD~1

propose apply -- Apply a proposal

Trigger: /insights propose apply [proposal-file] or /insights propose apply all

Steps:

  1. If specific file: Read the proposal, apply the change to the target SKILL.md
  2. If all: Apply all proposals in the configured proposals_path that haven't been applied yet
  3. For each applied proposal: a. Edit the target SKILL.md with the proposed change b. Add a CHANGELOG entry with [EVOLUTION] tag c. Move the proposal file to <proposals_path>/.applied/ with a date prefix d. Mark the source skill_pattern entry as status: archived in _insights.yaml

Output:

Applied: <proposals_path>/260404-transcript-name-disambiguation.md
  -> skills/transcript/SKILL.md updated (Step 1: added pre-check)
  -> CHANGELOG.md updated
  -> Proposal archived to <proposals_path>/.applied/

1 proposal applied. Review changes with: git diff

help -- Usage guide

Trigger: /insights help

Output:

/insights -- Knowledge Extraction & Skill Evolution
=====================================================

Backfill _insights.yaml, compile execution feedback, and evolve skills.

Usage:
  /insights reprocess =bob-smith          Extract from one folder
  /insights reprocess all                Extract from all folders with CHANGELOG.md
  /insights reprocess since 260201       Extract from files dated after 260201
  /insights scan-claude-md               Extract from CLAUDE.md files
  /insights compile                      Compile execution feedback into patterns
  /insights compile since 260301         Compile only recent feedback
  /insights migrate [path] [--apply]   Migrate drifted files to current schema (dry-run default)
  /insights synthesize [topic|all]       Render insight clusters into wiki articles + INDEX (CR-027)
  /insights propose                      Generate SKILL.md improvement proposals
  /insights propose apply [file|all]     Apply a proposal to SKILL.md
  /insights status                       Show insights + evolution statistics
  /insights help                         This guide

Knowledge extraction (content):
  /transcript Step 3.5    Extracts insights from NEW transcripts (forward)
  /ops Step 5.5           Extracts insights from NEW meeting docs (forward)
  /insights reprocess     Extracts insights from EXISTING transcripts (backfill)
  /insights scan-claude-md  Extracts from CLAUDE.md files

Skill evolution (execution feedback):
  /ops Step 9             Captures edge cases and corrections (silent)
  /transcript Step 4.5    Captures edge cases and corrections (silent)
  /insights compile       Finds patterns in execution feedback
  /insights propose       Generates SKILL.md improvements from patterns

Data flow:
  /transcript or /ops ─┐
                       ├── _insights.yaml ──> visualisation app
  /insights ───────────┘       │
                               ├── execution feedback (edge_case, correction)
                               │        │
                               │   /insights compile -> skill_pattern entries
                               │        │
                               │   /insights propose -> SKILL.md improvements
                               │        │
                               └── skills get smarter over time

Config: workflows.knowledge_extraction.evolution in base.yaml
  auto_apply: false (default) -- proposals require manual review
  auto_apply: true -- proposals applied automatically

Extraction Reference (Quick Copy)

This is a convenience copy. The authoritative definition is in /transcript Step 3.5 (~/.claude/skills/transcript/SKILL.md).

TypeCapturesWritten by
decisionChoice + rationale/transcript, /ops, /insights reprocess
preferenceWorking style/transcript, /ops, /insights reprocess
learningWhat worked/didn't/transcript, /ops, /insights reprocess
opportunityIdeas not yet actioned/transcript, /ops, /insights reprocess
patternRecurring themes/transcript, /ops, /insights reprocess
quoteMemorable verbatim quote (exempt from promotion -- never becomes a rule)/transcript, /ops, /insights reprocess
metricA measurement where the number is the claim (exempt from promotion -- CR-046)/transcript, /ops, /insights reprocess
edge_caseSkill hit ambiguous input/transcript Step 4.5, /ops Step 9
correctionUser corrected skill output/transcript Step 4.5, /ops Step 9
skill_patternCompiled execution pattern/insights compile

metric vs learning (CR-046): remove the number from the summary. Nothing left -> metric. Claim survives -> learning citing evidence.

Threshold: Only non-obvious, durable, specific insights. If fewer than min_insights (default: 1) qualify, skip the file silently.

Format: See /transcript Step 3.5 for the complete _insights.yaml schema.


Reusability and language rules for _insights.yaml

Reusability (CR-020 -- replaces the former privacy rule)

Names are allowed in insight entries. The old rule ("never include personal or company names in summary, rationale, or tags") was retired in the 2026-04-07 audit and formally removed by CR-020 -- the vault is private, and quote entries need attribution by construction. What remains is a reusability preference: when an insight generalizes beyond the person who sparked it, prefer name-free phrasing in summary and tags so the entry reads well in cross-folder views -- context and source.file already carry the who/what. Names in rationale are always fine. See /transcript Step 3.5 for examples.

Contact Classification (CR-009)

Insights are extracted from all contacts regardless of their classification (family, personal, professional, confidential) — knowledge is valuable in all contexts. The core-skills-visualisation app is responsible for respecting classification when rendering.

Vocabulary guard (CR-020)

Before writing any entry, apply the write-time vocabulary guard defined in /transcript Step 3.5: canonical type values only, confidence limited to hypothesis | rule, YYMMDD dates, integer ids with next_id maintained, max 5 tags. This applies to every subcommand in this skill that writes entries.

Swedish Character Enforcement (CR-007: pre-write validator)

When processing Swedish-language content, ALL Swedish words MUST use correct å, ä, ö characters. Never substitute with a or o. This applies equally to _insights.yaml YAML fields as to markdown files -- YAML content is just as prone to missing characters.

Pre-write validator (CR-007, mandatory):

Before writing any entry to _insights.yaml where the summary, rationale, or context field is in Swedish (detected by presence of any å/ä/ö character anywhere in the file, OR by folder language per language_inheritance in base.yaml):

  1. Load ~/.claude/skills/ops-config/swedish_substitutions.yaml
  2. Scan each Swedish text field token-by-token using word-boundary matching
  3. For each match against the substitution map (excluding category: skip):
    • Non-ambiguous matches: refuse to write, report the violation, ask the user to confirm or fix
    • Ambiguous matches: warn but proceed (log to execution feedback as edge_case)
  4. If no violations, proceed with the write

This is the structural validation that the MEMORY.md reminder cannot provide -- the model may write a tempting "...byggs fran Meta..." line, but the validator catches it before the file lands on disk.

To remediate existing files written before this validator was added, run /ops normalize <path>.

Common mistakes to avoid (full list in swedish_substitutions.yaml):

  • "pagaende" -> "pågående", "foretag" -> "företag", "fran" -> "från"
  • "fore" -> "före", "nasta" -> "nästa", "behovs" -> "behövs", "kravs" -> "krävs"
  • "anvandning" -> "användning", "mote" -> "möte", "losning" -> "lösning"
  • "manader" -> "månader", "forberedelse" -> "förberedelse", "karnteam" -> "kärnteam"
  • "prissattning" -> "prissättning", "overgang" -> "övergång", "forandring" -> "förändring"

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.