<memvid-mind-context>
# 🧠 Claude Mind Ready

📁 Project: **obsidian**
💾 Memory will be created at: `.claude/mind.mv2`

_Your observations will be automatically captured._
</memvid-mind-context>


<EXTREMELY_IMPORTANT>
You have superpowers.

**Below is the full content of your 'superpowers:using-superpowers' skill - your introduction to using skills. For all other skills, use the 'Skill' tool:**

---
name: using-superpowers
description: Use when starting any conversation - establishes how to find and use skills, requiring Skill tool invocation before ANY response including clarifying questions
---

<SUBAGENT-STOP>
If you were dispatched as a subagent to execute a specific task, skip this skill.
</SUBAGENT-STOP>

<EXTREMELY-IMPORTANT>
If you think there is even a 1% chance a skill might apply to what you are doing, you ABSOLUTELY MUST invoke the skill.

IF A SKILL APPLIES TO YOUR TASK, YOU DO NOT HAVE A CHOICE. YOU MUST USE IT.

This is not negotiable. This is not optional. You cannot rationalize your way out of this.
</EXTREMELY-IMPORTANT>

## Instruction Priority

Superpowers skills override default system prompt behavior, but **user instructions always take precedence**:

1. **User's explicit instructions** (CLAUDE.md, GEMINI.md, AGENTS.md, direct requests) — highest priority
2. **Superpowers skills** — override default system behavior where they conflict
3. **Default system prompt** — lowest priority

If CLAUDE.md, GEMINI.md, or AGENTS.md says "don't use TDD" and a skill says "always use TDD," follow the user's instructions. The user is in control.

## How to Access Skills

**In Claude Code:** Use the `Skill` tool. When you invoke a skill, its content is loaded and presented to you—follow it directly. Never use the Read tool on skill files.

**In Copilot CLI:** Use the `skill` tool. Skills are auto-discovered from installed plugins. The `skill` tool works the same as Claude Code's `Skill` tool.

**In Gemini CLI:** Skills activate via the `activate_skill` tool. Gemini loads skill metadata at session start and activates the full content on demand.

**In other environments:** Check your platform's documentation for how skills are loaded.

## Platform Adaptation

Skills use Claude Code tool names. Non-CC platforms: see `references/copilot-tools.md` (Copilot CLI), `references/codex-tools.md` (Codex) for tool equivalents. Gemini CLI users get the tool mapping loaded automatically via GEMINI.md.

# Using Skills

## The Rule

**Invoke relevant or requested skills BEFORE any response or action.** Even a 1% chance a skill might apply means that you should invoke the skill to check. If an invoked skill turns out to be wrong for the situation, you don't need to use it.

```dot
digraph skill_flow {
    "User message received" [shape=doublecircle];
    "About to EnterPlanMode?" [shape=doublecircle];
    "Already brainstormed?" [shape=diamond];
    "Invoke brainstorming skill" [shape=box];
    "Might any skill apply?" [shape=diamond];
    "Invoke Skill tool" [shape=box];
    "Announce: 'Using [skill] to [purpose]'" [shape=box];
    "Has checklist?" [shape=diamond];
    "Create TodoWrite todo per item" [shape=box];
    "Follow skill exactly" [shape=box];
    "Respond (including clarifications)" [shape=doublecircle];

    "About to EnterPlanMode?" -> "Already brainstormed?";
    "Already brainstormed?" -> "Invoke brainstorming skill" [label="no"];
    "Already brainstormed?" -> "Might any skill apply?" [label="yes"];
    "Invoke brainstorming skill" -> "Might any skill apply?";

    "User message received" -> "Might any skill apply?";
    "Might any skill apply?" -> "Invoke Skill tool" [label="yes, even 1%"];
    "Might any skill apply?" -> "Respond (including clarifications)" [label="definitely not"];
    "Invoke Skill tool" -> "Announce: 'Using [skill] to [purpose]'";
    "Announce: 'Using [skill] to [purpose]'" -> "Has checklist?";
    "Has checklist?" -> "Create TodoWrite todo per item" [label="yes"];
    "Has checklist?" -> "Follow skill exactly" [label="no"];
    "Create TodoWrite todo per item" -> "Follow skill exactly";
}
```

## Red Flags

These thoughts mean STOP—you're rationalizing:

| Thought | Reality |
|---------|---------|
| "This is just a simple question" | Questions are tasks. Check for skills. |
| "I need more context first" | Skill check comes BEFORE clarifying questions. |
| "Let me explore the codebase first" | Skills tell you HOW to explore. Check first. |
| "I can check git/files quickly" | Files lack conversation context. Check for skills. |
| "Let me gather information first" | Skills tell you HOW to gather information. |
| "This doesn't need a formal skill" | If a skill exists, use it. |
| "I remember this skill" | Skills evolve. Read current version. |
| "This doesn't count as a task" | Action = task. Check for skills. |
| "The skill is overkill" | Simple things become complex. Use it. |
| "I'll just do this one thing first" | Check BEFORE doing anything. |
| "This feels productive" | Undisciplined action wastes time. Skills prevent this. |
| "I know what that means" | Knowing the concept ≠ using the skill. Invoke it. |

## Skill Priority

When multiple skills could apply, use this order:

1. **Process skills first** (brainstorming, debugging) - these determine HOW to approach the task
2. **Implementation skills second** (frontend-design, mcp-builder) - these guide execution

"Let's build X" → brainstorming first, then implementation skills.
"Fix this bug" → debugging first, then domain-specific skills.

## Skill Types

**Rigid** (TDD, debugging): Follow exactly. Don't adapt away discipline.

**Flexible** (patterns): Adapt principles to context.

The skill itself tells you which.

## User Instructions

Instructions say WHAT, not HOW. "Add X" or "Fix Y" doesn't mean skip workflows.

</EXTREMELY_IMPORTANT>


<memvid-mind-context>
# 🧠 Claude Mind Ready

📁 Project: **obsidian**
💾 Memory will be created at: `.claude/mind.mv2`

_Your observations will be automatically captured._
</memvid-mind-context>

<EXTREMELY_IMPORTANT>
You have superpowers.

**Below is the full content of your 'superpowers:using-superpowers' skill - your introduction to using skills. For all other skills, use the 'Skill' tool:**

---
name: using-superpowers
description: Use when starting any conversation - establishes how to find and use skills, requiring Skill tool invocation before ANY response including clarifying questions
---

<SUBAGENT-STOP>
If you were dispatched as a subagent to execute a specific task, skip this skill.
</SUBAGENT-STOP>

<EXTREMELY-IMPORTANT>
If you think there is even a 1% chance a skill might apply to what you are doing, you ABSOLUTELY MUST invoke the skill.

IF A SKILL APPLIES TO YOUR TASK, YOU DO NOT HAVE A CHOICE. YOU MUST USE IT.

This is not negotiable. This is not optional. You cannot rationalize your way out of this.
</EXTREMELY-IMPORTANT>

## Instruction Priority

Superpowers skills override default system prompt behavior, but **user instructions always take precedence**:

1. **User's explicit instructions** (CLAUDE.md, GEMINI.md, AGENTS.md, direct requests) — highest priority
2. **Superpowers skills** — override default system behavior where they conflict
3. **Default system prompt** — lowest priority

If CLAUDE.md, GEMINI.md, or AGENTS.md says "don't use TDD" and a skill says "always use TDD," follow the user's instructions. The user is in control.

## How to Access Skills

**In Claude Code:** Use the `Skill` tool. When you invoke a skill, its content is loaded and presented to you—follow it directly. Never use the Read tool on skill files.

**In Copilot CLI:** Use the `skill` tool. Skills are auto-discovered from installed plugins. The `skill` tool works the same as Claude Code's `Skill` tool.

**In Gemini CLI:** Skills activate via the `activate_skill` tool. Gemini loads skill metadata at session start and activates the full content on demand.

**In other environments:** Check your platform's documentation for how skills are loaded.

## Platform Adaptation

Skills use Claude Code tool names. Non-CC platforms: see `references/copilot-tools.md` (Copilot CLI), `references/codex-tools.md` (Codex) for tool equivalents. Gemini CLI users get the tool mapping loaded automatically via GEMINI.md.

# Using Skills

## The Rule

**Invoke relevant or requested skills BEFORE any response or action.** Even a 1% chance a skill might apply means that you should invoke the skill to check. If an invoked skill turns out to be wrong for the situation, you don't need to use it.

```dot
digraph skill_flow {
    "User message received" [shape=doublecircle];
    "About to EnterPlanMode?" [shape=doublecircle];
    "Already brainstormed?" [shape=diamond];
    "Invoke brainstorming skill" [shape=box];
    "Might any skill apply?" [shape=diamond];
    "Invoke Skill tool" [shape=box];
    "Announce: 'Using [skill] to [purpose]'" [shape=box];
    "Has checklist?" [shape=diamond];
    "Create TodoWrite todo per item" [shape=box];
    "Follow skill exactly" [shape=box];
    "Respond (including clarifications)" [shape=doublecircle];

    "About to EnterPlanMode?" -> "Already brainstormed?";
    "Already brainstormed?" -> "Invoke brainstorming skill" [label="no"];
    "Already brainstormed?" -> "Might any skill apply?" [label="yes"];
    "Invoke brainstorming skill" -> "Might any skill apply?";

    "User message received" -> "Might any skill apply?";
    "Might any skill apply?" -> "Invoke Skill tool" [label="yes, even 1%"];
    "Might any skill apply?" -> "Respond (including clarifications)" [label="definitely not"];
    "Invoke Skill tool" -> "Announce: 'Using [skill] to [purpose]'";
    "Announce: 'Using [skill] to [purpose]'" -> "Has checklist?";
    "Has checklist?" -> "Create TodoWrite todo per item" [label="yes"];
    "Has checklist?" -> "Follow skill exactly" [label="no"];
    "Create TodoWrite todo per item" -> "Follow skill exactly";
}
```

## Red Flags

These thoughts mean STOP—you're rationalizing:

| Thought | Reality |
|---------|---------|
| "This is just a simple question" | Questions are tasks. Check for skills. |
| "I need more context first" | Skill check comes BEFORE clarifying questions. |
| "Let me explore the codebase first" | Skills tell you HOW to explore. Check first. |
| "I can check git/files quickly" | Files lack conversation context. Check for skills. |
| "Let me gather information first" | Skills tell you HOW to gather information. |
| "This doesn't need a formal skill" | If a skill exists, use it. |
| "I remember this skill" | Skills evolve. Read current version. |
| "This doesn't count as a task" | Action = task. Check for skills. |
| "The skill is overkill" | Simple things become complex. Use it. |
| "I'll just do this one thing first" | Check BEFORE doing anything. |
| "This feels productive" | Undisciplined action wastes time. Skills prevent this. |
| "I know what that means" | Knowing the concept ≠ using the skill. Invoke it. |

## Skill Priority

When multiple skills could apply, use this order:

1. **Process skills first** (brainstorming, debugging) - these determine HOW to approach the task
2. **Implementation skills second** (frontend-design, mcp-builder) - these guide execution

"Let's build X" → brainstorming first, then implementation skills.
"Fix this bug" → debugging first, then domain-specific skills.

## Skill Types

**Rigid** (TDD, debugging): Follow exactly. Don't adapt away discipline.

**Flexible** (patterns): Adapt principles to context.

The skill itself tells you which.

## User Instructions

Instructions say WHAT, not HOW. "Add X" or "Fix Y" doesn't mean skip workflows.

</EXTREMELY_IMPORTANT>


The current directory is the base path to my Obsidian notes, I would like to write either a small utility (in go lang?) or a bash script, or maybe there is some other methodology we could use? I want to encrypt these before commiting them to a private github repo. I would like it be configurable so that maybe it looks for a special file in the directory that has some basic configuration and if that file exists then it encrypts every file/note in that directory recursively? Thoughts?


## claude.ai Context7
Use this server to fetch current documentation whenever the user asks about a library, framework, SDK, API, CLI tool, or cloud service -- even well-known ones like React, Next.js, Prisma, Express, Tailwind, Django, or Spring Boot. This includes API syntax, configuration, version migration, library-specific debugging, setup instructions, and CLI tool usage. Use even when you think you know the answer -- your training data may not reflect recent changes. Prefer this over web search for library docs.

Do not use for: refactoring, writing scripts from scratch, debugging business logic, code review, or general programming concepts.


- update-config: Use this skill to configure the Claude Code harness via settings.json. Automated behaviors ("from now on when X", "each time X", "whenever X", "before/after X") require hooks configured in settings.json - the harness executes these, not Claude, so memory/preferences cannot fulfill them. Also use for: permissions ("allow X", "add permission", "move permission to"), env vars ("set X=Y"), hook troubleshooting, or any changes to settings.json/settings.local.json files. Examples: "allow npm commands", "add bq permission to global settings", "move permission to user settings", "set DEBUG=true", "when claude stops show X". For simple settings like theme/model, suggest the /config command.
- keybindings-help: Use when the user wants to customize keyboard shortcuts, rebind keys, add chord bindings, or modify ~/.claude/keybindings.json. Examples: "rebind ctrl+s", "add a chord shortcut", "change the submit key", "customize keybindings".
- simplify: Review changed code for reuse, quality, and efficiency, then fix any issues found.
- fewer-permission-prompts: Scan your transcripts for common read-only Bash and MCP tool calls, then add a prioritized allowlist to project .claude/settings.json to reduce permission prompts.
- loop: Run a prompt or slash command on a recurring interval (e.g. /loop 5m /foo). Omit the interval to let the model self-pace. - When the user wants to set up a recurring task, poll for status, or run something repeatedly on an interval (e.g. "check the deploy every 5 minutes", "keep running /babysit-prs"). Do NOT invoke for one-off tasks.
- schedule: Create, update, list, or run scheduled remote agents (routines) that execute on a cron schedule. - When the user wants to schedule a recurring or one-time remote agent ("run this every Monday", "open a cleanup PR for X in 2 weeks"), or to manage existing routines. ALSO OFFER PROACTIVELY: after you finish work that has a natural future follow-up, end your reply with a one-line offer to schedule a background agent to do it. Strong signals: a feature flag / gate / experiment / staged rollout was just shipped (offer a one-time agent in ~2 weeks to open a cleanup PR or evaluate results), a new alert/monitor was created (offer a recurring agent to triage it), a TODO/migration with a "remove once X" condition was left behind (offer a one-time agent to do the removal). Skip the offer for refactors, bug fixes, and anything that is done once it ships. Name a concrete action and cadence ("in 2 weeks", "every Monday") and only offer when the run just succeeded — do not pitch a schedule for something that has not happened yet.
- claude-api: Build, debug, and optimize Claude API / Anthropic SDK apps. Apps built with this skill should include prompt caching. Also handles migrating existing Claude API code between Claude model versions (4.5 → 4.6, 4.6 → 4.7, retired-model replacements).
TRIGGER when: code imports `anthropic`/`@anthropic-ai/sdk`; user asks for the Claude API, Anthropic SDK, or Managed Agents; user adds/modifies/tunes a Claude feature (caching, thinking, compaction, tool use, batch, files, citations, memory) or model (Opus/Sonnet/Haiku) in a file; questions about prompt caching / cache hit rate in an Anthropic SDK project.
SKIP: file imports `openai`/other-provider SDK, filename like `*-openai.py`/`*-generic.py`, provider-neutral code, general programming/ML.
- obsidian-load: Load context from Obsidian notes in the `Claude/` directory into the current conversation.
- obsidian-save: Save current conversation context to an Obsidian note under the `Claude/` directory.
- superpowers:execute-plan: Deprecated - use the superpowers:executing-plans skill instead
- superpowers:write-plan: Deprecated - use the superpowers:writing-plans skill instead
- superpowers:brainstorm: Deprecated - use the superpowers:brainstorming skill instead
- mind:stats: Show memory statistics and storage information
- mind:search: Search memories for specific content or patterns
- mind:recent: Show recent memories and activity timeline
- mind:ask: Ask questions about memories and get context-aware answers
- superpowers:brainstorming: You MUST use this before any creative work - creating features, building components, adding functionality, or modifying behavior. Explores user intent, requirements and design before implementation.
- superpowers:using-superpowers: Use when starting any conversation - establishes how to find and use skills, requiring Skill tool invocation before ANY response including clarifying questions
- superpowers:writing-plans: Use when you have a spec or requirements for a multi-step task, before touching code
- superpowers:systematic-debugging: Use when encountering any bug, test failure, or unexpected behavior, before proposing fixes
- superpowers:subagent-driven-development: Use when executing implementation plans with independent tasks in the current session
- superpowers:receiving-code-review: Use when receiving code review feedback, before implementing suggestions, especially if feedback seems unclear or technically questionable - requires technical rigor and verification, not performative agreement or blind implementation
- superpowers:requesting-code-review: Use when completing tasks, implementing major features, or before merging to verify work meets requirements
- superpowers:test-driven-development: Use when implementing any feature or bugfix, before writing implementation code
- superpowers:verification-before-completion: Use when about to claim work is complete, fixed, or passing, before committing or creating PRs - requires running verification commands and confirming output before making any success claims; evidence before assertions always
- superpowers:executing-plans: Use when you have a written implementation plan to execute in a separate session with review checkpoints
- superpowers:dispatching-parallel-agents: Use when facing 2+ independent tasks that can be worked on without shared state or sequential dependencies
- superpowers:finishing-a-development-branch: Use when implementation is complete, all tests pass, and you need to decide how to integrate the work - guides completion of development work by presenting structured options for merge, PR, or cleanup
- superpowers:using-git-worktrees: Use when starting feature work that needs isolation from current workspace or before executing implementation plans - creates isolated git worktrees with smart directory selection and safety verification
- superpowers:writing-skills: Use when creating new skills, editing existing skills, or verifying skills work before deployment
- mind:memory: Claude Mind - Search and manage Claude's persistent memory stored in a single portable .mv2 file
- mind:mind: Claude Mind - Search and manage Claude's persistent memory stored in a single portable .mv2 file
- init: Initialize a new CLAUDE.md file with codebase documentation
- review: Review a pull request
- security-review: Complete a security review of the pending changes on the current branch


Encrypt Obsidian notes before GitHub commit


Launching skill: superpowers:brainstorming


Base directory for this skill: /Users/steve.briggs/.claude/plugins/cache/claude-plugins-official/superpowers/5.0.7/skills/brainstorming

# Brainstorming Ideas Into Designs

Help turn ideas into fully formed designs and specs through natural collaborative dialogue.

Start by understanding the current project context, then ask questions one at a time to refine the idea. Once you understand what you're building, present the design and get user approval.

<HARD-GATE>
Do NOT invoke any implementation skill, write any code, scaffold any project, or take any implementation action until you have presented a design and the user has approved it. This applies to EVERY project regardless of perceived simplicity.
</HARD-GATE>

## Anti-Pattern: "This Is Too Simple To Need A Design"

Every project goes through this process. A todo list, a single-function utility, a config change — all of them. "Simple" projects are where unexamined assumptions cause the most wasted work. The design can be short (a few sentences for truly simple projects), but you MUST present it and get approval.

## Checklist

You MUST create a task for each of these items and complete them in order:

1. **Explore project context** — check files, docs, recent commits
2. **Offer visual companion** (if topic will involve visual questions) — this is its own message, not combined with a clarifying question. See the Visual Companion section below.
3. **Ask clarifying questions** — one at a time, understand purpose/constraints/success criteria
4. **Propose 2-3 approaches** — with trade-offs and your recommendation
5. **Present design** — in sections scaled to their complexity, get user approval after each section
6. **Write design doc** — save to `docs/superpowers/specs/YYYY-MM-DD-<topic>-design.md` and commit
7. **Spec self-review** — quick inline check for placeholders, contradictions, ambiguity, scope (see below)
8. **User reviews written spec** — ask user to review the spec file before proceeding
9. **Transition to implementation** — invoke writing-plans skill to create implementation plan

## Process Flow

```dot
digraph brainstorming {
    "Explore project context" [shape=box];
    "Visual questions ahead?" [shape=diamond];
    "Offer Visual Companion\n(own message, no other content)" [shape=box];
    "Ask clarifying questions" [shape=box];
    "Propose 2-3 approaches" [shape=box];
    "Present design sections" [shape=box];
    "User approves design?" [shape=diamond];
    "Write design doc" [shape=box];
    "Spec self-review\n(fix inline)" [shape=box];
    "User reviews spec?" [shape=diamond];
    "Invoke writing-plans skill" [shape=doublecircle];

    "Explore project context" -> "Visual questions ahead?";
    "Visual questions ahead?" -> "Offer Visual Companion\n(own message, no other content)" [label="yes"];
    "Visual questions ahead?" -> "Ask clarifying questions" [label="no"];
    "Offer Visual Companion\n(own message, no other content)" -> "Ask clarifying questions";
    "Ask clarifying questions" -> "Propose 2-3 approaches";
    "Propose 2-3 approaches" -> "Present design sections";
    "Present design sections" -> "User approves design?";
    "User approves design?" -> "Present design sections" [label="no, revise"];
    "User approves design?" -> "Write design doc" [label="yes"];
    "Write design doc" -> "Spec self-review\n(fix inline)";
    "Spec self-review\n(fix inline)" -> "User reviews spec?";
    "User reviews spec?" -> "Write design doc" [label="changes requested"];
    "User reviews spec?" -> "Invoke writing-plans skill" [label="approved"];
}
```

**The terminal state is invoking writing-plans.** Do NOT invoke frontend-design, mcp-builder, or any other implementation skill. The ONLY skill you invoke after brainstorming is writing-plans.

## The Process

**Understanding the idea:**

- Check out the current project state first (files, docs, recent commits)
- Before asking detailed questions, assess scope: if the request describes multiple independent subsystems (e.g., "build a platform with chat, file storage, billing, and analytics"), flag this immediately. Don't spend questions refining details of a project that needs to be decomposed first.
- If the project is too large for a single spec, help the user decompose into sub-projects: what are the independent pieces, how do they relate, what order should they be built? Then brainstorm the first sub-project through the normal design flow. Each sub-project gets its own spec → plan → implementation cycle.
- For appropriately-scoped projects, ask questions one at a time to refine the idea
- Prefer multiple choice questions when possible, but open-ended is fine too
- Only one question per message - if a topic needs more exploration, break it into multiple questions
- Focus on understanding: purpose, constraints, success criteria

**Exploring approaches:**

- Propose 2-3 different approaches with trade-offs
- Present options conversationally with your recommendation and reasoning
- Lead with your recommended option and explain why

**Presenting the design:**

- Once you believe you understand what you're building, present the design
- Scale each section to its complexity: a few sentences if straightforward, up to 200-300 words if nuanced
- Ask after each section whether it looks right so far
- Cover: architecture, components, data flow, error handling, testing
- Be ready to go back and clarify if something doesn't make sense

**Design for isolation and clarity:**

- Break the system into smaller units that each have one clear purpose, communicate through well-defined interfaces, and can be understood and tested independently
- For each unit, you should be able to answer: what does it do, how do you use it, and what does it depend on?
- Can someone understand what a unit does without reading its internals? Can you change the internals without breaking consumers? If not, the boundaries need work.
- Smaller, well-bounded units are also easier for you to work with - you reason better about code you can hold in context at once, and your edits are more reliable when files are focused. When a file grows large, that's often a signal that it's doing too much.

**Working in existing codebases:**

- Explore the current structure before proposing changes. Follow existing patterns.
- Where existing code has problems that affect the work (e.g., a file that's grown too large, unclear boundaries, tangled responsibilities), include targeted improvements as part of the design - the way a good developer improves code they're working in.
- Don't propose unrelated refactoring. Stay focused on what serves the current goal.

## After the Design

**Documentation:**

- Write the validated design (spec) to `docs/superpowers/specs/YYYY-MM-DD-<topic>-design.md`
  - (User preferences for spec location override this default)
- Use elements-of-style:writing-clearly-and-concisely skill if available
- Commit the design document to git

**Spec Self-Review:**
After writing the spec document, look at it with fresh eyes:

1. **Placeholder scan:** Any "TBD", "TODO", incomplete sections, or vague requirements? Fix them.
2. **Internal consistency:** Do any sections contradict each other? Does the architecture match the feature descriptions?
3. **Scope check:** Is this focused enough for a single implementation plan, or does it need decomposition?
4. **Ambiguity check:** Could any requirement be interpreted two different ways? If so, pick one and make it explicit.

Fix any issues inline. No need to re-review — just fix and move on.

**User Review Gate:**
After the spec review loop passes, ask the user to review the written spec before proceeding:

> "Spec written and committed to `<path>`. Please review it and let me know if you want to make any changes before we start writing out the implementation plan."

Wait for the user's response. If they request changes, make them and re-run the spec review loop. Only proceed once the user approves.

**Implementation:**

- Invoke the writing-plans skill to create a detailed implementation plan
- Do NOT invoke any other skill. writing-plans is the next step.

## Key Principles

- **One question at a time** - Don't overwhelm with multiple questions
- **Multiple choice preferred** - Easier to answer than open-ended when possible
- **YAGNI ruthlessly** - Remove unnecessary features from all designs
- **Explore alternatives** - Always propose 2-3 approaches before settling
- **Incremental validation** - Present design, get approval before moving on
- **Be flexible** - Go back and clarify when something doesn't make sense

## Visual Companion

A browser-based companion for showing mockups, diagrams, and visual options during brainstorming. Available as a tool — not a mode. Accepting the companion means it's available for questions that benefit from visual treatment; it does NOT mean every question goes through the browser.

**Offering the companion:** When you anticipate that upcoming questions will involve visual content (mockups, layouts, diagrams), offer it once for consent:
> "Some of what we're working on might be easier to explain if I can show it to you in a web browser. I can put together mockups, diagrams, comparisons, and other visuals as we go. This feature is still new and can be token-intensive. Want to try it? (Requires opening a local URL)"

**This offer MUST be its own message.** Do not combine it with clarifying questions, context summaries, or any other content. The message should contain ONLY the offer above and nothing else. Wait for the user's response before continuing. If they decline, proceed with text-only brainstorming.

**Per-question decision:** Even after the user accepts, decide FOR EACH QUESTION whether to use the browser or the terminal. The test: **would the user understand this better by seeing it than reading it?**

- **Use the browser** for content that IS visual — mockups, wireframes, layout comparisons, architecture diagrams, side-by-side visual designs
- **Use the terminal** for content that is text — requirements questions, conceptual choices, tradeoff lists, A/B/C/D text options, scope decisions

A question about a UI topic is not automatically a visual question. "What does personality mean in this context?" is a conceptual question — use the terminal. "Which wizard layout works better?" is a visual question — use the browser.

If they agree to the companion, read the detailed guide before proceeding:
`skills/brainstorming/visual-companion.md`


The current directory is the base path to my Obsidian notes, I would like to write either a small utility (in go lang?) or a bash script, or maybe there is some other methodology we could use? I want…


Let me first peek at the project context before diving in, Sir Charles of St Cheese.


Bash

ls -la /Users/steve.briggs/Documents/obsidian/ 2>&1 | head -30

List Obsidian directory contents


git status 2>&1 | head -20 && echo "---" && git remote -v 2>&1

Check git status and remotes


Error: Exit code 128
fatal: not a git repository (or any of the parent directories): .git
---
fatal: not a git repository (or any of the parent directories): .git


<tool_use_error>Cancelled: parallel tool call Bash(git status 2>&1 | head -20 && echo "---"…) errored</tool_use_error>


ls -la /Users/steve.briggs/Documents/obsidian/ 2>&1 | head -40

List obsidian directory


drwx------ steve.briggs staff 2.1 KB Wed Apr 29 16:55:50 2026 ..
drwxr-xr-x steve.briggs staff  96 B  Wed Apr 29 16:55:53 2026 .
drwxr-xr-x steve.briggs staff 256 B  Thu Apr 30 12:09:14 2026 home


Pretty bare directory — just a `home/` folder, not yet a git repo. Good blank slate.

Before I start sketching utilities, I want to make sure we're solving the right problem, because there's a non-trivial chance the answer is "use an existing tool, not a custom one." A few questions, one at a time.

**Question 1 — Threat model.** What are you actually defending against by encrypting? This drives almost everything else:

**A.** *GitHub itself / the network.* You don't trust GitHub (or anyone with read access to the repo) to see plaintext. Even though it's private, you want zero-knowledge storage.

**B.** *Accidental exposure.* Mostly worried about the repo accidentally going public, a leaked token, or a stolen laptop with cached creds. Private repo is "probably fine" but encryption is belt-and-suspenders.

**C.** *Specific sensitive notes only.* Most notes are mundane; a handful have credentials/personal stuff. You want those encrypted, the rest in the clear.

**D.** *Something else* — tell me.

The reason this matters: if it's **(A)**, we want strong client-side encryption with a key that never touches GitHub, and we should look hard at `git-crypt` or `age` before writing anything ourselves. If it's **(B)**, a simpler symmetric-blob-on-commit approach is fine. If it's **(C)**, we don't want to encrypt-everything at all — we want a marker/ignore pattern. Which one fits?


afplay ~/.claude/sounds/mario/stop/stomp.wav 2>/dev/null || true


Mostly B, accidental exposure


Good — that opens up simpler options. Next fork in the road:

**Question 2 — Single machine, or syncing across machines?** Are you using this repo as:

**A.** *Backup only.* One machine writes, GitHub is the offsite copy. You'd basically never `git pull` to restore — only if the laptop dies.

**B.** *Sync across machines.* You edit on a laptop, push, then pull on a desktop / phone / work machine and keep editing.

**C.** *Single machine for now, but might want multi-machine later.*

This matters a lot because:

- If **(A)**, the dead-simple answer is "tar the whole vault, encrypt the tarball with `age`, commit one blob." A 30-line bash script does it. No per-file anything.
- If **(B)**, you need *per-file* encryption so git can diff/merge sanely across machines, and you really want transparent encryption (plaintext on disk, ciphertext in the repo). At that point `git-crypt` already does exactly what you described — a marker file (`.gitattributes`) tells it which paths to encrypt — and writing a custom Go tool to reinvent it would be… well, a fun afternoon, but probably not the right call given the threat model is just accidental exposure.
- If **(C)**, I'd lean toward designing for (B) from the start so you don't have to migrate later.

Which is it?


I would like to sync the file across multiple machines so B.


Right, so that locks us in: per-file encryption, plaintext on disk, ciphertext in the repo. Here are the three approaches I'd consider, in order of how much code Sir Charles of St Cheese has to maintain:

---

**Approach 1 — Just use `git-crypt` (recommended, and yes, I know that's not what you asked for)**

Install once (`brew install git-crypt`), run `git-crypt init` in the vault, and add a `.gitattributes` line like `*.md filter=git-crypt diff=git-crypt`. Push to GitHub: ciphertext. Clone on a second machine, `git-crypt unlock` with the exported key, plaintext reappears. Uses AES-256 in GCM-ish mode. Battle-tested since 2013.

- *Pro:* Zero code to write, zero code to maintain, exactly the marker-file UX you described (`.gitattributes` *is* the config file).
- *Con:* Filename leakage — git-crypt encrypts contents but commit metadata (filenames, sizes, mtimes) is plaintext. For threat model **B**, that's fine: someone glancing at a leaked repo sees `daily-notes/2026-04-30.md` but no contents.
- *The honest take:* Given the threat model is "belt-and-suspenders for an already-private repo," writing a Go utility to reinvent this is a hobby project, not an engineering decision. I'll happily help you build the hobby project, but I'd be a bad engineer if I didn't say it out loud.

**Approach 2 — Custom Go tool wrapping `age`, wired into git filters**

Write a small Go binary that acts as a `clean`/`smudge` filter using [`age`](https://age-encryption.org/) under the hood (there's a decent Go library: `filippo.io/age`). Config file in the vault root (say, `.vault-encrypt.yaml`) lists glob patterns to encrypt. Tool reads it, registers itself as a git filter via `.gitattributes`. Same end result as git-crypt, but you control the format and the key handling.

- *Pro:* You own the code. You can add features git-crypt doesn't (per-folder keys, key rotation, compress-then-encrypt, whatever).
- *Con:* You have to get filter semantics right (idempotency, deterministic output for the same plaintext+key — otherwise every `git status` looks dirty). Non-trivial footgun.

**Approach 3 — Custom Go tool, no git filters, parallel ciphertext tree**

Plaintext stays in `home/` (gitignored). A pre-commit hook (or a manual `vault sync` command) walks the tree, encrypts changed files into `home.enc/`, commits *that*. On pull, you run `vault decrypt` to repopulate `home/`.

- *Pro:* Easy to reason about. No git filter weirdness. Diffing in the GitHub UI is useless either way (it's encrypted), so no real loss.
- *Con:* Two copies on disk. Easy to forget to run the encrypt step. Manual conflict resolution is gnarlier (you can't merge ciphertext).

---

My recommendation: **Approach 1** for the threat model you described. If you want to build something for the joy of building it, **Approach 2** is the more interesting design — it's where the git internals get fun and the Go is non-trivial.

Which way do you want to go? (And if it's 2 or 3, totally fair — but tell me it's "because I want to" rather than "because git-crypt won't work," so I scope the design honestly.)


git-crypt seems like a good option


Solid choice. Even though git-crypt does most of the heavy lifting, there are still real decisions to make about scope and operations. Here's the design — short on purpose, since most of it is setup, not software:

---

**1. What gets encrypted vs. plaintext vs. gitignored**

- **Encrypted:** `*.md` (notes), `*.canvas`, attachments (`*.png`, `*.jpg`, `*.pdf`, etc.) — anything you'd actually write.
- **Plaintext (committed):** `.gitattributes` itself (it has to be — it tells git-crypt what to encrypt). Also `.gitignore`.
- **Gitignored entirely:** `.obsidian/workspace*.json`, `.obsidian/cache`, `.trash/`, `.DS_Store`. These churn every time you blink at Obsidian and don't belong in version control at all. Encrypting them is just noise on every commit.
- **Plaintext, committed:** the rest of `.obsidian/` (your plugin list, themes, hotkeys). It's not sensitive and it's useful to sync across machines. If you'd rather encrypt it too, easy to flip later.

**2. Key management (this is the one real decision)**

git-crypt supports either a **symmetric key file** or **GPG keys**. Two options:

- **(A) Symmetric key.** Run `git-crypt export-key ~/vault.key`, then move that file to each other machine via something out-of-band (1Password secure note, encrypted USB, AirDrop). On each machine: `git-crypt unlock ~/vault.key`. Simplest. Recommended for a single user.
- **(B) GPG.** Each machine has its own GPG key; you add each one as a "collaborator" with `git-crypt add-gpg-user`. Heavier ceremony, only worth it if you're sharing with others or want per-machine revocation.

I'd go with **(A)** unless you already live in GPG. Backup the key to a password manager and you're done.

**3. Bootstrap procedure**

Wraps up as a short README in the vault. First machine: `git init` → `brew install git-crypt` → `git-crypt init` → write `.gitattributes` and `.gitignore` → commit → create private GitHub repo → push. Second machine: `git clone` → install git-crypt → copy the key over → `git-crypt unlock` → done.

**4. Safety net (optional but I'd do it)**

A tiny pre-push hook that runs `git-crypt status` and refuses to push if any file that *should* be encrypted is showing up as plaintext in the index. Cheap insurance against the failure mode where you accidentally edit `.gitattributes`, forget, and push your secrets in the clear next week. ~15 lines of bash. This is the only "code" we'd actually write.

---

Does this look right? Specifically I want a thumbs-up on:

1. The encrypt-everything-Markdown-and-attachments scope (vs. selectively encrypting only certain folders).
2. Symmetric key vs. GPG.
3. Whether the pre-push safety hook is worth bothering with.

Once you confirm, I'll write this up as a spec doc and we can move to an implementation plan.


1. This all sounds good, lets encrypt that list, lets do the gitignore that you suggested. 2. For key management I will be the only user so a symmetric key is fine, I would like to use 1Password to store that key as I use 1Password across all of my devices. 3. Yup sounds sweet, write up the README big dawg. 4. Yo, you smart, you loyal. I like the safety net idea, lets do the git-crypt pre-push hook


Loyal AND smart. Don't let it go to my head. Writing the spec now.


Write

# Obsidian Vault Encryption — Design

**Date:** 2026-04-30
**Author:** Sir Charles of St Cheese (with Claudebob Squarepants)
**Status:** Approved, ready for implementation plan

## Goal

Encrypt the contents of this Obsidian vault before pushing to a private GitHub repo, while keeping plaintext on disk locally so Obsidian works normally. Sync the same encrypted repo across multiple machines belonging to a single user.

## Threat Model

Defending against **accidental exposure**: a leaked GitHub access token, a repo accidentally flipped to public, a stolen laptop with cached credentials. Not a zero-knowledge / hostile-GitHub scenario. The repo is already private; encryption is belt-and-suspenders.

Out of scope: hiding metadata (filenames, sizes, commit timestamps), defending against an attacker with the encryption key, or sharing the vault with other users.

## Approach: `git-crypt`

Use [`git-crypt`](https://github.com/AGWA/git-crypt) — a maintained tool that encrypts file contents transparently via git's `clean`/`smudge` filter mechanism. Plaintext stays on disk in the working directory; ciphertext is what lives in commits and on GitHub.

We considered building a custom Go utility wrapping `age` to do the same thing. Rejected: for the stated threat model, it would be reinventing a battle-tested tool with no meaningful benefit.

**The only code we write is a pre-push safety hook** (see §6).

## Scope

### Encrypted (via `.gitattributes`)

- `*.md` — Markdown notes
- `*.canvas` — Obsidian canvas files
- Attachments: `*.png`, `*.jpg`, `*.jpeg`, `*.gif`, `*.pdf`, `*.webp`, `*.svg`

### Plaintext (committed)

- `.gitattributes` — required to be plaintext; it tells git-crypt what to encrypt
- `.gitignore`
- The README documenting bootstrap / restore
- Most of `.obsidian/` — plugin list, themes, hotkeys, app config. Useful to sync, not sensitive.

### Gitignored entirely

These churn constantly and don't belong in version control at all:

- `.obsidian/workspace.json`, `.obsidian/workspace-mobile.json`
- `.obsidian/cache`
- `.obsidian/plugins/*/data.json` (per-plugin local state — case-by-case; some are useful, most aren't)
- `.trash/`
- `.DS_Store`

If a particular plugin's `data.json` turns out to be worth syncing, we can selectively un-ignore it later.

## Key Management

**Single symmetric key**, exported once and stored in 1Password.

- `git-crypt init` on the first machine generates the key.
- `git-crypt export-key <path>` writes the raw key to a file.
- The key file goes into 1Password as an attachment on a secure note titled "Obsidian Vault git-crypt key" (or similar).
- On each subsequent machine: clone the repo, install git-crypt, retrieve the key from 1Password, run `git-crypt unlock <key-file>`, delete the temporary file.

GPG-based collaboration is not used. Single user.

## Bootstrap Procedure (first machine)

Documented in `README.md` at the vault root. High-level:

1. `cd` into the vault, `git init`.
2. `brew install git-crypt`.
3. `git-crypt init`.
4. Write `.gitattributes` with the patterns from §3.
5. Write `.gitignore` with the entries from §3.
6. Install the pre-push hook (see §6).
7. `git-crypt export-key ~/vault.key`, store in 1Password, securely delete the temp file (`rm -P ~/vault.key` on macOS, or shred equivalent).
8. `git add . && git commit -m "Initial encrypted vault"`.
9. Create the private GitHub repo, add as remote, push.

## Bootstrap Procedure (additional machines)

1. `brew install git-crypt`.
2. `git clone <repo>`.
3. Retrieve key from 1Password to a temp file.
4. `git-crypt unlock <key-file>`.
5. Securely delete the temp key file.
6. Open vault in Obsidian, confirm contents are readable.

## Pre-Push Safety Hook

A bash hook at `.git/hooks/pre-push` that prevents pushing if encryption is misconfigured. Specifically, it should:

1. Verify `git-crypt status` reports no files in the encrypt-list as currently unencrypted.
2. Verify the key is locked-or-unlocked-as-expected (i.e., the repo isn't in some half-broken state).
3. Exit non-zero with a clear error if anything looks wrong, blocking the push.

The hook itself lives committed in the repo at `hooks/pre-push` (so it survives clones), and the bootstrap procedure symlinks `.git/hooks/pre-push` to it. (Git doesn't track `.git/hooks/`, so a checked-in `hooks/` directory + symlink is the standard workaround.)

Roughly ~15-30 lines of bash.

## Out of Scope

- Filename encryption / metadata hiding.
- Multi-user collaboration via GPG.
- Encrypting `.obsidian/` config.
- Custom Go utility (rejected; see §3).
- Automatic key rotation. Manual procedure if ever needed: `git-crypt` doesn't natively support rotation; you'd re-encrypt history with a new key, which is a one-off ceremony.

## Open Questions

None at design time. Implementation plan will pick exact `.gitattributes` patterns, the exact pre-push hook text, and the README wording.


File created successfully at: /Users/steve.briggs/Documents/obsidian/docs/superpowers/specs/2026-04-30-obsidian-vault-encryption-design.md

# Obsidian Vault Encryption — Design

**Date:** 2026-04-30
**Author:** Sir Charles of St Cheese (with Claudebob Squarepants)
**Status:** Approved, ready for implementation plan

## Goal

Encrypt the contents of this Obsidian vault before pushing to a private GitHub repo, while keeping plaintext on disk locally so Obsidian works normally. Sync the same encrypted repo across multiple machines belonging to a single user.

## Threat Model

Defending against **accidental exposure**: a leaked GitHub access token, a repo accidentally flipped to public, a stolen laptop with cached credentials. Not a zero-knowledge / hostile-GitHub scenario. The repo is already private; encryption is belt-and-suspenders.

Out of scope: hiding metadata (filenames, sizes, commit timestamps), defending against an attacker with the encryption key, or sharing the vault with other users.

## Approach: `git-crypt`

Use [`git-crypt`](https://github.com/AGWA/git-crypt) — a maintained tool that encrypts file contents transparently via git's `clean`/`smudge` filter mechanism. Plaintext stays on disk in the working directory; ciphertext is what lives in commits and on GitHub.

We considered building a custom Go utility wrapping `age` to do the same thing. Rejected: for the stated threat model, it would be reinventing a battle-tested tool with no meaningful benefit.

**The only code we write is a pre-push safety hook** (see §6).

## Scope

### Encrypted (via `.gitattributes`)

- `*.md` — Markdown notes
- `*.canvas` — Obsidian canvas files
- Attachments: `*.png`, `*.jpg`, `*.jpeg`, `*.gif`, `*.pdf`, `*.webp`, `*.svg`

### Plaintext (committed)

- `.gitattributes` — required to be plaintext; it tells git-crypt what to encrypt
- `.gitignore`
- The README documenting bootstrap / restore
- Most of `.obsidian/` — plugin list, themes, hotkeys, app config. Useful to sync, not sensitive.

### Gitignored entirely

These churn constantly and don't belong in version control at all:

- `.obsidian/workspace.json`, `.obsidian/workspace-mobile.json`
- `.obsidian/cache`
- `.obsidian/plugins/*/data.json` (per-plugin local state — case-by-case; some are useful, most aren't)
- `.trash/`
- `.DS_Store`

If a particular plugin's `data.json` turns out to be worth syncing, we can selectively un-ignore it later.

## Key Management

**Single symmetric key**, exported once and stored in 1Password.

- `git-crypt init` on the first machine generates the key.
- `git-crypt export-key <path>` writes the raw key to a file.
- The key file goes into 1Password as an attachment on a secure note titled "Obsidian Vault git-crypt key" (or similar).
- On each subsequent machine: clone the repo, install git-crypt, retrieve the key from 1Password, run `git-crypt unlock <key-file>`, delete the temporary file.

GPG-based collaboration is not used. Single user.

## Bootstrap Procedure (first machine)

Documented in `README.md` at the vault root. High-level:

1. `cd` into the vault, `git init`.
2. `brew install git-crypt`.
3. `git-crypt init`.
4. Write `.gitattributes` with the patterns from §3.
5. Write `.gitignore` with the entries from §3.
6. Install the pre-push hook (see §6).
7. `git-crypt export-key ~/vault.key`, store in 1Password, securely delete the temp file (`rm -P ~/vault.key` on macOS, or shred equivalent).
8. `git add . && git commit -m "Initial encrypted vault"`.
9. Create the private GitHub repo, add as remote, push.

## Bootstrap Procedure (additional machines)

1. `brew install git-crypt`.
2. `git clone <repo>`.
3. Retrieve key from 1Password to a temp file.
4. `git-crypt unlock <key-file>`.
5. Securely delete the temp key file.
6. Open vault in Obsidian, confirm contents are readable.

## Pre-Push Safety Hook

A bash hook at `.git/hooks/pre-push` that prevents pushing if encryption is misconfigured. Specifically, it should:

1. Verify `git-crypt status` reports no files in the encrypt-list as currently unencrypted.
2. Verify the key is locked-or-unlocked-as-expected (i.e., the repo isn't in some half-broken state).
3. Exit non-zero with a clear error if anything looks wrong, blocking the push.

The hook itself lives committed in the repo at `hooks/pre-push` (so it survives clones), and the bootstrap procedure symlinks `.git/hooks/pre-push` to it. (Git doesn't track `.git/hooks/`, so a checked-in `hooks/` directory + symlink is the standard workaround.)

Roughly ~15-30 lines of bash.

## Out of Scope

- Filename encryption / metadata hiding.
- Multi-user collaboration via GPG.
- Encrypting `.obsidian/` config.
- Custom Go utility (rejected; see §3).
- Automatic key rotation. Manual procedure if ever needed: `git-crypt` doesn't natively support rotation; you'd re-encrypt history with a new key, which is a one-off ceremony.

## Open Questions

None at design time. Implementation plan will pick exact `.gitattributes` patterns, the exact pre-push hook text, and the README wording.


1. This all sounds good, lets encrypt that list, lets do the gitignore that you suggested. 2. For key management I will be the only user so a symmetric key is fine, I would like to use 1Password to st…


Self-reviewing the spec — found one woolly bullet in §6 to tighten.


Edit

1. Verify `git-crypt status` reports no files in the encrypt-list as currently unencrypted.
2. Verify the key is locked-or-unlocked-as-expected (i.e., the repo isn't in some half-broken state).
3. Exit non-zero with a clear error if anything looks wrong, blocking the push.

1. Verify `.gitattributes` exists and still contains the expected `filter=git-crypt` patterns (catches the failure mode where someone edits or deletes it).
2. Run `git-crypt status` and fail if any file matched by the encrypt patterns appears as `not encrypted` in the index.
3. Exit non-zero with a clear error message if either check fails, blocking the push.


The file /Users/steve.briggs/Documents/obsidian/docs/superpowers/specs/2026-04-30-obsidian-vault-encryption-design.md has been updated successfully.

1. Verify `.gitattributes` exists and still contains the expected `filter=git-crypt` patterns (catches the failure mode where someone edits or deletes it).
2. Run `git-crypt status` and fail if any file matched by the encrypt patterns appears as `not encrypted` in the index.
3. Exit non-zero with a clear error message if either check fails, blocking the push.

# Obsidian Vault Encryption — Design

**Date:** 2026-04-30
**Author:** Sir Charles of St Cheese (with Claudebob Squarepants)
**Status:** Approved, ready for implementation plan

## Goal

Encrypt the contents of this Obsidian vault before pushing to a private GitHub repo, while keeping plaintext on disk locally so Obsidian works normally. Sync the same encrypted repo across multiple machines belonging to a single user.

## Threat Model

Defending against **accidental exposure**: a leaked GitHub access token, a repo accidentally flipped to public, a stolen laptop with cached credentials. Not a zero-knowledge / hostile-GitHub scenario. The repo is already private; encryption is belt-and-suspenders.

Out of scope: hiding metadata (filenames, sizes, commit timestamps), defending against an attacker with the encryption key, or sharing the vault with other users.

## Approach: `git-crypt`

Use [`git-crypt`](https://github.com/AGWA/git-crypt) — a maintained tool that encrypts file contents transparently via git's `clean`/`smudge` filter mechanism. Plaintext stays on disk in the working directory; ciphertext is what lives in commits and on GitHub.

We considered building a custom Go utility wrapping `age` to do the same thing. Rejected: for the stated threat model, it would be reinventing a battle-tested tool with no meaningful benefit.

**The only code we write is a pre-push safety hook** (see §6).

## Scope

### Encrypted (via `.gitattributes`)

- `*.md` — Markdown notes
- `*.canvas` — Obsidian canvas files
- Attachments: `*.png`, `*.jpg`, `*.jpeg`, `*.gif`, `*.pdf`, `*.webp`, `*.svg`

### Plaintext (committed)

- `.gitattributes` — required to be plaintext; it tells git-crypt what to encrypt
- `.gitignore`
- The README documenting bootstrap / restore
- Most of `.obsidian/` — plugin list, themes, hotkeys, app config. Useful to sync, not sensitive.

### Gitignored entirely

These churn constantly and don't belong in version control at all:

- `.obsidian/workspace.json`, `.obsidian/workspace-mobile.json`
- `.obsidian/cache`
- `.obsidian/plugins/*/data.json` (per-plugin local state — case-by-case; some are useful, most aren't)
- `.trash/`
- `.DS_Store`

If a particular plugin's `data.json` turns out to be worth syncing, we can selectively un-ignore it later.

## Key Management

**Single symmetric key**, exported once and stored in 1Password.

- `git-crypt init` on the first machine generates the key.
- `git-crypt export-key <path>` writes the raw key to a file.
- The key file goes into 1Password as an attachment on a secure note titled "Obsidian Vault git-crypt key" (or similar).
- On each subsequent machine: clone the repo, install git-crypt, retrieve the key from 1Password, run `git-crypt unlock <key-file>`, delete the temporary file.

GPG-based collaboration is not used. Single user.

## Bootstrap Procedure (first machine)

Documented in `README.md` at the vault root. High-level:

1. `cd` into the vault, `git init`.
2. `brew install git-crypt`.
3. `git-crypt init`.
4. Write `.gitattributes` with the patterns from §3.
5. Write `.gitignore` with the entries from §3.
6. Install the pre-push hook (see §6).
7. `git-crypt export-key ~/vault.key`, store in 1Password, securely delete the temp file (`rm -P ~/vault.key` on macOS, or shred equivalent).
8. `git add . && git commit -m "Initial encrypted vault"`.
9. Create the private GitHub repo, add as remote, push.

## Bootstrap Procedure (additional machines)

1. `brew install git-crypt`.
2. `git clone <repo>`.
3. Retrieve key from 1Password to a temp file.
4. `git-crypt unlock <key-file>`.
5. Securely delete the temp key file.
6. Open vault in Obsidian, confirm contents are readable.

## Pre-Push Safety Hook

A bash hook at `.git/hooks/pre-push` that prevents pushing if encryption is misconfigured. Specifically, it should:

1. Verify `git-crypt status` reports no files in the encrypt-list as currently unencrypted.
2. Verify the key is locked-or-unlocked-as-expected (i.e., the repo isn't in some half-broken state).
3. Exit non-zero with a clear error if anything looks wrong, blocking the push.

The hook itself lives committed in the repo at `hooks/pre-push` (so it survives clones), and the bootstrap procedure symlinks `.git/hooks/pre-push` to it. (Git doesn't track `.git/hooks/`, so a checked-in `hooks/` directory + symlink is the standard workaround.)

Roughly ~15-30 lines of bash.

## Out of Scope

- Filename encryption / metadata hiding.
- Multi-user collaboration via GPG.
- Encrypting `.obsidian/` config.
- Custom Go utility (rejected; see §3).
- Automatic key rotation. Manual procedure if ever needed: `git-crypt` doesn't natively support rotation; you'd re-encrypt history with a new key, which is a one-off ceremony.

## Open Questions

None at design time. Implementation plan will pick exact `.gitattributes` patterns, the exact pre-push hook text, and the README wording.

-1. Verify `git-crypt status` reports no files in the encrypt-list as currently unencrypted.

-2. Verify the key is locked-or-unlocked-as-expected (i.e., the repo isn't in some half-broken state).

-3. Exit non-zero with a clear error if anything looks wrong, blocking the push.

+1. Verify `.gitattributes` exists and still contains the expected `filter=git-crypt` patterns (catches the failure mode where someone edits or deletes it).

+2. Run `git-crypt status` and fail if any file matched by the encrypt patterns appears as `not encrypted` in the index.

+3. Exit non-zero with a clear error message if either check fails, blocking the push.


Spec written and self-reviewed. Tightened up one bullet in the pre-push hook section that was waving its hands about "locked-or-unlocked-as-expected" — now it's two concrete checks.

Note on committing it: the brainstorming workflow normally has me commit the spec to git here, but the vault isn't a git repo yet — that's literally step 1 of the implementation. So the spec is sitting on disk at:

`docs/superpowers/specs/2026-04-30-obsidian-vault-encryption-design.md`

It'll be part of the very first commit when we do `git init`.

**Please give it a read** and let me know if you want any changes. Once you approve, I'll move to writing the implementation plan.


looks good big dawg lets do it


Onward. Invoking writing-plans next.


Launching skill: superpowers:writing-plans


Base directory for this skill: /Users/steve.briggs/.claude/plugins/cache/claude-plugins-official/superpowers/5.0.7/skills/writing-plans

# Writing Plans

## Overview

Write comprehensive implementation plans assuming the engineer has zero context for our codebase and questionable taste. Document everything they need to know: which files to touch for each task, code, testing, docs they might need to check, how to test it. Give them the whole plan as bite-sized tasks. DRY. YAGNI. TDD. Frequent commits.

Assume they are a skilled developer, but know almost nothing about our toolset or problem domain. Assume they don't know good test design very well.

**Announce at start:** "I'm using the writing-plans skill to create the implementation plan."

**Context:** This should be run in a dedicated worktree (created by brainstorming skill).

**Save plans to:** `docs/superpowers/plans/YYYY-MM-DD-<feature-name>.md`
- (User preferences for plan location override this default)

## Scope Check

If the spec covers multiple independent subsystems, it should have been broken into sub-project specs during brainstorming. If it wasn't, suggest breaking this into separate plans — one per subsystem. Each plan should produce working, testable software on its own.

## File Structure

Before defining tasks, map out which files will be created or modified and what each one is responsible for. This is where decomposition decisions get locked in.

- Design units with clear boundaries and well-defined interfaces. Each file should have one clear responsibility.
- You reason best about code you can hold in context at once, and your edits are more reliable when files are focused. Prefer smaller, focused files over large ones that do too much.
- Files that change together should live together. Split by responsibility, not by technical layer.
- In existing codebases, follow established patterns. If the codebase uses large files, don't unilaterally restructure - but if a file you're modifying has grown unwieldy, including a split in the plan is reasonable.

This structure informs the task decomposition. Each task should produce self-contained changes that make sense independently.

## Bite-Sized Task Granularity

**Each step is one action (2-5 minutes):**
- "Write the failing test" - step
- "Run it to make sure it fails" - step
- "Implement the minimal code to make the test pass" - step
- "Run the tests and make sure they pass" - step
- "Commit" - step

## Plan Document Header

**Every plan MUST start with this header:**

```markdown
# [Feature Name] Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** [One sentence describing what this builds]

**Architecture:** [2-3 sentences about approach]

**Tech Stack:** [Key technologies/libraries]

---
```

## Task Structure

````markdown
### Task N: [Component Name]

**Files:**
- Create: `exact/path/to/file.py`
- Modify: `exact/path/to/existing.py:123-145`
- Test: `tests/exact/path/to/test.py`

- [ ] **Step 1: Write the failing test**

```python
def test_specific_behavior():
    result = function(input)
    assert result == expected
```

- [ ] **Step 2: Run test to verify it fails**

Run: `pytest tests/path/test.py::test_name -v`
Expected: FAIL with "function not defined"

- [ ] **Step 3: Write minimal implementation**

```python
def function(input):
    return expected
```

- [ ] **Step 4: Run test to verify it passes**

Run: `pytest tests/path/test.py::test_name -v`
Expected: PASS

- [ ] **Step 5: Commit**

```bash
git add tests/path/test.py src/path/file.py
git commit -m "feat: add specific feature"
```
````

## No Placeholders

Every step must contain the actual content an engineer needs. These are **plan failures** — never write them:
- "TBD", "TODO", "implement later", "fill in details"
- "Add appropriate error handling" / "add validation" / "handle edge cases"
- "Write tests for the above" (without actual test code)
- "Similar to Task N" (repeat the code — the engineer may be reading tasks out of order)
- Steps that describe what to do without showing how (code blocks required for code steps)
- References to types, functions, or methods not defined in any task

## Remember
- Exact file paths always
- Complete code in every step — if a step changes code, show the code
- Exact commands with expected output
- DRY, YAGNI, TDD, frequent commits

## Self-Review

After writing the complete plan, look at the spec with fresh eyes and check the plan against it. This is a checklist you run yourself — not a subagent dispatch.

**1. Spec coverage:** Skim each section/requirement in the spec. Can you point to a task that implements it? List any gaps.

**2. Placeholder scan:** Search your plan for red flags — any of the patterns from the "No Placeholders" section above. Fix them.

**3. Type consistency:** Do the types, method signatures, and property names you used in later tasks match what you defined in earlier tasks? A function called `clearLayers()` in Task 3 but `clearFullLayers()` in Task 7 is a bug.

If you find issues, fix them inline. No need to re-review — just fix and move on. If you find a spec requirement with no task, add the task.

## Execution Handoff

After saving the plan, offer execution choice:

**"Plan complete and saved to `docs/superpowers/plans/<filename>.md`. Two execution options:**

**1. Subagent-Driven (recommended)** - I dispatch a fresh subagent per task, review between tasks, fast iteration

**2. Inline Execution** - Execute tasks in this session using executing-plans, batch execution with checkpoints

**Which approach?"**

**If Subagent-Driven chosen:**
- **REQUIRED SUB-SKILL:** Use superpowers:subagent-driven-development
- Fresh subagent per task + two-stage review

**If Inline Execution chosen:**
- **REQUIRED SUB-SKILL:** Use superpowers:executing-plans
- Batch execution with checkpoints for review


I'm using the writing-plans skill to create the implementation plan.


Write

# Obsidian Vault Encryption Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** Set up the Obsidian vault at `/Users/steve.briggs/Documents/obsidian/` as a git-crypt-encrypted repository, ready to sync across machines via a private GitHub repo, with a safety hook that blocks pushes if encryption is misconfigured.

**Architecture:** Use `git-crypt` for transparent per-file encryption via git's `clean`/`smudge` filters. Plaintext stays on disk; ciphertext is what gets committed. A symmetric key is exported once and stored in 1Password for cross-machine sync. A committed bash pre-push hook (symlinked into `.git/hooks/`) verifies `.gitattributes` is intact and `git-crypt status` reports no leaks before any push succeeds.

**Tech Stack:** `git`, `git-crypt` (Homebrew), bash, GitHub.

---

## File Structure

| Path | Purpose | Status |
|---|---|---|
| `.gitattributes` | git-crypt encryption patterns | Create |
| `.gitignore` | Obsidian churn / OS noise | Create |
| `hooks/pre-push` | Safety hook (committed; survives clones) | Create |
| `tests/test-pre-push-hook.sh` | Shell test exercising hook scenarios | Create |
| `README.md` | Bootstrap & restore documentation | Create |
| `.git/hooks/pre-push` | Symlink to `../../hooks/pre-push` | Runtime only (not committed; git ignores `.git/`) |

The vault contents (`home/` and any future notes) are unchanged by this work — only metadata and tooling files are added at the repo root.

---

## Task 1: Initialize the git repository

**Files:** None created yet — just `git init`.

- [ ] **Step 1: Verify we're in the vault and it's not already a repo**

Run:
```bash
cd /Users/steve.briggs/Documents/obsidian
[[ -d .git ]] && echo "ALREADY A REPO — STOP" || echo "OK to init"
```
Expected: `OK to init`

- [ ] **Step 2: Initialize the repo**

Run:
```bash
git init
```
Expected: `Initialized empty Git repository in /Users/steve.briggs/Documents/obsidian/.git/`

- [ ] **Step 3: Verify the initial branch name**

Run:
```bash
git symbolic-ref --short HEAD
```
Expected: `main` (if not, run `git branch -m main` to rename).

- [ ] **Step 4: No commit yet**

Do not commit. We commit at the end of Task 11 once everything is in place.

---

## Task 2: Create `.gitignore`

**Files:**
- Create: `/Users/steve.briggs/Documents/obsidian/.gitignore`

- [ ] **Step 1: Write the test (verification command)**

The test is: after writing `.gitignore`, `git status --ignored` should NOT list any of the entries below as untracked. Defer the actual run to Step 3.

- [ ] **Step 2: Write `.gitignore`**

Create `.gitignore` with exactly:
```gitignore
# Obsidian churn — rewritten constantly, not worth syncing
.obsidian/workspace.json
.obsidian/workspace-mobile.json
.obsidian/cache
.obsidian/plugins/*/data.json

# Obsidian local-only state
.trash/

# macOS noise
.DS_Store
```

- [ ] **Step 3: Verify it works**

Run:
```bash
mkdir -p .obsidian
touch .obsidian/workspace.json .DS_Store
git status --short
```
Expected: neither `.obsidian/workspace.json` nor `.DS_Store` appears in the output. Then clean up the test files: `rm .obsidian/workspace.json .DS_Store && rmdir .obsidian 2>/dev/null || true`.

- [ ] **Step 4: No commit yet**

---

## Task 3: Create `.gitattributes`

**Files:**
- Create: `/Users/steve.briggs/Documents/obsidian/.gitattributes`

- [ ] **Step 1: Write `.gitattributes`**

Create `.gitattributes` with exactly:
```gitattributes
*.md       filter=git-crypt diff=git-crypt
*.canvas   filter=git-crypt diff=git-crypt
*.png      filter=git-crypt diff=git-crypt
*.jpg      filter=git-crypt diff=git-crypt
*.jpeg     filter=git-crypt diff=git-crypt
*.gif      filter=git-crypt diff=git-crypt
*.webp     filter=git-crypt diff=git-crypt
*.svg      filter=git-crypt diff=git-crypt
*.pdf      filter=git-crypt diff=git-crypt

.gitattributes !filter !diff
```

(The last line explicitly excludes `.gitattributes` itself — defensive; it would never match `*.md` etc., but spelling it out documents the intent.)

- [ ] **Step 2: Verify the patterns match**

Run:
```bash
git check-attr filter diff -- test.md
```
Expected:
```
test.md: filter: git-crypt
test.md: diff: git-crypt
```

- [ ] **Step 3: Verify `.gitattributes` itself is NOT matched**

Run:
```bash
git check-attr filter diff -- .gitattributes
```
Expected: filter and diff should both be `unspecified`.

- [ ] **Step 4: No commit yet**

---

## Task 4: Install git-crypt and initialize

**Files:** None created at the repo level. `git-crypt init` creates `.git/git-crypt/` (not tracked).

- [ ] **Step 1: Install git-crypt**

Run:
```bash
brew install git-crypt
```
Expected: installs successfully. If already installed: `Warning: git-crypt X.Y.Z is already installed`.

- [ ] **Step 2: Verify version**

Run:
```bash
git-crypt --version
```
Expected: prints a version (e.g., `git-crypt 0.7.0`).

- [ ] **Step 3: Initialize git-crypt in the repo**

Run:
```bash
git-crypt init
```
Expected: `Generating key...` and silence.

- [ ] **Step 4: Verify the key was created**

Run:
```bash
ls .git/git-crypt/keys/
```
Expected: a file called `default`.

- [ ] **Step 5: No commit yet**

---

## Task 5: Write the test for the pre-push hook

**Files:**
- Create: `/Users/steve.briggs/Documents/obsidian/tests/test-pre-push-hook.sh`

- [ ] **Step 1: Create the tests directory**

Run:
```bash
mkdir -p tests
```

- [ ] **Step 2: Write the test script**

Create `tests/test-pre-push-hook.sh` with exactly:
```bash
#!/usr/bin/env bash
# Test cases for hooks/pre-push.
# Run from the repo root: bash tests/test-pre-push-hook.sh

set -u

REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
HOOK="$REPO_ROOT/hooks/pre-push"

cd "$REPO_ROOT" || exit 1

pass=0
fail=0

run_case() {
    local name="$1"
    local expected_exit="$2"
    local actual_exit="$3"
    if [[ "$actual_exit" == "$expected_exit" ]]; then
        echo "PASS: $name (exit $actual_exit)"
        pass=$((pass + 1))
    else
        echo "FAIL: $name (expected exit $expected_exit, got $actual_exit)"
        fail=$((fail + 1))
    fi
}

# --- Case 1: Healthy state — hook should pass ---
out=$(bash "$HOOK" origin git@example.com:fake/repo.git </dev/null 2>&1)
run_case "healthy state passes" 0 $?

# --- Case 2: Missing .gitattributes — hook should fail ---
mv .gitattributes .gitattributes.bak
out=$(bash "$HOOK" origin git@example.com:fake/repo.git </dev/null 2>&1)
run_case "missing .gitattributes fails" 1 $?
mv .gitattributes.bak .gitattributes

# --- Case 3: .gitattributes missing the git-crypt filter line — hook should fail ---
cp .gitattributes .gitattributes.bak
echo "# only comments" > .gitattributes
out=$(bash "$HOOK" origin git@example.com:fake/repo.git </dev/null 2>&1)
run_case "no git-crypt patterns fails" 1 $?
mv .gitattributes.bak .gitattributes

echo
echo "Results: $pass passed, $fail failed"
[[ "$fail" -eq 0 ]]
```

- [ ] **Step 3: Make the test executable**

Run:
```bash
chmod +x tests/test-pre-push-hook.sh
```

- [ ] **Step 4: Run the test — it should fail because the hook does not exist yet**

Run:
```bash
bash tests/test-pre-push-hook.sh
```
Expected: every case fails (the hook file doesn't exist), output ends with `Results: 0 passed, 3 failed` and exit code 1. **This is the failing-test step of TDD — confirm before writing the hook.**

- [ ] **Step 5: No commit yet**

---

## Task 6: Write the pre-push hook

**Files:**
- Create: `/Users/steve.briggs/Documents/obsidian/hooks/pre-push`
- Create (symlink, runtime-only): `.git/hooks/pre-push`

- [ ] **Step 1: Create the hooks directory**

Run:
```bash
mkdir -p hooks
```

- [ ] **Step 2: Write the hook**

Create `hooks/pre-push` with exactly:
```bash
#!/usr/bin/env bash
# Pre-push safety hook for git-crypt-encrypted vault.
# Blocks the push if encryption looks misconfigured.
#
# Checks:
#   1. git-crypt binary is installed.
#   2. .gitattributes exists and contains at least one filter=git-crypt pattern.
#   3. `git-crypt status` reports no files matched-but-not-encrypted.

set -u

repo_root=$(git rev-parse --show-toplevel)
cd "$repo_root" || exit 1

fail() {
    echo "pre-push hook: $1" >&2
    echo "Push BLOCKED. Fix and try again." >&2
    exit 1
}

command -v git-crypt >/dev/null 2>&1 \
    || fail "git-crypt is not installed (brew install git-crypt)"

[[ -f .gitattributes ]] \
    || fail ".gitattributes is missing — encryption rules would not apply"

grep -q 'filter=git-crypt' .gitattributes \
    || fail ".gitattributes contains no 'filter=git-crypt' patterns"

# git-crypt status prints "not encrypted: <path>" for any file that is matched
# by .gitattributes but is currently plaintext in the index. Any such line is
# a leak waiting to happen.
leaks=$(git-crypt status 2>&1 | grep -E '^[[:space:]]*not encrypted: ' || true)
if [[ -n "$leaks" ]]; then
    echo "pre-push hook: files matched by .gitattributes are NOT encrypted:" >&2
    echo "$leaks" >&2
    fail "run 'git-crypt status -f' to fix, then commit and re-push"
fi

exit 0
```

- [ ] **Step 3: Make the hook executable**

Run:
```bash
chmod +x hooks/pre-push
```

- [ ] **Step 4: Symlink into `.git/hooks/`**

Run:
```bash
ln -sf ../../hooks/pre-push .git/hooks/pre-push
ls -l .git/hooks/pre-push
```
Expected: shows a symlink pointing to `../../hooks/pre-push`.

- [ ] **Step 5: Run the test — it should now pass**

Run:
```bash
bash tests/test-pre-push-hook.sh
```
Expected: `Results: 3 passed, 0 failed` and exit code 0.

- [ ] **Step 6: No commit yet**

---

## Task 7: Manually verify encryption with a sample note

This is a one-time sanity check that git-crypt is actually encrypting things, performed BEFORE we commit anything important.

**Files:** Temporary `home/_encryption-test.md` (deleted at end of task).

- [ ] **Step 1: Create a test note**

Run:
```bash
mkdir -p home
echo "this is a secret test note" > home/_encryption-test.md
```

- [ ] **Step 2: Stage it**

Run:
```bash
git add home/_encryption-test.md
```

- [ ] **Step 3: Verify the staged blob is encrypted**

Run:
```bash
git show :home/_encryption-test.md | head -c 9 | xxd
```
Expected: the first 9 bytes are `00 47 49 54 43 52 59 50 54` (the literal bytes `\0GITCRYPT`). If you see plaintext (`this is`), encryption is not working — STOP and debug.

- [ ] **Step 4: Verify the working-tree file is still plaintext**

Run:
```bash
cat home/_encryption-test.md
```
Expected: `this is a secret test note`.

- [ ] **Step 5: Clean up**

Run:
```bash
git rm -f home/_encryption-test.md
```

- [ ] **Step 6: No commit yet**

---

## Task 8: Write the README

**Files:**
- Create: `/Users/steve.briggs/Documents/obsidian/README.md`

- [ ] **Step 1: Write `README.md`**

Create `README.md` with exactly:
````markdown
# Obsidian Vault (encrypted)

This vault uses [`git-crypt`](https://github.com/AGWA/git-crypt) for transparent per-file encryption. Plaintext lives on disk locally; only ciphertext is committed and pushed to GitHub.

## What's encrypted

Anything matched by `.gitattributes` — currently `*.md`, `*.canvas`, and common image / PDF extensions. Filenames, directory structure, and commit metadata are NOT encrypted (this is fine for our threat model: belt-and-suspenders for an already-private repo).

## Setting up a new machine

```bash
# 1. Install git-crypt
brew install git-crypt   # macOS
# (or: apt install git-crypt / pacman -S git-crypt / etc.)

# 2. Clone the repo
git clone git@github.com:<you>/<repo>.git
cd <repo>

# 3. Get the key from 1Password
#    Open the "Obsidian Vault git-crypt key" item, download the attachment
#    to a temp location, e.g. ~/vault.key

# 4. Unlock
git-crypt unlock ~/vault.key

# 5. Securely delete the temp key file
rm -P ~/vault.key   # macOS; on Linux use `shred -u ~/vault.key`

# 6. Install the pre-push hook (the file is committed at hooks/pre-push)
ln -sf ../../hooks/pre-push .git/hooks/pre-push

# 7. Verify
cat home/some-note.md   # should be plaintext
```

## Daily use

Just use Obsidian and `git` normally. `git status` / `git add` / `git commit` / `git push` all work. The pre-push hook will block the push if encryption looks misconfigured.

## Adding new file types to encryption

Edit `.gitattributes`, add a `filter=git-crypt diff=git-crypt` line for the new pattern, then run:

```bash
git-crypt status -f      # re-encrypts any newly-matched files
git add .
git commit -m "Encrypt <pattern>"
```

## Backing up the key

The key is the only thing that lets you decrypt this vault. Lose it and the GitHub repo is permanently unreadable. It is stored in 1Password as an attachment on the secure note "Obsidian Vault git-crypt key". Do not store it anywhere else.

## Rotating the key

Not currently supported by `git-crypt` natively. If ever needed, the procedure is: clone, decrypt, re-init with a new key, force-push. One-off ceremony — write it up if/when you actually need to.
````

- [ ] **Step 2: No commit yet**

---

## Task 9: Export and securely store the key (manual)

This is a manual step — Claude cannot put things in 1Password.

**Files:** Temporary `~/vault.key`, deleted after upload.

- [ ] **Step 1: Export the key**

Run:
```bash
git-crypt export-key ~/vault.key
ls -l ~/vault.key
```
Expected: a small (~50 byte) file at `~/vault.key`.

- [ ] **Step 2: Sir Charles of St Cheese, do this by hand:**

  - Open 1Password.
  - Create a new Secure Note titled `Obsidian Vault git-crypt key`.
  - Attach `~/vault.key` to it.
  - Save.
  - Verify the attachment opens and contains binary (not empty).

- [ ] **Step 3: Securely delete the temp file**

Run:
```bash
rm -P ~/vault.key
ls -l ~/vault.key 2>&1
```
Expected: `No such file or directory`.

- [ ] **Step 4: No commit yet**

---

## Task 10: Pre-flight check before first commit

- [ ] **Step 1: Confirm the working tree state**

Run:
```bash
git status --short
```
Expected: shows `??` lines for `.gitattributes`, `.gitignore`, `README.md`, `hooks/pre-push`, `tests/test-pre-push-hook.sh`, `docs/superpowers/specs/2026-04-30-obsidian-vault-encryption-design.md`, `docs/superpowers/plans/2026-04-30-obsidian-vault-encryption.md`, and any actual notes under `home/`. Should NOT show `.obsidian/workspace.json` or similar churn files.

- [ ] **Step 2: Run the hook test once more for confidence**

Run:
```bash
bash tests/test-pre-push-hook.sh
```
Expected: `Results: 3 passed, 0 failed`.

- [ ] **Step 3: Run the hook directly to verify exit 0 in the current state**

Run:
```bash
bash hooks/pre-push origin none </dev/null
echo "exit: $?"
```
Expected: `exit: 0`.

---

## Task 11: Initial commit

- [ ] **Step 1: Stage everything**

Run:
```bash
git add .
```

- [ ] **Step 2: Verify what's staged**

Run:
```bash
git status --short
```
Expected: all the files from Task 10 Step 1 are now staged (`A` lines, not `??`).

- [ ] **Step 3: Spot-check that a Markdown file is staged as ciphertext**

Pick any `.md` file in `home/` (if there are any). If `home/` is empty, skip this step.

Run (substitute a real path):
```bash
git show ":home/<some-existing-note>.md" | head -c 9 | xxd
```
Expected: starts with `\0GITCRYPT`.

- [ ] **Step 4: Commit**

Run:
```bash
git commit -m "Initial encrypted vault setup

- git-crypt for transparent per-file encryption
- .gitattributes patterns for *.md, *.canvas, images, PDFs
- .gitignore for Obsidian workspace churn and OS noise
- Committed pre-push safety hook (hooks/pre-push) with shell test
- README documenting bootstrap and restore procedure
- Design + implementation plan under docs/superpowers/"
```
Expected: a commit lands on `main`.

- [ ] **Step 5: Verify the commit**

Run:
```bash
git log --stat -1
```
Expected: shows the commit with the file list.

---

## Task 12: Create the GitHub repo and push

- [ ] **Step 1: Create the private repo**

Sir Charles of St Cheese, do one of the following:

**Option A — `gh` CLI (preferred if installed):**
```bash
gh repo create obsidian-vault --private --source=. --remote=origin
```
Expected: prints the URL of the new repo and adds `origin`.

**Option B — web UI:**
1. Go to https://github.com/new
2. Name: `obsidian-vault` (or your choice). Visibility: **Private**. Do NOT initialize with a README.
3. After creation, run locally:
   ```bash
   git remote add origin git@github.com:<you>/obsidian-vault.git
   ```

- [ ] **Step 2: Verify the remote**

Run:
```bash
git remote -v
```
Expected: `origin` listed for both fetch and push.

- [ ] **Step 3: Push**

Run:
```bash
git push -u origin main
```
Expected: the pre-push hook runs, prints nothing (or only `pre-push hook:` lines if it found something), exits 0, and the push completes.

If the hook blocks: read its message, fix the issue, re-run. **Do not bypass with `--no-verify`** — that's the entire point of the hook.

---

## Task 13: Verify on GitHub that ciphertext landed

- [ ] **Step 1: Open the repo in a browser**

Sir Charles of St Cheese, navigate to your new repo on GitHub.

- [ ] **Step 2: Click on any `.md` file**

Expected: GitHub shows binary-blob output, NOT readable text. The first bytes should look like `\0GITCRYPT` followed by gibberish.

If you see readable plaintext: **STOP**. Something is wrong. Force-push is not a fix — the plaintext is now in GitHub's git history. You'd need to delete the repo, debug locally, and start the push from scratch.

---

## Task 14: Verify cross-machine sync works (deferred — do later when you set up a second machine)

This is for future-Sir-Charles when he sits down at another machine. Not part of today's work, just documenting the procedure here so it's findable.

Follow the "Setting up a new machine" section in `README.md`. After unlock, confirm:
- Files in `home/` are readable plaintext locally.
- `git-crypt status` reports everything as `encrypted` (no `not encrypted:` lines).

---

## Notes

- **Task 9 and Task 12 require human action** (1Password and GitHub UI/auth). An agent executing this plan should pause and surface those steps to the user rather than trying to automate them.
- **Order matters.** Task 7 (encryption sanity check) must happen before Task 11 (initial commit). If encryption is broken and we commit, plaintext lands in git history — recoverable only by destroying the repo before pushing.
- **No `--no-verify`.** The whole point of the pre-push hook is to be a safety net. Bypassing it defeats Task 6.