---
description: Content idea bank manager — captures, mines, and ranks post ideas for LinkedIn and Substack. Three modes -- /idea for instant capture (5s), weekly mine for source-sweep (4 parallel sub-agents over project-logs / OpenCode session DB / Obsidian vault / readings), and /content-rank for "what should I post next." Outputs ~/.personal/content-bank/ideas.json. Skips ideas that overlap recent posts.
---

# personal-content-bank

The capture + mining + ranking layer of the content engine. Three modes; one data store.

## Trigger phrases

**Capture mode:**

- "Idea: [thought]"
- "Capture this thought: [thought]"
- `/idea [thought]`

**Mine mode:**

- "Mine ideas from this week"
- "Run weekly idea sweep"
- `/content-mine`
- Auto: launchd job Sunday 14:00 local

**Rank mode:**

- "What should I post next?"
- "Rank my content ideas"
- `/content-rank`

## Data store

`~/.personal/content-bank/ideas.json`. Schema:

```json
{
  "_meta": {
    "schema_version": 1,
    "next_id": 1,
    "themes_recently_covered": []
  },
  "ideas": [
    {
      "id": "IDEA-00001",
      "captured": "YYYY-MM-DD",
      "source": "voice-memo|obsidian|project-log|session-db|reading|manual",
      "raw_thought": "string",
      "themes": ["..."],
      "platform_fit": ["linkedin", "substack-long", "substack-short", "neither"],
      "status": "raw|drafted|scheduled|posted|dropped",
      "post_id": null,
      "engagement": null,
      "ranked_score": null,
      "notes": "..."
    }
  ]
}
```

## Capture mode (Tier 1, $0.001)

Minimal friction. The whole point is < 10 seconds from thought to captured.

1. Append a new idea to `ideas.json` with `status: raw`, `source: manual` (or detected from invocation context).
2. Auto-generate next `IDEA-NNNNN` ID.
3. Confirm with assigned ID and total count.

NO judgment, NO drafting, NO platform-fit guessing at capture time. Capture is for the *thought*. Triage happens later.

If the user says "Idea: AI agents are eating CRMs", you write:

```json
{
  "id": "IDEA-00042",
  "captured": "2026-05-09",
  "source": "manual",
  "raw_thought": "AI agents are eating CRMs",
  "themes": [],
  "platform_fit": [],
  "status": "raw"
}
```

Done in < 1 second. Themes/platform_fit get filled in by the mine pass later.

## Mine mode (Tier 2 sub-agents, ~$0.15 per run)

Weekly sweep. Fires 4 parallel `research` sub-agents (Tier 2 Haiku):

1. **Project-log miner** — reads `~/Documents/OpenCode Working Folder/*/project-log.md` from last 7 days, extracts decisions/observations/learnings worth a post.
2. **Session DB miner** — queries `~/.local/share/opencode/opencode.db` for sessions with substantive output in last 7 days, extracts themes.
3. **Obsidian miner** — walks `~/.personal/vault/` for notes tagged `#idea` or modified-and-#post-candidate.
4. **Reading miner** — checks `~/.career/reading-log.md` (if exists) and any RSS/Readwise sync output for recent reads worth commenting on.

Each sub-agent returns ≤300 tokens of "candidate ideas with sourced evidence."

Main session (Tier 3) synthesizes:

- Dedupes against existing `ideas.json` (don't re-capture)
- Tags themes
- Assigns `platform_fit` per candidate (LinkedIn / Substack-long / Substack-short / neither)
- Appends new ideas with `source: <miner>`, status: raw

After mine, update `_meta.themes_recently_covered` from `posted` ideas in the last 30 days. This feeds the rank mode.

## Rank mode (Tier 2 main, ~$0.02 per call)

When user asks "what should I post next":

1. Load `ideas.json` filtered to `status: raw` or `drafted`
2. Score each:
   - **Freshness:** when captured (recent = higher) BUT against:
   - **Theme repetition penalty:** if theme appears in `themes_recently_covered`, downweight
   - **Platform demand:** if user said "for LinkedIn" or "for Substack", filter by `platform_fit`
   - **Strength signal:** raw_thought length, source (project-log > random thought), evidence linked
3. Return top 5 with rationale: "IDEA-00042 — [thought] — fits LinkedIn, fresh take, theme not covered in 30d."

Output format:

```markdown
## Top 5 ideas to post next

### 1. IDEA-00042 — "AI agents are eating CRMs"
**Platform fit:** LinkedIn (220 words, hot take)
**Why now:** Captured Tuesday, themes [agents, crm-future] not covered in 30d, ranks high on freshness + uniqueness.
**Suggested next:** `/linkedin IDEA-00042`

### 2. ...

## What I'd skip this week

- IDEA-00031 "[old]" — captured 14 days ago, theme [observability] covered POST-00007 last week
- IDEA-00038 "[stale]" — vague, expand or drop
```

## Dropping ideas

If an idea sits at `status: raw` for >60 days:

- Surface in next rank: "Drop or keep? IDEA-NNNNN has been raw for 60d."
- User says drop → `status: dropped`, `notes: "stale at 60d"`

## Integration with other skills

- `personal-linkedin-drafter` reads `ideas.json` to start from an idea ID
- `personal-substack-drafter` same
- `personal-content-repurpose` reads `posted` ideas to find candidates for cross-platform
- `personal-tracker` also writes `POST-NNNNN` items linked to `IDEA-NNNNN` when posts are scheduled

## Discipline

- **Capture is sacred.** Don't add friction at capture. NO required fields beyond raw_thought.
- **Mining doesn't draft.** Mining produces idea objects; drafting is a separate skill on demand.
- **Ranking surfaces, doesn't decide.** User picks. AI suggests.
- **Theme dedup is real.** If you posted about agents 3 days ago, don't surface another agents idea unless it's a sharp new angle.

## Privacy

`ideas.json` may contain raw thoughts that aren't fit for anyone else's eyes. Lives in `~/.personal/`, gitignored. Don't surface raw thoughts in any cloud-MCP call beyond what the drafting skills explicitly need.
