[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M75K831CSCTNK35WJS5KA30Q":3,"skill-same:01M75K831CSCTNK35WJS5KA30Q":64},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":19,"linkOnly":20,"markdownContent":21,"markdownBody":22,"frontMatter":23,"refName":37,"commitSha":38,"skillDirectory":39,"forksCount":14,"repositoryHtmlUrl":40,"repositoryHomepageUrl":6,"ownerHtmlUrl":41,"ownerBlogUrl":42,"ownerDescription":43,"updatedAt":44,"install":45,"resources":57},"01M75K831CSCTNK35WJS5KA30Q","archive-crawler",null,"Universal archivist for personal file archives (Dropbox\u002FB2\u002FGmail-takeout\u002Flocal-mount\u002Fhard-drive-dump). Filters for high-value content (the user's own writing, ideas, relationships) and surfaces it interactively. REFUSES TO RUN without an explicit gbrain.yml `archive-crawler.scan_paths:` allow-list.","cheRoma\u002Fgbrain-link-chat","cheRoma","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F265356812?v=4","01M75JVGAJEZK04E1THSDHYVNK","Roman Cherepanov","01M75JVGB5SWY40H959C3QXRAQ",0,"MIT","https:\u002F\u002Fgithub.com\u002FcheRoma\u002Fgbrain-link-chat\u002Fblob\u002Ffeat\u002Flink-chat-distiller\u002Fplugin\u002Fskills\u002Farchive-crawler\u002FSKILL.md",[],[],"2026-11-12 13:55:43",false,"---\nname: archive-crawler\nversion: 0.1.0\ndescription: Universal archivist for personal file archives (Dropbox\u002FB2\u002FGmail-takeout\u002Flocal-mount\u002Fhard-drive-dump). Filters for high-value content (the user's own writing, ideas, relationships) and surfaces it interactively. REFUSES TO RUN without an explicit gbrain.yml `archive-crawler.scan_paths:` allow-list.\ntriggers:\n  - \"crawl my archive\"\n  - \"find gold in my archive\"\n  - \"archive crawler\"\n  - \"scan my dropbox for\"\n  - \"mine my old files for\"\nmutating: true\nwrites_pages: true\nwrites_to:\n  - originals\u002F\n  - personal\u002F\n  - ideas\u002F\nwhen_to_use: \"Use when the user asks: \\\"crawl my archive\\\", \\\"find gold in my archive\\\", \\\"archive crawler\\\", \\\"scan my dropbox for\\\", \\\"mine my old files for\\\".\"\n---\n\n# archive-crawler — The Universal Archivist\n\n> **Convention:** see [conventions\u002Fquality.md](..\u002Fconventions\u002Fquality.md) for\n> citation rules, exact-phrasing requirements when capturing the user's\n> reactions, and back-link enforcement.\n>\n> **Convention:** see [_brain-filing-rules.md](..\u002F_brain-filing-rules.md) —\n> this skill is **schema-generic**: it reads the user's filing rules from\n> the rules JSON instead of hardcoding any specific era \u002F archive layout.\n\n## Safety gate (REQUIRED, no exceptions)\n\narchive-crawler refuses to run unless `archive-crawler.scan_paths:` is\nexplicitly set in `gbrain.yml`. This is a deliberate safety fence against\nthe agent over-scoping a scan and ingesting sensitive content (tax PDFs,\nmedical records, credentials).\n\n```yaml\n# gbrain.yml — the allow-list is mandatory\narchive-crawler:\n  scan_paths:\n    - ~\u002FDocuments\u002Fwriting\u002F\n    - ~\u002FDropbox\u002FArchive\u002F\n    - \u002Fmnt\u002Fbackup\u002Fold-letters\u002F\n  # Optional deny-list inside the allow-list:\n  # deny_paths:\n  #   - ~\u002FDocuments\u002Ffinances\u002F\n  #   - ~\u002FDocuments\u002Fmedical\u002F\n```\n\nIf `scan_paths` is empty or missing, the skill exits with:\n\n```\narchive-crawler: refusing to run. No `archive-crawler.scan_paths:` allow-list\nin gbrain.yml. Add explicit paths the agent is permitted to scan, then re-run.\nThis is a safety fence — the agent will not infer what's safe to read.\n```\n\nThis contract is enforced by `src\u002Fcore\u002Fstorage-config.ts` (mirrors the\n`db_tracked` \u002F `db_only` allow-list pattern from v0.22.11 storage tiering).\n\n## What this is\n\nGeneric engine for exploring any tree of personal content within an\nexplicit allow-list. Works on local mounts, Dropbox API targets,\nBackblaze B2, Gmail takeouts (`.mbox`), and similar archives. Filters\nfor \"gold\" (the user's own writing, ideas, relationships) and surfaces\nit interactively for review. Skips noise (system files, configs, binary\nblobs).\n\n## Concepts\n\n### Source\n\nA source is any tree of files to explore. Sources have:\n\n- **type**: `local` | `dropbox` | `backblaze` | `gmail-takeout` | `mbox` | `pst`\n- **root**: filesystem path, Dropbox path, B2 prefix, mbox path\n- **manifest**: a brain page tracking progress at\n  `projects\u002F\u003Carchive-slug>\u002FSTATUS.md`\n\n### Manifest\n\nEvery archive exploration gets a manifest brain page that tracks:\n\n1. **Tree inventory** — folders \u002F files \u002F sizes \u002F types\n2. **Triage status** — each item: `⬜ unseen` \u002F `👀 reviewed` \u002F\n   `✅ ingested` \u002F `⏭️ skip` \u002F `🔥 high-signal`\n3. **User reactions** — exact quotes when they react (per\n   conventions\u002Fquality.md exact-phrasing rule)\n4. **Priority queue** — what to explore next, ranked\n5. **Session log** — timestamped record of what was shown per session\n\n### Gold filter\n\nBefore showing anything to the user, apply the gold filter:\n\n| Keep (show) | Skip (note existence, don't show) |\n|-------------|-----------------------------------|\n| Personal writing (journals, letters, reflections, essays) | System files, configs, package.json, node_modules |\n| Conversations (IM logs, email threads with substance) | Binary blobs (images \u002F video) |\n| Ideas, theses, frameworks | Receipts, invoices, tax docs |\n| Relationship material (letters to \u002F from people who matter) | Spam, newsletters, mailing-list bulk |\n| Creative work (poetry, stories, code with soul) | Corrupted \u002F null files |\n| Origin stories (first versions of things that became important) | |\n| Emotional content (anger, love, grief, discovery) | |\n\n## Protocol\n\n### Phase 1: Inventory\n\nWhen pointed at a new source:\n\n1. **Confirm scan_paths is set** (safety gate). Exit if not.\n2. **Map the tree** — list folders + files + sizes + date ranges.\n3. **Classify folders** — group by likely content type (writing, email,\n   code, photos, docs, system).\n4. **Create manifest** — write `projects\u002F\u003Carchive-slug>\u002FSTATUS.md` with\n   the full inventory.\n5. **Propose priority queue** — rank folders by likely gold density.\n6. **Present to user** — show the map and proposed order. Let them\n   override.\n\n### Phase 2: Crawl\n\nWork through folders in priority order:\n\n1. **Read before showing** — open each candidate file, apply the gold\n   filter, skip noise.\n2. **Show one at a time** — present gold items individually for review.\n3. **Capture exact reaction** — track the user's response in the\n   manifest using their exact words (per conventions\u002Fquality.md).\n4. **Ingest if worth keeping** — create a brain page immediately.\n5. **Update manifest** — mark item status after each interaction.\n6. **Never re-show** — check the manifest before presenting anything.\n\n### Phase 3: Ingest\n\nWhen an item is worth keeping, file it by **primary subject** per\n`_brain-filing-rules.md`:\n\n- User's own writing \u002F ideas \u002F origin-story content → `originals\u002F\u003Cslug>.md`\n- Reflections \u002F personal-life content → `personal\u002F\u003Cslug>.md`\n- Product \u002F business ideas → `ideas\u002F\u003Cslug>.md`\n- Letters or threads about a specific person → `people\u002F\u003Cperson>\u002Ftimeline`\n  back-link plus the letter at `personal\u002F\u003Cslug>.md` or `originals\u002F\u003Cslug>.md`\n\n**The skill is schema-generic.** It does NOT bake in any specific\nera-folder structure (e.g., `originals\u002Farchive\u002F` for pre-2003,\n`originals\u002Fyc-era\u002F` for post-2019, etc.). The user's filing rules from\n`_brain-filing-rules.json` are read at runtime; the agent decides per-page\nwhere content lands within those sanctioned directories.\n\nBrain page format:\n\n```markdown\n---\ntitle: \"[Title or first line]\"\ntype: original\nsource_type: \"[local|dropbox|backblaze|gmail-takeout|mbox|pst]\"\nsource_path: \"[path within the allow-listed scan_paths]\"\ndate: \"YYYY-MM-DD\"  # date from the file metadata or content\npeople: [\"person-1\", \"person-2\"]\ntags: [\"tag-1\", \"tag-2\"]\n---\n\n# [Title]\n\n[Summary: what it is, when it's from, why it matters]\n\n**User's reaction:** [exact quote, no paraphrasing]\n\n## Context\n\n[Cross-links to people, concepts, projects.]\n\n---\n\n[Raw source material below the line — full text]\n```\n\n## File-type handlers\n\n### Plain text \u002F HTML \u002F Markdown\nRead directly. Strip HTML tags for display.\n\n### `.mbox` (email archives)\n\n```python\nimport mailbox\nmbox = mailbox.mbox('\u002Fpath\u002Fto\u002Ffile.mbox')\nfor msg in mbox:\n    body = ''\n    if msg.is_multipart():\n        for part in msg.walk():\n            if part.get_content_type() == 'text\u002Fplain':\n                body = part.get_payload(decode=True).decode('utf-8', errors='replace')\n                break\n    else:\n        body = msg.get_payload(decode=True).decode('utf-8', errors='replace')\n    # Apply gold filter\n```\n\n### `.doc` \u002F `.docx`\n\n```bash\n# .docx (modern)\npython3 -c \"\nimport zipfile, xml.etree.ElementTree as ET\nwith zipfile.ZipFile('\u002Fpath\u002Fto\u002Ffile.docx') as z:\n    tree = ET.parse(z.open('word\u002Fdocument.xml'))\n    print(''.join(t.text or '' for t in tree.iter('{http:\u002F\u002Fschemas.openxmlformats.org\u002Fwordprocessingml\u002F2006\u002Fmain}t')))\n\"\n\n# .doc (legacy, requires antiword or catdoc)\nantiword \u002Fpath\u002Fto\u002Ffile.doc 2>\u002Fdev\u002Fnull || catdoc \u002Fpath\u002Fto\u002Ffile.doc 2>\u002Fdev\u002Fnull\n```\n\n### `.pst` (Outlook archives)\n\n```bash\n# Validate first; many PSTs are null bytes\npython3 -c \"\nwith open('\u002Fpath\u002Fto\u002Ffile.pst', 'rb') as f:\n    print('Valid PST' if f.read(4) == b'!BDN' else 'CORRUPT\u002FNULL')\n\"\n# If valid:\nreadpst -o \u002Ftmp\u002Fpst-output \u002Fpath\u002Fto\u002Ffile.pst\n```\n\n### `.zip` \u002F `.tar` \u002F `.tar.gz`\n\nExtract to a temp dir, then recurse through the extracted tree.\n\n### Images\n\nNote existence + metadata (filename, size, date). Don't show unless the\nuser asks. Flag scans \u002F portraits as potentially personal.\n\n## Manifest template\n\n```markdown\n---\ntitle: \"[Archive Name] — Ingestion Status\"\ntype: project\ncreated: YYYY-MM-DD\nupdated: YYYY-MM-DD\nsource_type: \"[local|dropbox|...]\"\nscan_paths: [\"paths from gbrain.yml\"]\n---\n\n# [Archive Name] — Ingestion Status\n\n## Source\n- **Type:** [local|dropbox|...]\n- **Allow-listed paths:** [from gbrain.yml]\n- **Total files:** [N]\n- **Total size:** [X GB]\n- **Date range:** [earliest] — [latest]\n\n## Inventory\n\n### [Folder 1]\n| Item | Type | Size | Status | Reaction |\n|------|------|------|--------|----------|\n| file1.txt | text | 2KB | ✅ ingested | 🔥 \"exact quote\" |\n| file2.doc | doc | 15KB | ⏭️ skip | — |\n| file3.html | html | 4KB | ⬜ unseen | — |\n\n### [Folder 2]\n...\n\n## Priority Queue\n1. [Highest priority — why]\n2. [Next — why]\n...\n\n## Session Log\n\n### YYYY-MM-DD — [Session topic]\n- Reviewed: [list]\n- Reactions: [exact quotes]\n- Ingested: [brain pages created]\n- Next: [what's queued]\n```\n\n## When it fails\n\nFollow the [agent operator protocol](..\u002Fconventions\u002Fagent-operator-protocol.md) for any gbrain error `code`, exit code, `[AGENT]` block or notice block. Specific to this skill:\n\n- No `archive-crawler.scan_paths:` allow-list: this is the skill's own hard refusal. Ask the user which directories may be scanned; never widen the list yourself to get past it.\n- An archive mount, takeout or bucket is unreadable (permission, expired token): report the exact path that failed and stop that source; do not fall back to scanning a parent directory.\n- Filing a find returns `write_pending` (exit 10) or `revision_conflict`: poll `gbrain write-request \u003Crequest_id>` for the first; re-read the page and merge for the second. Never re-file under a new slug.\n\n## Anti-Patterns\n\n- ❌ Running without `archive-crawler.scan_paths:` set. Hard refusal.\n  This is the safety contract — never bypass.\n- ❌ Hardcoding era-specific filing paths (e.g., `originals\u002Farchive\u002F`,\n  `originals\u002Fyc-era\u002F`). Read filing rules at runtime instead.\n- ❌ Re-showing items already marked in the manifest. The user's time\n  is the scarcest resource.\n- ❌ Paraphrasing reactions. Exact words only.\n- ❌ Wrapping found content in lessons or takeaways. Let stories breathe.\n- ❌ Skipping back-links when content references people \u002F companies who\n  have brain pages. Iron Law per conventions\u002Fquality.md.\n\n## Related skills\n\n- `skills\u002Fvoice-note-ingest\u002FSKILL.md` — same exact-phrasing pattern for\n  audio capture\n- `skills\u002Fidea-ingest\u002FSKILL.md` — single-link-or-article ingest with\n  the same primary-subject filing rule\n- `skills\u002Fconventions\u002Fquality.md` — citations, back-links, voice\n\n\n## Contract\n\nThis skill guarantees:\n\n- Routing matches the canonical triggers in the frontmatter.\n- Output written under the directories listed in `writes_to:` (when applicable).\n- Conventions referenced (`quality.md`, `brain-first.md`, `_brain-filing-rules.md`) are followed.\n- Privacy contract preserved: no real names, no fork-specific filesystem path literals, no upstream-fork references.\n\nThe full behavior contract is documented in the body sections above; this section exists for the conformance test.\n\n## Output Format\n\nThe skill's output shape is documented inline in the body sections above (see \"Output\", \"Brain page format\", or equivalent). The literal section header here exists for the conformance test (`test\u002Fskills-conformance.test.ts`).\n","# archive-crawler — The Universal Archivist\n\n> **Convention:** see [conventions\u002Fquality.md](..\u002Fconventions\u002Fquality.md) for\n> citation rules, exact-phrasing requirements when capturing the user's\n> reactions, and back-link enforcement.\n>\n> **Convention:** see [_brain-filing-rules.md](..\u002F_brain-filing-rules.md) —\n> this skill is **schema-generic**: it reads the user's filing rules from\n> the rules JSON instead of hardcoding any specific era \u002F archive layout.\n\n## Safety gate (REQUIRED, no exceptions)\n\narchive-crawler refuses to run unless `archive-crawler.scan_paths:` is\nexplicitly set in `gbrain.yml`. This is a deliberate safety fence against\nthe agent over-scoping a scan and ingesting sensitive content (tax PDFs,\nmedical records, credentials).\n\n```yaml\n# gbrain.yml — the allow-list is mandatory\narchive-crawler:\n  scan_paths:\n    - ~\u002FDocuments\u002Fwriting\u002F\n    - ~\u002FDropbox\u002FArchive\u002F\n    - \u002Fmnt\u002Fbackup\u002Fold-letters\u002F\n  # Optional deny-list inside the allow-list:\n  # deny_paths:\n  #   - ~\u002FDocuments\u002Ffinances\u002F\n  #   - ~\u002FDocuments\u002Fmedical\u002F\n```\n\nIf `scan_paths` is empty or missing, the skill exits with:\n\n```\narchive-crawler: refusing to run. No `archive-crawler.scan_paths:` allow-list\nin gbrain.yml. Add explicit paths the agent is permitted to scan, then re-run.\nThis is a safety fence — the agent will not infer what's safe to read.\n```\n\nThis contract is enforced by `src\u002Fcore\u002Fstorage-config.ts` (mirrors the\n`db_tracked` \u002F `db_only` allow-list pattern from v0.22.11 storage tiering).\n\n## What this is\n\nGeneric engine for exploring any tree of personal content within an\nexplicit allow-list. Works on local mounts, Dropbox API targets,\nBackblaze B2, Gmail takeouts (`.mbox`), and similar archives. Filters\nfor \"gold\" (the user's own writing, ideas, relationships) and surfaces\nit interactively for review. Skips noise (system files, configs, binary\nblobs).\n\n## Concepts\n\n### Source\n\nA source is any tree of files to explore. Sources have:\n\n- **type**: `local` | `dropbox` | `backblaze` | `gmail-takeout` | `mbox` | `pst`\n- **root**: filesystem path, Dropbox path, B2 prefix, mbox path\n- **manifest**: a brain page tracking progress at\n  `projects\u002F\u003Carchive-slug>\u002FSTATUS.md`\n\n### Manifest\n\nEvery archive exploration gets a manifest brain page that tracks:\n\n1. **Tree inventory** — folders \u002F files \u002F sizes \u002F types\n2. **Triage status** — each item: `⬜ unseen` \u002F `👀 reviewed` \u002F\n   `✅ ingested` \u002F `⏭️ skip` \u002F `🔥 high-signal`\n3. **User reactions** — exact quotes when they react (per\n   conventions\u002Fquality.md exact-phrasing rule)\n4. **Priority queue** — what to explore next, ranked\n5. **Session log** — timestamped record of what was shown per session\n\n### Gold filter\n\nBefore showing anything to the user, apply the gold filter:\n\n| Keep (show) | Skip (note existence, don't show) |\n|-------------|-----------------------------------|\n| Personal writing (journals, letters, reflections, essays) | System files, configs, package.json, node_modules |\n| Conversations (IM logs, email threads with substance) | Binary blobs (images \u002F video) |\n| Ideas, theses, frameworks | Receipts, invoices, tax docs |\n| Relationship material (letters to \u002F from people who matter) | Spam, newsletters, mailing-list bulk |\n| Creative work (poetry, stories, code with soul) | Corrupted \u002F null files |\n| Origin stories (first versions of things that became important) | |\n| Emotional content (anger, love, grief, discovery) | |\n\n## Protocol\n\n### Phase 1: Inventory\n\nWhen pointed at a new source:\n\n1. **Confirm scan_paths is set** (safety gate). Exit if not.\n2. **Map the tree** — list folders + files + sizes + date ranges.\n3. **Classify folders** — group by likely content type (writing, email,\n   code, photos, docs, system).\n4. **Create manifest** — write `projects\u002F\u003Carchive-slug>\u002FSTATUS.md` with\n   the full inventory.\n5. **Propose priority queue** — rank folders by likely gold density.\n6. **Present to user** — show the map and proposed order. Let them\n   override.\n\n### Phase 2: Crawl\n\nWork through folders in priority order:\n\n1. **Read before showing** — open each candidate file, apply the gold\n   filter, skip noise.\n2. **Show one at a time** — present gold items individually for review.\n3. **Capture exact reaction** — track the user's response in the\n   manifest using their exact words (per conventions\u002Fquality.md).\n4. **Ingest if worth keeping** — create a brain page immediately.\n5. **Update manifest** — mark item status after each interaction.\n6. **Never re-show** — check the manifest before presenting anything.\n\n### Phase 3: Ingest\n\nWhen an item is worth keeping, file it by **primary subject** per\n`_brain-filing-rules.md`:\n\n- User's own writing \u002F ideas \u002F origin-story content → `originals\u002F\u003Cslug>.md`\n- Reflections \u002F personal-life content → `personal\u002F\u003Cslug>.md`\n- Product \u002F business ideas → `ideas\u002F\u003Cslug>.md`\n- Letters or threads about a specific person → `people\u002F\u003Cperson>\u002Ftimeline`\n  back-link plus the letter at `personal\u002F\u003Cslug>.md` or `originals\u002F\u003Cslug>.md`\n\n**The skill is schema-generic.** It does NOT bake in any specific\nera-folder structure (e.g., `originals\u002Farchive\u002F` for pre-2003,\n`originals\u002Fyc-era\u002F` for post-2019, etc.). The user's filing rules from\n`_brain-filing-rules.json` are read at runtime; the agent decides per-page\nwhere content lands within those sanctioned directories.\n\nBrain page format:\n\n```markdown\n---\ntitle: \"[Title or first line]\"\ntype: original\nsource_type: \"[local|dropbox|backblaze|gmail-takeout|mbox|pst]\"\nsource_path: \"[path within the allow-listed scan_paths]\"\ndate: \"YYYY-MM-DD\"  # date from the file metadata or content\npeople: [\"person-1\", \"person-2\"]\ntags: [\"tag-1\", \"tag-2\"]\n---\n\n# [Title]\n\n[Summary: what it is, when it's from, why it matters]\n\n**User's reaction:** [exact quote, no paraphrasing]\n\n## Context\n\n[Cross-links to people, concepts, projects.]\n\n---\n\n[Raw source material below the line — full text]\n```\n\n## File-type handlers\n\n### Plain text \u002F HTML \u002F Markdown\nRead directly. Strip HTML tags for display.\n\n### `.mbox` (email archives)\n\n```python\nimport mailbox\nmbox = mailbox.mbox('\u002Fpath\u002Fto\u002Ffile.mbox')\nfor msg in mbox:\n    body = ''\n    if msg.is_multipart():\n        for part in msg.walk():\n            if part.get_content_type() == 'text\u002Fplain':\n                body = part.get_payload(decode=True).decode('utf-8', errors='replace')\n                break\n    else:\n        body = msg.get_payload(decode=True).decode('utf-8', errors='replace')\n    # Apply gold filter\n```\n\n### `.doc` \u002F `.docx`\n\n```bash\n# .docx (modern)\npython3 -c \"\nimport zipfile, xml.etree.ElementTree as ET\nwith zipfile.ZipFile('\u002Fpath\u002Fto\u002Ffile.docx') as z:\n    tree = ET.parse(z.open('word\u002Fdocument.xml'))\n    print(''.join(t.text or '' for t in tree.iter('{http:\u002F\u002Fschemas.openxmlformats.org\u002Fwordprocessingml\u002F2006\u002Fmain}t')))\n\"\n\n# .doc (legacy, requires antiword or catdoc)\nantiword \u002Fpath\u002Fto\u002Ffile.doc 2>\u002Fdev\u002Fnull || catdoc \u002Fpath\u002Fto\u002Ffile.doc 2>\u002Fdev\u002Fnull\n```\n\n### `.pst` (Outlook archives)\n\n```bash\n# Validate first; many PSTs are null bytes\npython3 -c \"\nwith open('\u002Fpath\u002Fto\u002Ffile.pst', 'rb') as f:\n    print('Valid PST' if f.read(4) == b'!BDN' else 'CORRUPT\u002FNULL')\n\"\n# If valid:\nreadpst -o \u002Ftmp\u002Fpst-output \u002Fpath\u002Fto\u002Ffile.pst\n```\n\n### `.zip` \u002F `.tar` \u002F `.tar.gz`\n\nExtract to a temp dir, then recurse through the extracted tree.\n\n### Images\n\nNote existence + metadata (filename, size, date). Don't show unless the\nuser asks. Flag scans \u002F portraits as potentially personal.\n\n## Manifest template\n\n```markdown\n---\ntitle: \"[Archive Name] — Ingestion Status\"\ntype: project\ncreated: YYYY-MM-DD\nupdated: YYYY-MM-DD\nsource_type: \"[local|dropbox|...]\"\nscan_paths: [\"paths from gbrain.yml\"]\n---\n\n# [Archive Name] — Ingestion Status\n\n## Source\n- **Type:** [local|dropbox|...]\n- **Allow-listed paths:** [from gbrain.yml]\n- **Total files:** [N]\n- **Total size:** [X GB]\n- **Date range:** [earliest] — [latest]\n\n## Inventory\n\n### [Folder 1]\n| Item | Type | Size | Status | Reaction |\n|------|------|------|--------|----------|\n| file1.txt | text | 2KB | ✅ ingested | 🔥 \"exact quote\" |\n| file2.doc | doc | 15KB | ⏭️ skip | — |\n| file3.html | html | 4KB | ⬜ unseen | — |\n\n### [Folder 2]\n...\n\n## Priority Queue\n1. [Highest priority — why]\n2. [Next — why]\n...\n\n## Session Log\n\n### YYYY-MM-DD — [Session topic]\n- Reviewed: [list]\n- Reactions: [exact quotes]\n- Ingested: [brain pages created]\n- Next: [what's queued]\n```\n\n## When it fails\n\nFollow the [agent operator protocol](..\u002Fconventions\u002Fagent-operator-protocol.md) for any gbrain error `code`, exit code, `[AGENT]` block or notice block. Specific to this skill:\n\n- No `archive-crawler.scan_paths:` allow-list: this is the skill's own hard refusal. Ask the user which directories may be scanned; never widen the list yourself to get past it.\n- An archive mount, takeout or bucket is unreadable (permission, expired token): report the exact path that failed and stop that source; do not fall back to scanning a parent directory.\n- Filing a find returns `write_pending` (exit 10) or `revision_conflict`: poll `gbrain write-request \u003Crequest_id>` for the first; re-read the page and merge for the second. Never re-file under a new slug.\n\n## Anti-Patterns\n\n- ❌ Running without `archive-crawler.scan_paths:` set. Hard refusal.\n  This is the safety contract — never bypass.\n- ❌ Hardcoding era-specific filing paths (e.g., `originals\u002Farchive\u002F`,\n  `originals\u002Fyc-era\u002F`). Read filing rules at runtime instead.\n- ❌ Re-showing items already marked in the manifest. The user's time\n  is the scarcest resource.\n- ❌ Paraphrasing reactions. Exact words only.\n- ❌ Wrapping found content in lessons or takeaways. Let stories breathe.\n- ❌ Skipping back-links when content references people \u002F companies who\n  have brain pages. Iron Law per conventions\u002Fquality.md.\n\n## Related skills\n\n- `skills\u002Fvoice-note-ingest\u002FSKILL.md` — same exact-phrasing pattern for\n  audio capture\n- `skills\u002Fidea-ingest\u002FSKILL.md` — single-link-or-article ingest with\n  the same primary-subject filing rule\n- `skills\u002Fconventions\u002Fquality.md` — citations, back-links, voice\n\n\n## Contract\n\nThis skill guarantees:\n\n- Routing matches the canonical triggers in the frontmatter.\n- Output written under the directories listed in `writes_to:` (when applicable).\n- Conventions referenced (`quality.md`, `brain-first.md`, `_brain-filing-rules.md`) are followed.\n- Privacy contract preserved: no real names, no fork-specific filesystem path literals, no upstream-fork references.\n\nThe full behavior contract is documented in the body sections above; this section exists for the conformance test.\n\n## Output Format\n\nThe skill's output shape is documented inline in the body sections above (see \"Output\", \"Brain page format\", or equivalent). The literal section header here exists for the conformance test (`test\u002Fskills-conformance.test.ts`).\n",{"name":5,"version":24,"mutating":25,"triggers":26,"writes_to":32,"description":7,"when_to_use":36,"writes_pages":25},"0.1.0",true,[27,28,29,30,31],"crawl my archive","find gold in my archive","archive crawler","scan my dropbox for","mine my old files for",[33,34,35],"originals\u002F","personal\u002F","ideas\u002F","Use when the user asks: \"crawl my archive\", \"find gold in my archive\", \"archive crawler\", \"scan my dropbox for\", \"mine my old files for\".","feat\u002Flink-chat-distiller","b7935e119783c2f35d6d182ede452faf32de675c","plugin\u002Fskills\u002Farchive-crawler","https:\u002F\u002Fgithub.com\u002FcheRoma\u002Fgbrain-link-chat","https:\u002F\u002Fgithub.com\u002FcheRoma","https:\u002F\u002Fostov.dev","Engineer and founder of Ostov. Websites, Telegram apps, business automation and ERP\u002FCRM integrations.","2026-11-12 20:40:42",{"source":8,"skillName":5,"commands":46,"prompt":56,"zipAvailable":25},[47,50,53],{"tool":48,"command":49},"npx","npx skills add cheRoma\u002Fgbrain-link-chat --skill archive-crawler",{"tool":51,"command":52},"bunx","bunx skills add cheRoma\u002Fgbrain-link-chat --skill archive-crawler",{"tool":54,"command":55},"pnpm","pnpm dlx skills add cheRoma\u002Fgbrain-link-chat --skill archive-crawler","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FcheRoma\u002Fgbrain-link-chat\u002Fblob\u002Ffeat\u002Flink-chat-distiller\u002Fplugin\u002Fskills\u002Farchive-crawler\u002FSKILL.md",[58],{"path":59,"resourceType":60,"resourceTypeDesc":61,"sizeBytes":62,"sourceHtmlUrl":63},"routing-eval.jsonl","OTHER","其他",666,"https:\u002F\u002Fgithub.com\u002FcheRoma\u002Fgbrain-link-chat\u002Fblob\u002Ffeat\u002Flink-chat-distiller\u002Fplugin\u002Fskills\u002Farchive-crawler\u002Frouting-eval.jsonl",[65,71,77,84,91,98],{"skillNo":66,"name":67,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":68,"categories":69,"keywords":70,"publishedAt":19},"01M75M5HR90P229V66Q4Q1GM0W","query-helper","https:\u002F\u002Fgithub.com\u002FcheRoma\u002Fgbrain-link-chat\u002Fblob\u002Ffeat\u002Flink-chat-distiller\u002Ftest\u002Ffixtures\u002Fskill-catalog\u002Fskills\u002Fquery-helper\u002FSKILL.md",[],[],{"skillNo":72,"name":73,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":74,"categories":75,"keywords":76,"publishedAt":19},"01M75M5GZ1WQB7NHR07QV38YB8","broken","https:\u002F\u002Fgithub.com\u002FcheRoma\u002Fgbrain-link-chat\u002Fblob\u002Ffeat\u002Flink-chat-distiller\u002Ftest\u002Ffixtures\u002Fskill-catalog\u002Fskills\u002Fbroken\u002FSKILL.md",[],[],{"skillNo":78,"name":79,"nameZh":6,"description":80,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":81,"categories":82,"keywords":83,"publishedAt":19},"01M75M5FDJV3M4GP71SKD31P33","brain-ops","Read, enrich, and write brain pages with source attribution.","https:\u002F\u002Fgithub.com\u002FcheRoma\u002Fgbrain-link-chat\u002Fblob\u002Ffeat\u002Flink-chat-distiller\u002Ftest\u002Ffixtures\u002Fskill-catalog\u002Fskills\u002Fbrain-ops\u002FSKILL.md",[],[],{"skillNo":85,"name":86,"nameZh":6,"description":87,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":88,"categories":89,"keywords":90,"publishedAt":19},"01M75M5DYW3WBGDC6M90YMC843","meeting-prep","Build a briefing before you meet someone, from their recent threads, open loops and what they care about.","https:\u002F\u002Fgithub.com\u002FcheRoma\u002Fgbrain-link-chat\u002Fblob\u002Ffeat\u002Flink-chat-distiller\u002Ftest\u002Ffixtures\u002Fskill-catalog-query\u002Fskills\u002Fmeeting-prep\u002FSKILL.md",[],[],{"skillNo":92,"name":93,"nameZh":6,"description":94,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":95,"categories":96,"keywords":97,"publishedAt":19},"01M75M5CJZX22MV7XKJQYEMC9Y","inbox-zero","Triage the inbox into replies, delegations and archives.","https:\u002F\u002Fgithub.com\u002FcheRoma\u002Fgbrain-link-chat\u002Fblob\u002Ffeat\u002Flink-chat-distiller\u002Ftest\u002Ffixtures\u002Fskill-catalog-query\u002Fskills\u002Finbox-zero\u002FSKILL.md",[],[],{"skillNo":99,"name":100,"nameZh":6,"description":101,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":102,"categories":103,"keywords":104,"publishedAt":19},"01M75M5B953478ACM9X3MPAX3P","deal-memo","Draft an investment memo from the deal pages and the founder history already in the brain.","https:\u002F\u002Fgithub.com\u002FcheRoma\u002Fgbrain-link-chat\u002Fblob\u002Ffeat\u002Flink-chat-distiller\u002Ftest\u002Ffixtures\u002Fskill-catalog-query\u002Fskills\u002Fdeal-memo\u002FSKILL.md",[],[]]