# Hooks

Memory Mason hooks capture prompts, tool output, and session summaries into an Obsidian vault.

## Config

Hooks resolve config in this order (first match wins):

| Priority | Source | Location |
|:--------:|:-------|:---------|
| 1 | Project `.env` | `MEMORY_MASON_VAULT_PATH` + optional `MEMORY_MASON_SUBFOLDER` + optional `MEMORY_MASON_SYNC` |
| 2 | Project config | `memory-mason.json` in project root |
| 3 | Global `.env` | `~/.memory-mason/.env` |
| 4 | Global config | `~/.memory-mason/config.json` |

Vault path is resolved from files only. Process environment variables `MEMORY_MASON_SYNC` and
`MEMORY_MASON_CAPTURE_MODE` still override file config for a single session. If no source is
found, hooks throw. `.env` sources default subfolder to `ai-knowledge` when
`MEMORY_MASON_SUBFOLDER` is unset.

### .env format

`MEMORY_MASON_VAULT_PATH` sets the Obsidian vault location. `MEMORY_MASON_SUBFOLDER` sets the
directory inside the vault. `MEMORY_MASON_SYNC` is optional — capture is enabled by default; set
it to `false` to pause capture. `MEMORY_MASON_CAPTURE_MODE` is optional — set it to `full` for
detailed tool output, or leave it at the default `lite` mode for compact capture. Setting
`MEMORY_MASON_SYNC` or `MEMORY_MASON_CAPTURE_MODE` as process environment variables overrides file
config for a single session.

```env
MEMORY_MASON_VAULT_PATH=/path/to/your/obsidian/vault
MEMORY_MASON_SUBFOLDER=ai-knowledge
MEMORY_MASON_SYNC=true
```

### JSON format

`vaultPath` sets the Obsidian vault location. `subfolder` sets the directory inside the vault. `sync` is optional — capture is enabled by default; set it to `false` to pause capture. Every hook checks `resolvedConfig.sync === false` early and returns without vault I/O.

```json
{
  "vaultPath": "/path/to/your/obsidian/vault",
  "subfolder": "ai-knowledge",
  "sync": true
}
```

## Hook Files

| File | Event | What it does |
|:-----|:------|:-------------|
| `session-start.js` | SessionStart | Injects knowledge base context from compiled index + recent daily log |
| `user-prompt-submit.js` | UserPromptSubmit | Appends user prompts to daily logs |
| `post-tool-use.js` | PostToolUse | Appends tool results after meaningful tool calls |
| `pre-compact.js` | PreCompact | Captures transcript excerpt before context compaction |
| `session-end.js` | Stop / SessionEnd | Stop appends latest assistant turns; SessionEnd captures full transcript |

`user-prompt-submit.js` still understands `UserPromptExpansion` input, but Memory Mason does not auto-register that event because current Claude plugin validation can reject the key.

## Memory Mason Command Suppression

Memory Mason commands are excluded from capture through three layers. This applies only to short-form commands `/mma`, `/mmc`, `/mml`, `/mms`, `/mmq`, and `/mmsetup`, plus their namespaced forms such as `/memory-mason:mmc`.

1. **Prompt skip** — `user-prompt-submit.js` detects a Memory Mason command, sets `mmSuppressed` in `capture-state.json`, and skips writing the prompt.
2. **Capture state flag** — `post-tool-use.js` and `pre-compact.js` check `mmSuppressed` and skip capture while active. The flag resets on the next non-Memory Mason prompt.
3. **Transcript filter** — `session-end.js` SessionEnd handler runs `filterMmTurns()` to strip Memory Mason user turns and their paired assistant replies from the transcript.

This prevents Memory Mason command traffic from ever being written into Obsidian daily logs and
avoids duplicate content in the knowledge base.

## Platform Mappings

| Platform | Hook source |
|:---------|:------------|
| Claude Code plugin | `hooks/hooks.json` (shipped with plugin, auto-discovered) |
| Claude Code shell install | `~/.claude/settings.json` (wired by `install.sh`) |
| Copilot plugin | Root `../hooks.json` (shipped with plugin) |
| Copilot shell install | Workspace hook JSON generated by installer |
| Codex | `.codex/hooks.json` (wired by installer) |

## Shell Install

### Claude Code

```bash
bash scripts/install/claude-code.sh               # macOS / Linux
powershell -File scripts\install\claude-code.ps1   # Windows
```

Copies runtime to `~/.claude/hooks/memory-mason/`, wires 6 events in `~/.claude/settings.json`, creates `~/.memory-mason/config.json`.

### GitHub Copilot

```bash
bash scripts/install/copilot.sh               # macOS / Linux
powershell -File scripts\install\copilot.ps1   # Windows
```

Writes 6 workspace hook files: `session-start.json`, `user-prompt-submit.json`, `post-tool-use.json`, `pre-compact.json`, `stop.json`, `session-end.json`.

Or use the root meta-installer:

```bash
bash install.sh --agent copilot
bash install.sh --agent all
```

### Codex

```bash
bash scripts/install/codex.sh               # macOS / Linux
powershell -File scripts\install\codex.ps1   # Windows
```

Or: `bash install.sh --agent codex`

## Tests

```bash
cd hooks
npm test
npm run coverage
```

`npm run coverage` enforces 100% line, statement, function, and branch coverage for shared logic in `lib/`. Entry scripts are validated by behavioral tests in `__tests__/`.
