@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.
- package/CHANGELOG.md +2 -2
- package/README.md +118 -152
- package/dist/cli.js +2049 -1055
- package/dist/cli.js.map +1 -1
- package/docs/evals/context-retrieval-golden.json +26 -0
- package/docs/evals/context-retrieval.md +27 -0
- package/docs/hooks.md +13 -7
- package/docs/ph-analysis.html +145 -0
- package/docs/ph-manual.md +337 -376
- package/docs/specs/SPEC-001-architecture-cli.md +82 -0
- package/docs/specs/SPEC-002-database-layer.md +105 -0
- package/docs/specs/SPEC-003-capture-modes.md +110 -0
- package/docs/specs/SPEC-004-filter-metadata.md +82 -0
- package/docs/specs/SPEC-005-search.md +102 -0
- package/docs/specs/SPEC-006-analysis-pipeline.md +98 -0
- package/docs/specs/SPEC-007-memory-summaries.md +96 -0
- package/docs/specs/SPEC-008-embeddings.md +90 -0
- package/docs/specs/SPEC-009-retention-archive.md +91 -0
- package/docs/specs/SPEC-010-remote-sync.md +106 -0
- package/docs/specs/SPEC-011-mcp-server.md +94 -0
- package/docs/specs/SPEC-012-tui-browser.md +98 -0
- package/docs/specs/SPEC-013-importers.md +109 -0
- package/docs/specs/SPEC-014-analytics-commands.md +109 -0
- package/docs/specs/SPEC-015-config-env.md +85 -0
- package/docs/specs/SPEC-INDEX.md +35 -0
- package/docs/specs/SPEC-ISSUES.md +122 -0
- package/docs/specs/_TEMPLATE.md +65 -0
- package/docs/superpowers/plans/2026-06-12-ph-evolution-phase1.md +466 -0
- package/docs/superpowers/plans/2026-06-12-ph-evolution-phase2.md +351 -0
- package/docs/superpowers/specs/2026-06-12-ph-evolution-design.md +173 -0
- package/hooks/codex/README.md +54 -0
- package/hooks/codex/ph-hook.sh +14 -0
- package/hooks/opencode/ph-plugin.ts +60 -57
- package/package.json +13 -12
package/docs/ph-manual.md
CHANGED
|
@@ -1,518 +1,479 @@
|
|
|
1
|
-
# ph — Prompt History
|
|
1
|
+
# ph — Prompt History and Project Memory
|
|
2
2
|
|
|
3
|
-
**
|
|
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
|
|
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
|
-
|
|
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
|
|
16
|
-
- **
|
|
17
|
-
- **
|
|
18
|
-
- **
|
|
19
|
-
- **
|
|
20
|
-
- **
|
|
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.
|
|
30
|
+
## 2. Installation
|
|
25
31
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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
|
-
|
|
50
|
-
|
|
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
|
-
|
|
44
|
+
### Quick config
|
|
53
45
|
|
|
54
|
-
|
|
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
|
-
|
|
54
|
+
## 3. Capture Modes
|
|
59
55
|
|
|
60
|
-
|
|
56
|
+
### 3a. Hook mode (recommended)
|
|
61
57
|
|
|
62
|
-
|
|
58
|
+
AI CLI tools invoke `ph log` automatically after each interaction.
|
|
63
59
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
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
|
-
|
|
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
|
-
|
|
94
|
-
|
|
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
|
-
|
|
74
|
+
**OpenCode** — plugin at `hooks/opencode/ph-plugin.ts`:
|
|
75
|
+
```bash
|
|
76
|
+
./hooks/opencode/install.sh # global install
|
|
77
|
+
```
|
|
118
78
|
|
|
119
|
-
|
|
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
|
-
|
|
83
|
+
### 3b. Wrapper mode
|
|
122
84
|
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
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
|
-
|
|
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
|
-
|
|
147
|
-
|
|
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
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
|
177
|
-
|
|
178
|
-
| `
|
|
179
|
-
| `
|
|
180
|
-
|
|
181
|
-
|
|
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
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
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
|
-
|
|
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
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
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
|
-
|
|
167
|
+
### Sessions options
|
|
220
168
|
|
|
221
|
-
```bash
|
|
222
|
-
cp hooks/opencode/ph-plugin.ts ~/.config/opencode/plugins/
|
|
223
169
|
```
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
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
|
-
|
|
177
|
+
### Cluster options
|
|
238
178
|
|
|
239
|
-
```
|
|
240
|
-
|
|
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
|
-
|
|
186
|
+
## 5. TUI Keybindings
|
|
246
187
|
|
|
247
|
-
|
|
|
248
|
-
|
|
249
|
-
|
|
|
250
|
-
|
|
|
251
|
-
|
|
|
252
|
-
|
|
|
253
|
-
|
|
|
254
|
-
|
|
|
255
|
-
|
|
|
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
|
-
##
|
|
216
|
+
## 6. Project Memory System
|
|
260
217
|
|
|
261
|
-
|
|
218
|
+
ph maintains two levels of per-project knowledge:
|
|
262
219
|
|
|
263
|
-
|
|
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
|
-
|
|
222
|
+
Accumulated knowledge with deduped insights and decisions. Updated on every analysis. Primary source for MCP tools.
|
|
272
223
|
|
|
273
224
|
```bash
|
|
274
|
-
#
|
|
275
|
-
|
|
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
|
-
###
|
|
232
|
+
### 6b. `memories` (append-only timeline)
|
|
279
233
|
|
|
280
|
-
|
|
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
|
-
|
|
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
|
-
|
|
289
|
-
ph config set background-analysis true
|
|
238
|
+
If you have existing data from before the evolution phases:
|
|
290
239
|
|
|
291
|
-
|
|
292
|
-
ph
|
|
240
|
+
```bash
|
|
241
|
+
ph memory-migrate # one-time: merge all memories into project_summaries
|
|
293
242
|
```
|
|
294
243
|
|
|
295
244
|
---
|
|
296
245
|
|
|
297
|
-
##
|
|
246
|
+
## 7. Retention & Archiving
|
|
298
247
|
|
|
299
|
-
|
|
248
|
+
Configurable auto-archiving to keep the database lean:
|
|
300
249
|
|
|
301
250
|
```bash
|
|
302
|
-
#
|
|
303
|
-
ph
|
|
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
|
-
#
|
|
306
|
-
ph
|
|
307
|
-
|
|
257
|
+
# Run retention cleanup
|
|
258
|
+
ph cleanup --retention # archive matching prompts
|
|
259
|
+
ph cleanup --retention --dry-run # preview only
|
|
308
260
|
|
|
309
|
-
|
|
261
|
+
# Search archived prompts
|
|
262
|
+
ph search --archive
|
|
310
263
|
|
|
311
|
-
|
|
312
|
-
ph browse
|
|
264
|
+
# Auto-purge: entries older than 2x retentionDays are deleted during cleanup
|
|
313
265
|
```
|
|
314
266
|
|
|
315
|
-
|
|
267
|
+
---
|
|
316
268
|
|
|
317
|
-
|
|
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
|
-
|
|
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
|
-
|
|
329
|
-
ph export --format md --limit 5 > prompts.md
|
|
274
|
+
ph config set background-analysis true
|
|
330
275
|
```
|
|
331
276
|
|
|
332
|
-
|
|
277
|
+
Analysis uses Ollama by default (requires `ollama serve` running). Configure:
|
|
333
278
|
|
|
334
279
|
```bash
|
|
335
|
-
|
|
336
|
-
ph
|
|
337
|
-
|
|
338
|
-
|
|
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
|
-
##
|
|
288
|
+
## 9. MCP Server
|
|
348
289
|
|
|
349
|
-
|
|
290
|
+
ph exposes an MCP (Model Context Protocol) server over stdio for AI agents:
|
|
350
291
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
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
|
-
##
|
|
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
|
-
|
|
316
|
+
Share prompt history across machines:
|
|
366
317
|
|
|
367
318
|
```bash
|
|
368
|
-
#
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
#
|
|
372
|
-
ph
|
|
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
|
-
|
|
329
|
+
Every `ph log` auto-pushes to remote if configured (fire-and-forget, never blocks).
|
|
376
330
|
|
|
377
|
-
|
|
331
|
+
---
|
|
378
332
|
|
|
379
|
-
|
|
380
|
-
[Unit]
|
|
381
|
-
Description=ph remote sync server
|
|
382
|
-
After=network.target
|
|
333
|
+
## 11. Database
|
|
383
334
|
|
|
384
|
-
|
|
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
|
-
|
|
395
|
-
WantedBy=multi-user.target
|
|
396
|
-
```
|
|
337
|
+
**Tables:**
|
|
397
338
|
|
|
398
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
357
|
+
---
|
|
444
358
|
|
|
445
|
-
|
|
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
|
-
|
|
361
|
+
Before saving, ph filters out:
|
|
458
362
|
|
|
459
|
-
|
|
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
|
-
|
|
462
|
-
# systemd
|
|
463
|
-
sudo journalctl -u ph.service -f
|
|
369
|
+
Configure:
|
|
464
370
|
|
|
465
|
-
|
|
466
|
-
|
|
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
|
-
##
|
|
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
|
-
|
|
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
|
-
###
|
|
419
|
+
### File layout
|
|
476
420
|
|
|
477
|
-
|
|
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
|
-
|
|
442
|
+
## 15. Importing Existing History
|
|
487
443
|
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
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
|
-
|
|
448
|
+
# Import from Gemini CLI
|
|
449
|
+
ph import gemini --filter
|
|
496
450
|
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
- **Registry**: `https://registry.npmjs.org/`
|
|
500
|
-
- **Access**: public
|
|
451
|
+
# Import from OpenCode
|
|
452
|
+
ph import opencode
|
|
501
453
|
|
|
502
|
-
|
|
454
|
+
# Import from Codex CLI
|
|
455
|
+
ph import codex --dry-run
|
|
456
|
+
ph import codex
|
|
503
457
|
|
|
504
|
-
|
|
505
|
-
|
|
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
|
-
|
|
464
|
+
---
|
|
465
|
+
|
|
466
|
+
## 16. Versioning and Releases
|
|
509
467
|
|
|
510
|
-
|
|
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
|
-
|
|
513
|
-
|
|
514
|
-
|
|
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
|
|