@gi4nks/ph 1.5.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/CHANGELOG.md +2 -2
  2. package/README.md +118 -152
  3. package/dist/cli.js +2049 -1055
  4. package/dist/cli.js.map +1 -1
  5. package/docs/evals/context-retrieval-golden.json +26 -0
  6. package/docs/evals/context-retrieval.md +27 -0
  7. package/docs/hooks.md +13 -7
  8. package/docs/ph-analysis.html +145 -0
  9. package/docs/ph-manual.md +337 -376
  10. package/docs/specs/SPEC-001-architecture-cli.md +82 -0
  11. package/docs/specs/SPEC-002-database-layer.md +105 -0
  12. package/docs/specs/SPEC-003-capture-modes.md +110 -0
  13. package/docs/specs/SPEC-004-filter-metadata.md +82 -0
  14. package/docs/specs/SPEC-005-search.md +102 -0
  15. package/docs/specs/SPEC-006-analysis-pipeline.md +98 -0
  16. package/docs/specs/SPEC-007-memory-summaries.md +96 -0
  17. package/docs/specs/SPEC-008-embeddings.md +90 -0
  18. package/docs/specs/SPEC-009-retention-archive.md +91 -0
  19. package/docs/specs/SPEC-010-remote-sync.md +106 -0
  20. package/docs/specs/SPEC-011-mcp-server.md +94 -0
  21. package/docs/specs/SPEC-012-tui-browser.md +98 -0
  22. package/docs/specs/SPEC-013-importers.md +109 -0
  23. package/docs/specs/SPEC-014-analytics-commands.md +109 -0
  24. package/docs/specs/SPEC-015-config-env.md +85 -0
  25. package/docs/specs/SPEC-INDEX.md +35 -0
  26. package/docs/specs/SPEC-ISSUES.md +122 -0
  27. package/docs/specs/_TEMPLATE.md +65 -0
  28. package/docs/superpowers/plans/2026-06-12-ph-evolution-phase1.md +466 -0
  29. package/docs/superpowers/plans/2026-06-12-ph-evolution-phase2.md +351 -0
  30. package/docs/superpowers/specs/2026-06-12-ph-evolution-design.md +173 -0
  31. package/hooks/codex/README.md +54 -0
  32. package/hooks/codex/ph-hook.sh +14 -0
  33. package/hooks/opencode/ph-plugin.ts +60 -57
  34. package/package.json +13 -12
package/docs/ph-manual.md CHANGED
@@ -1,518 +1,479 @@
1
- # ph — Prompt History CLI
1
+ # ph — Prompt History and Project Memory
2
2
 
3
- **Architecture, Hook System & Usage Guide**
3
+ **Zero-friction capture, semantic search, project memory, and MCP-based knowledge retrieval for AI CLI tools.**
4
4
 
5
5
  ---
6
6
 
7
7
  ## 1. Overview
8
8
 
9
- ph is a transparent capture layer for AI CLI tools such as Claude Code and Gemini CLI. Every prompt you type — and the AI response that follows — is automatically saved to a local SQLite database with full-text and semantic search, Git context, and optional background analysis.
9
+ ph is a transparent observability and knowledge layer for AI CLI tools (Claude Code, Codex CLI, Gemini CLI, OpenCode, etc.). It automatically records every prompt+response into a local SQLite database with full-text search, semantic vector search, LLM-based analysis, Git context snapshots, session grouping, and an interactive TUI browser.
10
10
 
11
- The core design principle is zero friction: ph never interrupts your workflow. Capture happens silently in the background. Your AI sessions remain unchanged.
11
+ **Core principle:** ph captures conversations without changing the normal tool workflow. Optional analysis turns captured history into project summaries and memories that can be searched locally or requested by an MCP client. Capture and full-text search work without an LLM provider; analysis, embeddings, and semantic search require the configured provider.
12
12
 
13
13
  ### Key Features
14
14
 
15
- - **Automatic Capture** — saves prompts, responses, and metadata without any manual action
16
- - **Git Context** — records current branch, modified files, and diff at capture time
17
- - **Full-text & Semantic Search** — FTS5 text search and vector-based semantic search (via Ollama embeddings)
18
- - **Background Analysis** — automatic role/tag/relevance classification via Ollama or Gemini
19
- - **Interactive TUI** — browse, filter, edit, re-run, and export your history with `ph browse`
20
- - **Privacy First** — all data stays local; no data ever leaves your machine
15
+ - **Automatic capture** via hooks (Claude Code, Codex CLI, Gemini CLI, OpenCode plugin) or wrapper mode
16
+ - **Full-text search** (FTS5) and **semantic vector search** (Ollama embeddings, 768-dim via sqlite-vec)
17
+ - **LLM analysis** — role/tag/relevance classification, summary extraction, key insights, technical decisions
18
+ - **Project memory** — per-project accumulated knowledge with deduped insights and decisions
19
+ - **MCP server** — tools for agents to search memories, check project knowledge, get context
20
+ - **Interactive TUI** — browse, filter, edit, star, re-run, export prompts
21
+ - **Session grouping** — automatic conversation grouping with cohesion scoring
22
+ - **Git context** — records branch, modified files, and diff at capture time
23
+ - **Background analysis** — async LLM processing after each capture (optional)
24
+ - **Retention & archiving** — configurable auto-archive of old/low-relevance prompts
25
+ - **Remote sync** — push/pull prompt history across machines via HTTP server
26
+ - **Local-first storage** — the database stays on the configured machine unless optional remote sync is enabled; no telemetry is sent
21
27
 
22
28
  ---
23
29
 
24
- ## 2. Architecture
30
+ ## 2. Installation
25
31
 
26
- ph uses a two-tier storage model: a SQLite database with FTS5 full-text indexing for fast retrieval, and a JSON config file for runtime settings. Both live in your home directory by default.
27
-
28
- ### Storage Layout
29
-
30
- | Item | Default Path | Description |
31
- |------|-------------|-------------|
32
- | Database | `~/.prompt_history.db` | SQLite with FTS5 + vector embeddings |
33
- | Config | `~/.ph_config.json` | JSON config file (0o600 permissions) |
34
-
35
- The database uses WAL (Write-Ahead Logging) mode, enabling concurrent reads and writes. This is essential for the background analysis system, which processes prompts asynchronously without blocking your terminal session.
36
-
37
- ---
38
-
39
- ## 3. The Hook System
40
-
41
- The hook system is ph's most powerful integration mechanism. Rather than requiring you to manually invoke ph for each session, hooks let the AI CLI tools themselves notify ph after every interaction — automatically, silently, and without any impact on response latency.
42
-
43
- > **Key insight:** Hooks are post-action handlers registered inside the AI tool's own config. ph never wraps or intercepts the AI process. The AI runs normally; the hook fires after the session ends.
44
-
45
- ### How Hooks Work
46
-
47
- Each supported AI CLI tool exposes a native hook mechanism:
32
+ ```bash
33
+ # Via npm
34
+ npm install -g @gi4nks/ph
48
35
 
49
- - **Claude Code** — provides a `Stop` hook, triggered after each agent session completes
50
- - **Gemini CLI** — provides an `AfterAgent` hook, triggered after each agent turn
36
+ # From source
37
+ git clone git@github.com:gi4nks/ph.git
38
+ cd ph
39
+ npm install
40
+ npm run build
41
+ npm link
42
+ ```
51
43
 
52
- When the hook fires, the AI tool passes a JSON payload on stdin to your registered script. The script reads that payload, extracts the prompt and response, and pipes the data to `ph log` — which persists everything to the local SQLite database.
44
+ ### Quick config
53
45
 
54
- The entire operation runs in the background using shell job control (`& + disown`), so it never adds latency to your terminal session and never blocks the AI tool from exiting.
46
+ ```bash
47
+ ph config set background-analysis true # auto-analyze after each capture
48
+ ph config set analyze-provider ollama # ollama (default) or gemini
49
+ ph config set ollama-model llama3.1:latest
50
+ ```
55
51
 
56
52
  ---
57
53
 
58
- ### Claude Code Hook
54
+ ## 3. Capture Modes
59
55
 
60
- #### How Claude Code delivers data
56
+ ### 3a. Hook mode (recommended)
61
57
 
62
- When the `Stop` hook fires, Claude Code sends a JSON object on stdin:
58
+ AI CLI tools invoke `ph log` automatically after each interaction.
63
59
 
64
- ```json
65
- {
66
- "session_id": "abc123...",
67
- "transcript_path": "/path/to/session.jsonl"
68
- }
60
+ **Claude Code** — `hooks/claude/ph-hook.sh`:
61
+ ```bash
62
+ ln -sf $(pwd)/hooks/claude/ph-hook.sh ~/.claude/ph-hook.sh
63
+ # Add to ~/.claude/settings.json:
64
+ # "hooks": { "Stop": [{ "matcher": ".*", "hooks": [{ "type": "command", "command": "~/.claude/ph-hook.sh", "async": true }] }] }
69
65
  ```
70
66
 
71
- The transcript is a JSONL file — one JSON object per line — containing the full session history. Each line is one of:
72
-
73
- | Turn type | Identifier |
74
- |-----------|-----------|
75
- | Human turn | Has `promptId` key; `message.content` is a plain string |
76
- | Tool result | Has `toolUseResult` key; `message.content` is an array |
77
- | Assistant turn | `message.role == "assistant"`; content is an array of typed blocks |
78
-
79
- #### What the hook script does
80
-
81
- 1. Reads the hook input from stdin to obtain the transcript path
82
- 2. Uses `jq` with slurp mode to parse the entire JSONL in one pass
83
- 3. Filters for genuine human turns: must have `promptId`, string content, and no `toolUseResult` key
84
- 4. Extracts the last human turn as the prompt
85
- 5. Scans assistant turns for the last `text`-type block as the response
86
- 6. Builds a JSON payload with `tool`, `prompt`, `response`, and `workdir` fields
87
- 7. Pipes the payload to `ph log` running in the background (`& + disown`)
88
- 8. Exits `0` unconditionally — Claude Code is never blocked
89
-
90
- #### Hook installation — Claude Code
91
-
67
+ **Gemini CLI** — `hooks/gemini/ph-hook.sh`:
92
68
  ```bash
93
- # Step 1: link the hook script
94
- ln -sf /path/to/ph/hooks/claude/ph-hook.sh ~/.claude/ph-hook.sh
95
-
96
- # Step 2: register in ~/.claude/settings.json
97
- {
98
- "hooks": {
99
- "Stop": [
100
- {
101
- "matcher": ".*",
102
- "hooks": [
103
- {
104
- "type": "command",
105
- "command": "~/.claude/ph-hook.sh",
106
- "async": true
107
- }
108
- ]
109
- }
110
- ]
111
- }
112
- }
69
+ ln -sf $(pwd)/hooks/gemini/ph-hook.sh ~/.gemini/ph-hook.sh
70
+ # Add to ~/.gemini/settings.json:
71
+ # "hooks": { "AfterAgent": [{ "hooks": [{ "type": "command", "command": "~/.gemini/ph-hook.sh" }] }] }
113
72
  ```
114
73
 
115
- ---
116
-
117
- ### Gemini CLI Hook
74
+ **OpenCode** — plugin at `hooks/opencode/ph-plugin.ts`:
75
+ ```bash
76
+ ./hooks/opencode/install.sh # global install
77
+ ```
118
78
 
119
- #### How Gemini CLI delivers data
79
+ **Codex CLI** — see [the Codex hook setup](../hooks/codex/README.md). The Stop
80
+ hook imports the active rollout transcript. To import existing sessions, run
81
+ `ph import codex --dry-run` and then `ph import codex`.
120
82
 
121
- Gemini CLI's `AfterAgent` hook is simpler: it delivers the prompt and response directly in the stdin payload, with no transcript file to parse:
83
+ ### 3b. Wrapper mode
122
84
 
123
- ```json
124
- {
125
- "session_id": "...",
126
- "transcript_path": "...",
127
- "cwd": "/path/to/workdir",
128
- "hook_event_name": "AfterAgent",
129
- "timestamp": "...",
130
- "prompt": "the user's prompt text",
131
- "prompt_response": "the assistant's full response text"
132
- }
85
+ ```bash
86
+ ph claude "explain goroutines"
87
+ ph codex exec "explain goroutines"
88
+ ph gemini "refactor this code"
89
+ ph --ph-role debug --ph-tag auth claude "fix JWT expiration"
133
90
  ```
134
91
 
135
- #### What the hook script does
136
-
137
- 1. Reads the JSON payload from stdin
138
- 2. Extracts `prompt`, `prompt_response`, and `cwd` directly via `jq`
139
- 3. Builds a JSON payload with `tool`, `prompt`, `response`, and `workdir` fields
140
- 4. Pipes to `ph log` in the background
141
- 5. Exits `0` unconditionally
142
-
143
- #### Hook installation — Gemini CLI
92
+ ### 3c. Direct log
144
93
 
145
94
  ```bash
146
- # Step 1: link the hook script
147
- ln -sf /path/to/ph/hooks/gemini/ph-hook.sh ~/.gemini/ph-hook.sh
148
-
149
- # Step 2: register in ~/.gemini/settings.json
150
- {
151
- "hooks": {
152
- "AfterAgent": [
153
- {
154
- "hooks": [
155
- {
156
- "type": "command",
157
- "command": "~/.gemini/ph-hook.sh"
158
- }
159
- ]
160
- }
161
- ]
162
- }
163
- }
95
+ ph log --tool claude --prompt "your prompt" --response "response text"
96
+ echo '{"tool":"claude","prompt":"hi","response":"hello"}' | ph log --stdin
164
97
  ```
165
98
 
166
99
  ---
167
100
 
168
- ### OpenCode Hook
169
-
170
- OpenCode uses a JavaScript/TypeScript **plugin** system (rather than shell scripts). The `ph` integration is a plugin that hooks into OpenCode's message lifecycle to capture prompts and responses.
171
-
172
- #### How the plugin captures data
173
-
174
- The plugin registers two hooks inside OpenCode's runtime:
175
-
176
- | Hook | Purpose |
177
- |------|---------|
178
- | `chat.message` | Intercepts every message in the conversation. User messages become prompts; assistant messages become response snapshots. |
179
- | `experimental.text.complete` | Fires after streaming completes. Replaces the snapshot with the full, final response text. |
180
-
181
- **Data flow:**
101
+ ## 4. CLI Commands
102
+
103
+ | Command | Description |
104
+ |---------|-------------|
105
+ | `ph` (no args) | Open interactive TUI browser |
106
+ | `ph <tool> [args...]` | Wrapper mode — run tool + capture |
107
+ | `ph search [query]` | Full-text search prompts |
108
+ | `ph search --semantic <query>` | Semantic (vector) search |
109
+ | `ph search --archive` | Search archived prompts |
110
+ | `ph search -i <query>` | Open results in interactive TUI |
111
+ | `ph last [n]` | Show last N prompts |
112
+ | `ph context [query]` | Get RAG context for current project |
113
+ | `ph sessions` | Group prompts into work sessions |
114
+ | `ph timeline <project>` | Full chronological project history |
115
+ | `ph stats` | History statistics |
116
+ | `ph cluster -k 5` | K-means clustering on embeddings |
117
+ | `ph analyze` | LLM analysis of untagged prompts |
118
+ | `ph analyze-reusability` | Reusability scoring |
119
+ | `ph cleanup` | Remove useless prompts (length/duplicates) |
120
+ | `ph cleanup --retention` | Archive old/unqualified prompts per retention policy |
121
+ | `ph cleanup-reusability` | Cleanup by reusability score |
122
+ | `ph star <id>` | Toggle bookmark |
123
+ | `ph export <id>` | Export prompt (txt/json/md) |
124
+ | `ph import gemini|claude|opencode|codex` | Import from AI CLI history |
125
+ | `ph log --tool <name> ...` | Direct log (hook target) |
126
+ | `ph embed-all` | Generate embeddings for all prompts |
127
+ | `ph config get|set <key> <value>` | View/edit config |
128
+ | `ph vacuum` | Compact SQLite database |
129
+ | `ph memory-migrate` | Merge existing memories into project_summaries |
130
+ | `ph mcp` | Start MCP stdio server |
131
+ | `ph server --port 3001` | Start HTTP REST server |
132
+ | `ph remote push|pull|status` | Sync with remote ph server |
133
+ | `ph chat <tool> <prompt>` | Run tool with project context injected |
134
+ | `ph ollama-models` | List available Ollama models |
135
+
136
+ ### Search options
182
137
 
183
138
  ```
184
- User types prompt
185
- → chat.message fires (role: user)
186
- → plugin stores the prompt text + metadata (agent, model, workdir)
187
-
188
- Assistant streams response
189
- → experimental.text.complete fires for each text part
190
- → plugin accumulates the complete response text
191
-
192
- Next user message or session end
193
- → plugin pairs prompt + accumulated response
194
- → pipes {"tool":"opencode","prompt":"...","response":"..."} to ph log
195
- → runs in background — never blocks OpenCode
139
+ -i / --interactive Open in TUI browser
140
+ --tool <name> Filter by tool
141
+ --project <name> Filter by project
142
+ --language <lang> Filter by language
143
+ --role <role> Filter by role
144
+ --tag <tag> Filter by tag
145
+ --starred Show only starred
146
+ --semantic Use semantic (vector) search
147
+ --archive Search archived prompts
148
+ --since YYYY-MM-DD Start date
149
+ --until YYYY-MM-DD End date
150
+ --limit <n> Max results (default 50)
151
+ --top Quality >= 8
152
+ --min-quality <n> Min quality (0-10)
153
+ --min-relevance <n> Min relevance (0-10)
154
+ --full Show full prompt text
196
155
  ```
197
156
 
198
- #### Hook installation — OpenCode
157
+ ### Context options
199
158
 
200
- OpenCode loads plugins from two directories:
201
- - `~/.config/opencode/plugins/` — global (all projects)
202
- - `.opencode/plugins/` — per-project
203
-
204
- **Option A: Quick install (global)**
205
-
206
- ```bash
207
- # Link the plugin into OpenCode's global plugin directory
208
- mkdir -p ~/.config/opencode/plugins
209
- ln -sf /path/to/ph/hooks/opencode/ph-plugin.ts ~/.config/opencode/plugins/ph-plugin.ts
210
159
  ```
211
-
212
- Or use the install script:
213
-
214
- ```bash
215
- ./hooks/opencode/install.sh # global (default)
216
- ./hooks/opencode/install.sh --project # current project only
160
+ --project <name> Project name (default: auto-detect)
161
+ --limit <n> Max results (default 5)
162
+ --prompts-only Skip project knowledge, show only prompts
163
+ --memories-only Skip prompts, show only project knowledge
164
+ --verbose Include full prompt text
217
165
  ```
218
166
 
219
- **Option B: Manual copy**
167
+ ### Sessions options
220
168
 
221
- ```bash
222
- cp hooks/opencode/ph-plugin.ts ~/.config/opencode/plugins/
223
169
  ```
224
-
225
- The plugin is automatically loaded on the next OpenCode startup. No config changes needed — Bun handles TypeScript natively.
226
-
227
- **Verify:**
228
-
229
- ```bash
230
- # Start OpenCode — the plugin loads silently
231
- opencode
232
-
233
- # Check that prompts are being captured
234
- ph search --tool opencode --limit 3
170
+ --gap-hours <n> Hours gap to split sessions (default 2)
171
+ --limit <n> Max sessions (default 20)
172
+ --min-size <n> Min prompts per session (default 1)
173
+ --no-cohesion Skip semantic cohesion computation
174
+ --export <n> Export session N as markdown
235
175
  ```
236
176
 
237
- **Uninstall:**
177
+ ### Cluster options
238
178
 
239
- ```bash
240
- rm ~/.config/opencode/plugins/ph-plugin.ts
179
+ ```
180
+ -k <number> Number of clusters (default 5)
181
+ --limit <n> Max prompts per cluster to show (default 3)
241
182
  ```
242
183
 
243
184
  ---
244
185
 
245
- ### Hook Comparison
186
+ ## 5. TUI Keybindings
246
187
 
247
- | Aspect | Claude Code | Gemini CLI | OpenCode |
248
- |--------|------------|------------|----------|
249
- | Hook mechanism | `Stop` shell script | `AfterAgent` shell script | JS/TS plugin |
250
- | Data delivery | `transcript_path` (JSONL) | Direct JSON on stdin | Event hooks (`chat.message`, `experimental.text.complete`) |
251
- | Prompt extraction | Parse JSONL with `jq` slurp | `jq .prompt` | `message.role === 'user'` parts |
252
- | Response extraction | Last assistant text block | `jq .prompt_response` | `experimental.text.complete` accumulation |
253
- | Async support | Yes (`async: true`) | Yes (`& + disown`) | Yes (Promise fire-and-forget) |
254
- | Blocks AI exit? | Never | Never | Never |
255
- | Install method | Symlink + settings.json | Symlink + settings.json | Copy plugin file to `plugins/` dir |
188
+ | Key | Action |
189
+ |-----|--------|
190
+ | `Up` / `Down`, `Page Up` / `Page Down` | Navigate list |
191
+ | `Tab` | Switch pane (wide mode) |
192
+ | `1`, `2`, `3` | Switch prompt/response/memory tab |
193
+ | `y` | Copy to clipboard |
194
+ | `s` | Toggle star |
195
+ | `e` | Edit metadata |
196
+ | `r` | Rerun prompt (edit before launch) |
197
+ | `Shift+C` | Chat mode: launch tool with project context |
198
+ | `x` | Delete entry |
199
+ | `/` | Search |
200
+ | `o` | Settings panel (toggle auto-analysis, view config) |
201
+ | `f` | Filter panel (flat list, Enter toggle, letter jump) |
202
+ | `c` | Clear all filters |
203
+ | `q` / `Escape` | Quit / back |
204
+
205
+ ### TUI components
206
+
207
+ - **SearchBar** — always visible spotlight bar at top
208
+ - **FilterPanel** — flat scrollable list of filter options with counts `[N]`, toggle with Enter, jump by letter
209
+ - **SettingsView** — config viewer/editor (auto-analysis toggle, ollama URL/model, filters)
210
+ - **PreviewPane** — three tabs (prompt/response/memory). Memory tab shows project-level knowledge
211
+ - **ListEntry** — role marker, analysis status, star, Q/R badges, optional summary line
212
+ - **Footer** — context-sensitive hints (shows `C:chat` only when entry has project)
256
213
 
257
214
  ---
258
215
 
259
- ## 4. Installation
216
+ ## 6. Project Memory System
260
217
 
261
- ### From Source
218
+ ph maintains two levels of per-project knowledge:
262
219
 
263
- ```bash
264
- git clone git@github.com:gi4nks/ph.git
265
- cd ph
266
- npm install
267
- make build
268
- make install # installs the global 'ph' symlink
269
- ```
220
+ ### 6a. `project_summaries` (curated, 1 row per project)
270
221
 
271
- ### Via npm
222
+ Accumulated knowledge with deduped insights and decisions. Updated on every analysis. Primary source for MCP tools.
272
223
 
273
224
  ```bash
274
- # Install globally:
275
- npm install -g @gi4nks/ph
225
+ # View accumulated project knowledge
226
+ ph context --project myproject
227
+
228
+ # Via MCP (for AI agents)
229
+ # get_project_summary(project: "myproject")
276
230
  ```
277
231
 
278
- ### Initial Configuration
232
+ ### 6b. `memories` (append-only timeline)
279
233
 
280
- ```bash
281
- # Set your Gemini API key (optional — Ollama works without it)
282
- ph config set gemini-api-key "YOUR_KEY"
234
+ Full chronological history of every analysis run. Preserved for detailed audit.
283
235
 
284
- # Choose your analysis provider
285
- ph config set analyze-provider ollama # default, fully local
286
- # ph config set analyze-provider gemini # cloud alternative
236
+ ### Memory migration
287
237
 
288
- # Enable background analysis
289
- ph config set background-analysis true
238
+ If you have existing data from before the evolution phases:
290
239
 
291
- # Optional: move the database to a custom location
292
- ph config set db-path "/path/to/your/custom.db"
240
+ ```bash
241
+ ph memory-migrate # one-time: merge all memories into project_summaries
293
242
  ```
294
243
 
295
244
  ---
296
245
 
297
- ## 5. Usage
246
+ ## 7. Retention & Archiving
298
247
 
299
- ### Search
248
+ Configurable auto-archiving to keep the database lean:
300
249
 
301
250
  ```bash
302
- # Full-text search
303
- ph search "how to refactor"
251
+ # Configure
252
+ ph config set retentionDays 90 # archive prompts older than 90 days
253
+ ph config set retentionMinRelevance 3 # prompts below this relevance archived first
254
+ ph config set retentionMinStarred true # starred prompts never archived
255
+ ph config set retentionMinAnalyzed true # analyzed prompts never archived
304
256
 
305
- # Semantic search (vector similarity)
306
- ph search --semantic "refactoring patterns"
307
- ```
257
+ # Run retention cleanup
258
+ ph cleanup --retention # archive matching prompts
259
+ ph cleanup --retention --dry-run # preview only
308
260
 
309
- ### Interactive TUI
261
+ # Search archived prompts
262
+ ph search --archive
310
263
 
311
- ```bash
312
- ph browse
264
+ # Auto-purge: entries older than 2x retentionDays are deleted during cleanup
313
265
  ```
314
266
 
315
- Available hotkeys inside the TUI:
267
+ ---
316
268
 
317
- | Key | Action |
318
- |-----|--------|
319
- | `f` | Open filters panel |
320
- | `e` | Edit prompt metadata (tags, notes) |
321
- | `r` | Re-run selected prompt in your AI tool |
322
- | `y` | Copy prompt to clipboard |
323
- | `x` | Delete prompt from history |
269
+ ## 8. Background Analysis
324
270
 
325
- ### Export
271
+ When enabled, every `ph log` automatically spawns a detached child process that analyzes the new entry (role, tags, relevance, summary, key insights, technical decisions).
326
272
 
327
273
  ```bash
328
- # Export last 5 prompts as Markdown
329
- ph export --format md --limit 5 > prompts.md
274
+ ph config set background-analysis true
330
275
  ```
331
276
 
332
- ### Database Maintenance
277
+ Analysis uses Ollama by default (requires `ollama serve` running). Configure:
333
278
 
334
279
  ```bash
335
- # Remove short or old prompts
336
- ph cleanup --min-length 20 --days 30
337
-
338
- # Compact the database
339
- ph vacuum
340
-
341
- # Dry-run to preview what would be removed
342
- ph cleanup --dry-run --days 60
280
+ ph config set analyze-provider gemini # use Gemini instead
281
+ ph config set gemini-api-key "YOUR_KEY"
282
+ ph config set ollama-model llama3.1:latest
283
+ ph config set ollama-embed-model nomic-embed-text-v2-moe
343
284
  ```
344
285
 
345
286
  ---
346
287
 
347
- ## 6. Why Prompt History Matters
288
+ ## 9. MCP Server
348
289
 
349
- Every interaction with an AI tool is a unit of intellectual work. A well-crafted prompt encodes context, intent, and engineering decisions that took time to develop. Without capture, that work is lost the moment the session closes.
290
+ ph exposes an MCP (Model Context Protocol) server over stdio for AI agents:
350
291
 
351
- ph treats your prompt history as a first-class artifact: searchable, annotated, versioned with Git context, and available for re-use. Over time, your history becomes a personal knowledge base of how you think and work with AI tools.
352
-
353
- > **The problem:** Manually saving prompts takes time, breaks flow, and rarely happens consistently. Without structure, even saved prompts become unsearchable noise.
354
-
355
- > **The solution:** ph captures everything automatically via hooks, indexes it locally, and gives you semantic search so you can find what you need — even if you only remember the intent, not the exact wording.
292
+ ```bash
293
+ ph mcp
294
+ ```
356
295
 
357
- ---
296
+ ### Available tools
297
+
298
+ | Tool | Description |
299
+ |------|-------------|
300
+ | `search_project_memory` | Semantic search + fallback to project_summaries |
301
+ | `get_project_context` | Merged summary + recent memories + recent prompts |
302
+ | `get_project_summary` | Accumulated key insights and technical decisions |
303
+ | `check_project_knowledge` | Before implementing: checks memories + prompts for existing work |
304
+ | `save_decision` | Persist an architectural decision to memory + summaries |
305
+ | `search_prompts` | Full-text search over prompt history |
306
+ | `get_prompt` | Full details by ID |
307
+ | `search_prompts_semantic` | Vector search over prompts |
308
+ | `get_project_timeline` | Full chronological project history |
309
+ | `get_project_diff` | Compare project state between dates |
310
+ | `list_prompts` | Paginated prompt listing |
358
311
 
359
312
  ---
360
313
 
361
- ## 7. Remote Server Setup
362
-
363
- ph can act as a central sync hub for prompt history across multiple machines.
314
+ ## 10. HTTP Server & Remote Sync
364
315
 
365
- ### Server Installation
316
+ Share prompt history across machines:
366
317
 
367
318
  ```bash
368
- # Install globally
369
- sudo npm install -g @gi4nks/ph
370
-
371
- # Verify
372
- ph --help
319
+ # Start server
320
+ ph server --port 3001 --host 0.0.0.0
321
+
322
+ # From another machine
323
+ ph config set remote-url http://server-ip:3001
324
+ ph remote push # send local unsynced prompts
325
+ ph remote pull # fetch remote prompts
326
+ ph remote status # show sync state
373
327
  ```
374
328
 
375
- ### Ubuntu (systemd service)
329
+ Every `ph log` auto-pushes to remote if configured (fire-and-forget, never blocks).
376
330
 
377
- Create `/etc/systemd/system/ph.service`:
331
+ ---
378
332
 
379
- ```ini
380
- [Unit]
381
- Description=ph remote sync server
382
- After=network.target
333
+ ## 11. Database
383
334
 
384
- [Service]
385
- Type=simple
386
- ExecStart=<path-to-ph> server --port 3001 --host 0.0.0.0
387
- Restart=always
388
- RestartSec=5
389
- User=<your-user>
390
- Environment=NODE_ENV=production
391
- StandardOutput=append:/var/log/ph-server.log
392
- StandardError=append:/var/log/ph-server.log
335
+ **Location:** `~/.prompt_history.db` (configurable via `ph config set db-path`)
393
336
 
394
- [Install]
395
- WantedBy=multi-user.target
396
- ```
337
+ **Tables:**
397
338
 
398
- Replace `<path-to-ph>` with the output of `which ph` on the server, and `<your-user>` with the user running the service.
339
+ | Table | Purpose |
340
+ |-------|---------|
341
+ | `prompts` | Main prompt+response storage with FTS5 index |
342
+ | `prompts_archive` | Archived (retention-aged) prompts |
343
+ | `memories` | Append-only per-project analysis timeline |
344
+ | `project_summaries` | Single curated row per project with merged knowledge |
345
+ | `vec_embeddings` | Vector embeddings (768-dim float, sqlite-vec) |
346
+ | `embeddings` | Legacy BLOB embeddings (migrated on connect) |
399
347
 
400
- ```bash
401
- sudo systemctl daemon-reload
402
- sudo systemctl enable --now ph.service
403
- sudo systemctl status ph.service
404
- sudo ufw allow 3001/tcp # if firewall is enabled
405
- ```
406
-
407
- ### macOS (launchd)
408
-
409
- Create `~/Library/LaunchAgents/com.gi4nks.ph.plist`:
410
-
411
- ```xml
412
- <?xml version="1.0" encoding="UTF-8"?>
413
- <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
414
- <plist version="1.0">
415
- <dict>
416
- <key>Label</key>
417
- <string>com.gi4nks.ph</string>
418
- <key>ProgramArguments</key>
419
- <array>
420
- <string>/usr/local/bin/ph</string>
421
- <string>server</string>
422
- <string>--port</string>
423
- <string>3001</string>
424
- <string>--host</string>
425
- <string>0.0.0.0</string>
426
- </array>
427
- <key>RunAtLoad</key>
428
- <true/>
429
- <key>KeepAlive</key>
430
- <true/>
431
- <key>StandardOutPath</key>
432
- <string>/tmp/ph-server.log</string>
433
- <key>StandardErrorPath</key>
434
- <string>/tmp/ph-server.err</string>
435
- </dict>
436
- </plist>
437
- ```
348
+ **Maintenance:**
438
349
 
439
350
  ```bash
440
- launchctl load ~/Library/LaunchAgents/com.gi4nks.ph.plist
351
+ ph vacuum # compact DB
352
+ ph cleanup # remove short/trivial/duplicate prompts
353
+ ph cleanup --retention # archive per retention policy
354
+ ph embed-all # (re)generate all embeddings
441
355
  ```
442
356
 
443
- ### Client Setup
357
+ ---
444
358
 
445
- ```bash
446
- # Configure remote server URL
447
- ph config set remote-url http://<server-ip>:3001
448
- # Or via env var (takes precedence)
449
- export PH_REMOTE_URL=http://<server-ip>:3001
450
-
451
- # Sync commands
452
- ph remote push # send unsynced local prompts to server
453
- ph remote pull # fetch remote prompts since last pull
454
- ph remote status # show sync state
455
- ```
359
+ ## 12. Filter Pipeline
456
360
 
457
- After `ph remote-url` is configured, every `ph log` automatically does a background push to the server (fire-and-forget, never blocks).
361
+ Before saving, ph filters out:
458
362
 
459
- ### Logs
363
+ - Prompts shorter than `filterMinLength` (default 15 chars)
364
+ - Non-printable content
365
+ - Trivial patterns (single chars, common noise)
366
+ - Exact duplicates (within last 7 days)
367
+ - Low-relevance prompts (when `--min-relevance` is set)
460
368
 
461
- ```bash
462
- # systemd
463
- sudo journalctl -u ph.service -f
369
+ Configure:
464
370
 
465
- # launchd
466
- cat /tmp/ph-server.log
371
+ ```bash
372
+ ph config set filter-min-length 20
373
+ ph config set filter-min-relevance 3
467
374
  ```
468
375
 
469
376
  ---
470
377
 
471
- ## 8. Release Process
378
+ ## 13. Configuration (`~/.ph_config.json`)
379
+
380
+ | Key | Default | Description |
381
+ |-----|---------|-------------|
382
+ | `dbPath` | `~/.prompt_history.db` | SQLite database path |
383
+ | `analyzeProvider` | `ollama` | LLM provider: `ollama` or `gemini` |
384
+ | `ollamaUrl` | `http://localhost:11434` | Ollama server URL |
385
+ | `ollamaModel` | `llama3.1:latest` | Analysis model |
386
+ | `ollamaEmbedModel` | `nomic-embed-text-v2-moe` | Embedding model |
387
+ | `geminiApiKey` | — | Gemini API key |
388
+ | `backgroundAnalysis` | `false` | Auto-analyze after each capture |
389
+ | `filterMinLength` | `15` | Min prompt length to keep |
390
+ | `filterMinRelevance` | `3` | Min relevance to keep (0=disable) |
391
+ | `retentionDays` | `90` | Auto-archive after N days |
392
+ | `retentionMinStarred` | `true` | Keep starred prompts |
393
+ | `retentionMinAnalyzed` | `true` | Keep analyzed prompts |
394
+ | `retentionMinRelevance` | `3` | Archive prompts below this relevance |
395
+ | `remoteUrl` | — | Remote ph server URL (or `PH_REMOTE_URL` env) |
396
+ | `remoteApiKey` | — | Remote server API key |
397
+ | `remoteLastPush` | — | Timestamp of last successful push |
398
+ | `remoteLastPull` | — | Timestamp of last successful pull |
399
+
400
+ ---
401
+
402
+ ## 14. Architecture
472
403
 
473
- Releases are fully automated via **semantic-release** using conventional commits.
404
+ ```
405
+ Hook/Import → ph log → prompts table (FTS5 indexed)
406
+ ↓
407
+ Background analysis (optional)
408
+ ↓
409
+ ┌────────────────┴────────────────┐
410
+ ↓ ↓
411
+ memories (append-only, project_summaries
412
+ with TTL) (1 row per project,
413
+ merged + deduped)
414
+ ↓ ↓
415
+ ph cleanup --retention MCP tools read
416
+ → prompts_archive from here
417
+ ```
474
418
 
475
- ### How it works
419
+ ### File layout
476
420
 
477
- 1. All commits must follow the [Conventional Commits](https://www.conventionalcommits.org/) format:
421
+ ```
422
+ src/
423
+ cli.ts # Entry point (~80 lines), switch dispatch
424
+ types.ts # Core types (PromptEntry, MemoryEntry, ProjectSummary, etc.)
425
+ db/index.ts # PhDB public SQLite adapter
426
+ db/semantic-index.ts # Vector encoding, storage, and nearest-neighbor search
427
+ context/index.ts # Shared project-context retrieval and rendering
428
+ capture/index.ts # Shared capture-record normalization
429
+ commands/ # One module per CLI command
430
+ analyzer/ # LLM analysis (role/tag/relevance/summary/insights)
431
+ embedding/ # Ollama embedding generation
432
+ filter/ # Capture-time filter pipeline
433
+ mcp/server.ts # MCP stdio server
434
+ server/index.ts # HTTP REST server (zero deps)
435
+ ui/ # React/Ink TUI, including extracted filter policy and panel
436
+ importer/ # Gemini/Claude/OpenCode/Codex history importers
437
+ hooks/ # Shell scripts and plugins for AI tools
438
+ ```
478
439
 
479
- ```
480
- feat: add new feature → minor release (1.x.0)
481
- fix: resolve bug → patch release (1.0.x)
482
- chore: bump deps → no release
483
- BREAKING CHANGE: ... → major release (x.0.0)
484
- ```
440
+ ---
485
441
 
486
- 2. Push to `main` triggers GitHub Actions workflow `.github/workflows/release.yml`
442
+ ## 15. Importing Existing History
487
443
 
488
- 3. The workflow runs:
489
- - `actions/checkout@v4` with full git history (`fetch-depth: 0`)
490
- - `actions/setup-node@v4` with Node 22
491
- - `npm ci` — clean install
492
- - `npm run build` — tsup bundle
493
- - `npx semantic-release` — analyzes commits, bumps version, updates CHANGELOG.md, creates git tag, publishes to npm
444
+ ```bash
445
+ # Import from Claude Code
446
+ ph import claude --analyze
494
447
 
495
- ### npm publish details
448
+ # Import from Gemini CLI
449
+ ph import gemini --filter
496
450
 
497
- - **OIDC Trusted Publishing**: Package is signed with provenance attestation via GitHub Actions OIDC token
498
- - **Publisher identity**: `GitHub Actions <npm-oidc-no-reply@github.com>`
499
- - **Registry**: `https://registry.npmjs.org/`
500
- - **Access**: public
451
+ # Import from OpenCode
452
+ ph import opencode
501
453
 
502
- ### Verify provenance
454
+ # Import from Codex CLI
455
+ ph import codex --dry-run
456
+ ph import codex
503
457
 
504
- ```bash
505
- npm audit signatures
458
+ # Options:
459
+ # --analyze run LLM analysis on imported prompts
460
+ # --filter apply capture-time filters
461
+ # --dry-run preview without importing
506
462
  ```
507
463
 
508
- ### Manual release (emergency)
464
+ ---
465
+
466
+ ## 16. Versioning and Releases
509
467
 
510
- Create a tag manually and push:
468
+ Use Conventional Commits to describe changes: `feat:` requests a minor release,
469
+ `fix:` requests a patch release, and `BREAKING CHANGE:` requests a major release.
470
+ The GitHub Actions workflow runs `semantic-release` on pushes to `main`, updates
471
+ release metadata, publishes to npm, and creates a GitHub release.
511
472
 
512
- ```bash
513
- git tag v1.2.3
514
- git push origin v1.2.3
515
- ```
473
+ The Make targets `make release-patch`, `make release-minor`, and
474
+ `make release-major` increment `package.json` and `package-lock.json` locally.
475
+ They do not commit, tag, or publish. The automated release workflow determines
476
+ the actual published version from commits since its most recent release tag.
516
477
 
517
478
  ---
518
479