spooling 0.1.1__tar.gz
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.
- spooling-0.1.1/LICENSE +21 -0
- spooling-0.1.1/PKG-INFO +28 -0
- spooling-0.1.1/README.md +471 -0
- spooling-0.1.1/pyproject.toml +47 -0
- spooling-0.1.1/setup.cfg +4 -0
- spooling-0.1.1/spooling/__init__.py +2 -0
- spooling-0.1.1/spooling/agent.py +213 -0
- spooling-0.1.1/spooling/classifiers.py +147 -0
- spooling-0.1.1/spooling/cli.py +522 -0
- spooling-0.1.1/spooling/cloud.py +768 -0
- spooling-0.1.1/spooling/config.py +44 -0
- spooling-0.1.1/spooling/db.py +21 -0
- spooling-0.1.1/spooling/embeddings.py +60 -0
- spooling-0.1.1/spooling/evals.py +611 -0
- spooling-0.1.1/spooling/experiments.py +407 -0
- spooling-0.1.1/spooling/ingest.py +496 -0
- spooling-0.1.1/spooling/mcp_server.py +312 -0
- spooling-0.1.1/spooling/parser.py +614 -0
- spooling-0.1.1/spooling/pricing.py +307 -0
- spooling-0.1.1/spooling/providers/__init__.py +46 -0
- spooling-0.1.1/spooling/providers/antigravity.py +312 -0
- spooling-0.1.1/spooling/providers/base.py +166 -0
- spooling-0.1.1/spooling/providers/codex.py +230 -0
- spooling-0.1.1/spooling/providers/copilot.py +294 -0
- spooling-0.1.1/spooling/providers/cortex_code.py +234 -0
- spooling-0.1.1/spooling/providers/cursor.py +307 -0
- spooling-0.1.1/spooling/providers/gemini.py +476 -0
- spooling-0.1.1/spooling/providers/github.py +241 -0
- spooling-0.1.1/spooling/providers/gitlab.py +186 -0
- spooling-0.1.1/spooling/providers/kiro.py +240 -0
- spooling-0.1.1/spooling/providers/opencode.py +282 -0
- spooling-0.1.1/spooling/providers/session_file.py +36 -0
- spooling-0.1.1/spooling/providers/windsurf.py +355 -0
- spooling-0.1.1/spooling/redact.py +284 -0
- spooling-0.1.1/spooling/remote_otel.py +257 -0
- spooling-0.1.1/spooling/sdk.py +364 -0
- spooling-0.1.1/spooling/search.py +68 -0
- spooling-0.1.1/spooling/server.py +1291 -0
- spooling-0.1.1/spooling/stats.py +180 -0
- spooling-0.1.1/spooling/subscription_pricing.py +131 -0
- spooling-0.1.1/spooling/tracing.py +451 -0
- spooling-0.1.1/spooling/watcher.py +125 -0
- spooling-0.1.1/spooling.egg-info/PKG-INFO +28 -0
- spooling-0.1.1/spooling.egg-info/SOURCES.txt +49 -0
- spooling-0.1.1/spooling.egg-info/dependency_links.txt +1 -0
- spooling-0.1.1/spooling.egg-info/entry_points.txt +2 -0
- spooling-0.1.1/spooling.egg-info/requires.txt +17 -0
- spooling-0.1.1/spooling.egg-info/top_level.txt +1 -0
- spooling-0.1.1/tests/test_parser.py +273 -0
- spooling-0.1.1/tests/test_pricing.py +157 -0
- spooling-0.1.1/tests/test_redact.py +220 -0
spooling-0.1.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Parsed Analytics, Inc.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
spooling-0.1.1/PKG-INFO
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: spooling
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Local session tracker and semantic search for AI coding assistants
|
|
5
|
+
Author: Parsed Analytics, Inc.
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
10
|
+
Requires-Python: >=3.11
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Requires-Dist: click>=8.1
|
|
13
|
+
Requires-Dist: psycopg[binary]>=3.1
|
|
14
|
+
Requires-Dist: sentence-transformers>=3.0
|
|
15
|
+
Requires-Dist: fastapi>=0.111
|
|
16
|
+
Requires-Dist: uvicorn[standard]>=0.30
|
|
17
|
+
Requires-Dist: jinja2>=3.1
|
|
18
|
+
Requires-Dist: watchdog>=4.0
|
|
19
|
+
Requires-Dist: rich>=13.0
|
|
20
|
+
Requires-Dist: httpx>=0.27
|
|
21
|
+
Requires-Dist: anthropic>=0.40
|
|
22
|
+
Requires-Dist: strands-agents[ollama]>=1.35
|
|
23
|
+
Requires-Dist: strands-agents-evals>=0.1
|
|
24
|
+
Requires-Dist: mcp>=1.27
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
27
|
+
Requires-Dist: pytest-mock>=3.14; extra == "dev"
|
|
28
|
+
Dynamic: license-file
|
spooling-0.1.1/README.md
ADDED
|
@@ -0,0 +1,471 @@
|
|
|
1
|
+
# Spooling
|
|
2
|
+
|
|
3
|
+
Local session tracker and semantic search for AI coding assistants.
|
|
4
|
+
|
|
5
|
+
Track your AI coding sessions across **OpenAI Codex CLI**, **GitHub Copilot**, **Cursor**, **Windsurf**, **Kiro**, **Google Antigravity**, and **opencode**, all in one place. Get usage stats, cost estimates, per-provider breakdowns, semantic search via pgvector, and a built-in AI chat agent to explore your history.
|
|
6
|
+
|
|
7
|
+
**Website:** [spooling.ai](https://spooling.ai)
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Prerequisites
|
|
12
|
+
|
|
13
|
+
- **Python 3.11+**
|
|
14
|
+
- **Node.js 18+**
|
|
15
|
+
- **Docker** (for PostgreSQL + pgvector)
|
|
16
|
+
- **Ollama** (optional, for free local AI chat) or an **Anthropic API key**
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
git clone <repo-url> spooling
|
|
24
|
+
cd spooling
|
|
25
|
+
|
|
26
|
+
# 1. Start the database
|
|
27
|
+
docker-compose up -d # or `docker compose up -d` if using Docker Compose V2
|
|
28
|
+
|
|
29
|
+
#docker-compose up -d
|
|
30
|
+
|
|
31
|
+
# 2. Install Python backend (pulls strands-agents, strands-agents-evals,
|
|
32
|
+
# ollama, mcp, and everything else declared in pyproject.toml).
|
|
33
|
+
python3 -m venv .venv
|
|
34
|
+
source .venv/bin/activate
|
|
35
|
+
pip install -e .
|
|
36
|
+
|
|
37
|
+
# 3. Install Ollama + pull the chat and judge models so the chat agent
|
|
38
|
+
# and Strands eval rubrics work out of the box with no API key.
|
|
39
|
+
brew install ollama
|
|
40
|
+
ollama serve &
|
|
41
|
+
ollama pull gemma3:4b # chat agent default
|
|
42
|
+
ollama pull qwen2.5:7b # tool-capable Strands eval judge
|
|
43
|
+
|
|
44
|
+
# 4. Check which providers are detected
|
|
45
|
+
spooling init
|
|
46
|
+
|
|
47
|
+
# 5. Sync sessions from all detected providers
|
|
48
|
+
spooling sync # with embeddings (slower, enables semantic search)
|
|
49
|
+
spooling sync --no-embed # without embeddings (faster, for initial setup)
|
|
50
|
+
|
|
51
|
+
# 6. Install UI dependencies
|
|
52
|
+
cd ui && npm install && cd ..
|
|
53
|
+
|
|
54
|
+
# 7. Start everything
|
|
55
|
+
spooling ui # API on :3002, MCP on :3004, GUI on :3003
|
|
56
|
+
|
|
57
|
+
# 8. (Optional) Connect an MCP-compatible agent to Spooling. The MCP server
|
|
58
|
+
# runs automatically with `spooling ui` over streamable-HTTP at
|
|
59
|
+
# http://127.0.0.1:3004/mcp, so any agent (Codex, Cursor,
|
|
60
|
+
# web agents) can connect by URL.
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Open **http://localhost:3003** and you're in.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Connect Spooling to your AI coding agent
|
|
68
|
+
|
|
69
|
+
`spooling ui` automatically exposes an MCP server at `http://127.0.0.1:3004/mcp` (HTTP streamable transport). Any MCP-speaking agent can connect to it and pull context from your local KB mid-conversation. The agent gets tools like `spooling_search`, `spooling_recent_sessions`, `spooling_get_session`, `spooling_workspace_stats`, and `spooling_top_projects`.
|
|
70
|
+
|
|
71
|
+
### Cursor / Windsurf / Codex / Antigravity
|
|
72
|
+
|
|
73
|
+
Edit your client's MCP config (usually `~/.cursor/mcp.json`, `~/.codeium/windsurf/mcp_config.json`, or the equivalent) and add:
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
{
|
|
77
|
+
"mcpServers": {
|
|
78
|
+
"spooling": {
|
|
79
|
+
"type": "http",
|
|
80
|
+
"url": "http://127.0.0.1:3004/mcp"
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Restart the client. The `spooling` server and its tools should appear in the MCP panel.
|
|
87
|
+
|
|
88
|
+
### Generic JSON-RPC smoke test
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
curl -s http://127.0.0.1:3004/mcp \
|
|
92
|
+
-H "Content-Type: application/json" \
|
|
93
|
+
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | jq
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Should return the five `spool_*` tools. If you get "connection refused", `spooling ui` is not running (or its ports got squatted, run `lsof -ti :3004 | xargs kill -9` and retry).
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## CLI Usage
|
|
101
|
+
|
|
102
|
+
All CLI commands require the venv to be active and the database running.
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
source .venv/bin/activate
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### `spooling init`
|
|
109
|
+
|
|
110
|
+
Check database connection and show which AI coding tool providers are detected on your system. This scans default paths for Codex CLI, GitHub Copilot, Cursor, and Windsurf session data.
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
spooling init
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### `spooling sync`
|
|
117
|
+
|
|
118
|
+
Parse and ingest sessions from all connected providers into the database. Chunks and embeds message content into pgvector for semantic search.
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
spooling sync # Full sync with embeddings
|
|
122
|
+
spooling sync --no-embed # Skip embeddings (faster initial sync)
|
|
123
|
+
spooling sync -p cursor # Sync only Cursor sessions
|
|
124
|
+
spooling sync -p codex # Sync only Codex CLI sessions
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### `spooling stats`
|
|
128
|
+
|
|
129
|
+
Show usage statistics - sessions, messages, tool calls, tokens, costs, broken down by project and day.
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
spooling stats # Overview + last 7 days
|
|
133
|
+
spooling stats --week # Weekly breakdown
|
|
134
|
+
spooling stats --days 30 # Last 30 days
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### `spooling search <query>`
|
|
138
|
+
|
|
139
|
+
Semantic search across all your session history using natural language.
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
spooling search "snowflake connector"
|
|
143
|
+
spooling search "authentication bug" -n 5
|
|
144
|
+
spooling search "database migration" -p ~/myproject
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Options:
|
|
148
|
+
- `-n, --limit` - Number of results (default: 10)
|
|
149
|
+
- `-p, --project` - Filter by project name
|
|
150
|
+
|
|
151
|
+
### `spooling watch`
|
|
152
|
+
|
|
153
|
+
Watch all connected provider directories for new session data and auto-sync in real time.
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
spooling watch
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### `spooling serve`
|
|
160
|
+
|
|
161
|
+
Start the API server only (for when you want to run the GUI separately).
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
spooling serve # Default: http://127.0.0.1:3002
|
|
165
|
+
spooling serve --port 8080 # Custom port
|
|
166
|
+
spooling serve --host 0.0.0.0 # Bind to all interfaces
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### `spooling ui`
|
|
170
|
+
|
|
171
|
+
Start the API server, the MCP HTTP server, and the Next.js UI together.
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
spooling ui
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### `spooling mcp`
|
|
178
|
+
|
|
179
|
+
Start the Spooling MCP server on its own. Defaults to streamable-HTTP at
|
|
180
|
+
`http://127.0.0.1:3004/mcp`, which any MCP-compatible agent can connect to
|
|
181
|
+
by URL. `spooling ui` already launches this alongside the API, so you only
|
|
182
|
+
need to run it directly when you want the MCP server without the GUI.
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
spooling mcp # streamable-HTTP at http://127.0.0.1:3004/mcp (default)
|
|
186
|
+
spooling mcp --stdio # stdio transport, for stdio-only clients
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## Spooling Cloud (optional)
|
|
192
|
+
|
|
193
|
+
By default Spooling stays 100% local. If you also want your sessions in the
|
|
194
|
+
hosted workspace at [spooling.ai](https://spooling.ai) (so teammates can
|
|
195
|
+
search the same pool, or you can chat with sessions from any browser),
|
|
196
|
+
the CLI ships with a `spooling cloud` subcommand.
|
|
197
|
+
|
|
198
|
+
### One-time setup
|
|
199
|
+
|
|
200
|
+
1. Mint an API key in the GUI at `app.spooling.ai/settings/api-keys`
|
|
201
|
+
(looks like `sk_live_...`).
|
|
202
|
+
2. Save it locally:
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
spooling cloud login --key sk_live_...
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
The key is stored at `~/.config/spooling/cloud.json` with `0600` perms.
|
|
209
|
+
You can override the API base with `--api-url` or the
|
|
210
|
+
`SPOOLING_CLOUD_URL` env var (default: `https://api.spooling.ai`).
|
|
211
|
+
|
|
212
|
+
### Push once
|
|
213
|
+
|
|
214
|
+
Send the most recent local sessions up to the cloud:
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
spooling push # 100 sessions, batches of 20
|
|
218
|
+
spooling push --limit 500 # bigger backfill
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
The server upserts by session id, so re-running is safe.
|
|
222
|
+
|
|
223
|
+
### Watch (continuous push)
|
|
224
|
+
|
|
225
|
+
Stream new and updated sessions to the cloud on a timer. Stop with
|
|
226
|
+
Ctrl+C.
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
spooling cloud watch # every 60s, 1000 sessions/cycle
|
|
230
|
+
spooling cloud watch --interval 30 # tighter cadence
|
|
231
|
+
spooling cloud watch --lookback 60 # widen the overlap window if you edit old sessions
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
What it does each cycle:
|
|
235
|
+
|
|
236
|
+
1. Reads `last_push_at` from `~/.config/spooling/cloud.json`.
|
|
237
|
+
2. Queries local sessions where `started_at >= last_push_at - lookback`
|
|
238
|
+
(default lookback: 10 minutes, so messages appended to an in-progress
|
|
239
|
+
session get re-uploaded).
|
|
240
|
+
3. POSTs to `/v1/sessions/batch` in chunks of `--batch` (default 20).
|
|
241
|
+
4. Advances `last_push_at` to the cycle start on success.
|
|
242
|
+
|
|
243
|
+
Cycles with no new work are silent. If a push fails the watermark is
|
|
244
|
+
not advanced, so the next cycle retries the same window.
|
|
245
|
+
|
|
246
|
+
### Status / logout
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
spooling cloud status # show what is in the cloud + stored API base
|
|
250
|
+
spooling cloud logout # remove the stored API key
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### Auto-start at login (macOS)
|
|
254
|
+
|
|
255
|
+
Run `spooling cloud watch` as a launchd agent so it survives reboots:
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
cat > ~/Library/LaunchAgents/ai.spooling.cloud-watch.plist <<'PLIST'
|
|
259
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
260
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
261
|
+
<plist version="1.0">
|
|
262
|
+
<dict>
|
|
263
|
+
<key>Label</key><string>ai.spooling.cloud-watch</string>
|
|
264
|
+
<key>ProgramArguments</key>
|
|
265
|
+
<array>
|
|
266
|
+
<string>/usr/local/bin/spooling</string>
|
|
267
|
+
<string>cloud</string>
|
|
268
|
+
<string>watch</string>
|
|
269
|
+
</array>
|
|
270
|
+
<key>RunAtLoad</key><true/>
|
|
271
|
+
<key>KeepAlive</key><true/>
|
|
272
|
+
<key>StandardOutPath</key><string>/tmp/spooling-cloud-watch.log</string>
|
|
273
|
+
<key>StandardErrorPath</key><string>/tmp/spooling-cloud-watch.log</string>
|
|
274
|
+
</dict>
|
|
275
|
+
</plist>
|
|
276
|
+
PLIST
|
|
277
|
+
launchctl load ~/Library/LaunchAgents/ai.spooling.cloud-watch.plist
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
(Adjust the `spooling` path with `which spooling` if it lives elsewhere.)
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
## MCP Endpoint
|
|
285
|
+
|
|
286
|
+
Spooling exposes an MCP server so any AI agent can query your session history
|
|
287
|
+
as a context source. The server runs over **streamable-HTTP** at
|
|
288
|
+
`http://127.0.0.1:3004/mcp` and is started automatically alongside `spooling
|
|
289
|
+
ui`.
|
|
290
|
+
|
|
291
|
+
Drop this into your MCP client config (`~/.mcp.json`, Cursor,
|
|
292
|
+
Codex, or any other streamable-HTTP capable agent):
|
|
293
|
+
|
|
294
|
+
```json
|
|
295
|
+
{
|
|
296
|
+
"mcpServers": {
|
|
297
|
+
"spooling": {
|
|
298
|
+
"url": "http://127.0.0.1:3004/mcp"
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
Or register it with an MCP client's config file.
|
|
305
|
+
|
|
306
|
+
The **Settings** page in the GUI shows the endpoint URL, a copy button, and
|
|
307
|
+
the full config snippet so you don't have to remember it.
|
|
308
|
+
|
|
309
|
+
### Tools exposed
|
|
310
|
+
|
|
311
|
+
| Tool | Purpose |
|
|
312
|
+
|------|---------|
|
|
313
|
+
| `list_traces` | Recent Spooling traces, filterable by provider/project |
|
|
314
|
+
| `get_trace` | Full detail for one trace: header, spans, eval scores |
|
|
315
|
+
| `search_sessions` | Semantic search over embedded session chunks |
|
|
316
|
+
| `get_stats` | Top-line stats: traces, tokens, cost, errors |
|
|
317
|
+
| `get_top_vendors` | Most-used external vendors by tool-call count |
|
|
318
|
+
| `list_evals` | Recent eval runs, optionally filtered by rubric |
|
|
319
|
+
| `list_rubrics` | All configured Strands eval rubrics |
|
|
320
|
+
| `run_eval` | Run a rubric against a trace and persist the result |
|
|
321
|
+
|
|
322
|
+
### Stdio (legacy clients)
|
|
323
|
+
|
|
324
|
+
For MCP clients that only speak stdio, run `spooling mcp --stdio` and register
|
|
325
|
+
it with the command-based form:
|
|
326
|
+
|
|
327
|
+
```bash
|
|
328
|
+
# MCP config for stdio transport
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
---
|
|
332
|
+
|
|
333
|
+
## GUI
|
|
334
|
+
|
|
335
|
+
The Spooling GUI runs on **http://localhost:3003** and includes:
|
|
336
|
+
|
|
337
|
+
| Page | Description |
|
|
338
|
+
|------|-------------|
|
|
339
|
+
| **Dashboard** | Overview stats, per-provider breakdown, daily activity chart, projects, top tools, recent sessions |
|
|
340
|
+
| **Sessions** | Browse all sessions with provider labels, filtering, click into any session for full conversation view |
|
|
341
|
+
| **Search** | Semantic search across all session history with similarity scores |
|
|
342
|
+
| **Analytics** | Charts for daily usage, cost trends, token usage, tool distribution, filterable by provider (AG Charts) |
|
|
343
|
+
| **Chat** | AI assistant that can answer questions about your session data (RAG-powered) |
|
|
344
|
+
| **Connections** | Connect/disconnect AI coding tools (Codex, Copilot, Cursor, Windsurf) |
|
|
345
|
+
| **Settings** | Configure the AI chat provider (Ollama or Anthropic) |
|
|
346
|
+
|
|
347
|
+
### Running the GUI
|
|
348
|
+
|
|
349
|
+
```bash
|
|
350
|
+
# Terminal 1: API server
|
|
351
|
+
source .venv/bin/activate
|
|
352
|
+
spooling serve
|
|
353
|
+
|
|
354
|
+
# Terminal 2: Next.js dev server
|
|
355
|
+
cd ui
|
|
356
|
+
npm run dev
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
Or use `spooling ui` to start both at once.
|
|
360
|
+
|
|
361
|
+
---
|
|
362
|
+
|
|
363
|
+
## Chat Agent Setup
|
|
364
|
+
|
|
365
|
+
The chat page lets you ask questions about your coding sessions in natural language. It uses RAG - retrieves relevant context from pgvector before answering.
|
|
366
|
+
|
|
367
|
+
### Option A: Ollama (free, local)
|
|
368
|
+
|
|
369
|
+
```bash
|
|
370
|
+
# Install Ollama
|
|
371
|
+
brew install ollama
|
|
372
|
+
|
|
373
|
+
# Start the server
|
|
374
|
+
ollama serve
|
|
375
|
+
|
|
376
|
+
# Pull a model
|
|
377
|
+
ollama pull gemma3:4b
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
Go to **Settings** in the GUI and select Ollama. The model will auto-detect.
|
|
381
|
+
|
|
382
|
+
### Option B: Anthropic API (bring your own key)
|
|
383
|
+
|
|
384
|
+
Go to **Settings** in the GUI, select Anthropic, and paste your API key from [console.anthropic.com](https://console.anthropic.com).
|
|
385
|
+
|
|
386
|
+
Available models: Sonnet, Haiku, Opus.
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
## Architecture
|
|
391
|
+
|
|
392
|
+
```
|
|
393
|
+
spooling/
|
|
394
|
+
├── docker-compose.yml # PostgreSQL + pgvector
|
|
395
|
+
├── init.sql # Database schema
|
|
396
|
+
├── pyproject.toml # Python package config
|
|
397
|
+
├── spooling/ # Python backend
|
|
398
|
+
│ ├── cli.py # Click CLI
|
|
399
|
+
│ ├── config.py # Configuration
|
|
400
|
+
│ ├── db.py # Database connection
|
|
401
|
+
│ ├── providers/ # Provider plugins (codex, copilot, cursor, windsurf)
|
|
402
|
+
│ ├── parser.py # Session JSONL parser
|
|
403
|
+
│ ├── embeddings.py # sentence-transformers (all-MiniLM-L6-v2)
|
|
404
|
+
│ ├── ingest.py # Sync pipeline
|
|
405
|
+
│ ├── search.py # pgvector semantic search
|
|
406
|
+
│ ├── stats.py # Usage statistics
|
|
407
|
+
│ ├── watcher.py # File watcher (watchdog)
|
|
408
|
+
│ ├── agent.py # Chat agent (Ollama + Anthropic)
|
|
409
|
+
│ └── server.py # FastAPI API server
|
|
410
|
+
└── ui/ # Next.js frontend
|
|
411
|
+
├── next.config.js # API proxy to :3002
|
|
412
|
+
└── src/
|
|
413
|
+
├── components/ # shadcn/ui components
|
|
414
|
+
├── lib/ # API helpers
|
|
415
|
+
└── app/(app)/ # Pages (dashboard, sessions, search, etc.)
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
### Stack
|
|
419
|
+
|
|
420
|
+
| Layer | Technology |
|
|
421
|
+
|-------|-----------|
|
|
422
|
+
| Database | PostgreSQL 16 + pgvector (Docker) |
|
|
423
|
+
| Embeddings | sentence-transformers / all-MiniLM-L6-v2 (local) |
|
|
424
|
+
| Backend | Python, FastAPI, Click |
|
|
425
|
+
| Frontend | Next.js 14, shadcn/ui, Tailwind CSS, AG Charts |
|
|
426
|
+
| Chat AI | Ollama (local) or Anthropic API |
|
|
427
|
+
|
|
428
|
+
### Ports
|
|
429
|
+
|
|
430
|
+
| Service | Port |
|
|
431
|
+
|---------|------|
|
|
432
|
+
| PostgreSQL | 5434 |
|
|
433
|
+
| API Server | 3002 |
|
|
434
|
+
| GUI | 3003 |
|
|
435
|
+
| MCP Server (streamable-HTTP) | 3004 |
|
|
436
|
+
|
|
437
|
+
---
|
|
438
|
+
|
|
439
|
+
## Environment Variables
|
|
440
|
+
|
|
441
|
+
All optional - defaults work out of the box for local development.
|
|
442
|
+
|
|
443
|
+
| Variable | Default | Description |
|
|
444
|
+
|----------|---------|-------------|
|
|
445
|
+
| `SPOOLING_DB_HOST` | `localhost` | Database host |
|
|
446
|
+
| `SPOOLING_DB_PORT` | `5434` | Database port |
|
|
447
|
+
| `SPOOLING_DB_NAME` | `spooling` | Database name |
|
|
448
|
+
| `SPOOLING_DB_USER` | `spooling` | Database user |
|
|
449
|
+
| `SPOOLING_DB_PASSWORD` | `spooling` | Database password |
|
|
450
|
+
| `SPOOLING_EMBEDDING_MODEL` | `all-MiniLM-L6-v2` | Sentence transformer model |
|
|
451
|
+
| `SPOOLING_UI_HOST` | `127.0.0.1` | API server host |
|
|
452
|
+
| `ANTHROPIC_API_KEY` | - | Anthropic API key (alternative to setting in UI) |
|
|
453
|
+
|
|
454
|
+
---
|
|
455
|
+
|
|
456
|
+
## Supported Providers
|
|
457
|
+
|
|
458
|
+
| Provider | Data Location | Format |
|
|
459
|
+
|----------|--------------|--------|
|
|
460
|
+
| **JSONL Sessions** | `~/.sessions/projects/` | UUID-named JSONL files with conversation history, tool calls, git context |
|
|
461
|
+
| **OpenAI Codex CLI** | `~/.codex/sessions/` | `rollout-*.jsonl` files organized by date |
|
|
462
|
+
| **GitHub Copilot** | `~/Library/Application Support/Code/User/workspaceStorage/` | Chat session JSON from VS Code |
|
|
463
|
+
| **Cursor** | `~/Library/Application Support/Cursor/User/workspaceStorage/` | Chat and composer sessions from SQLite |
|
|
464
|
+
| **Windsurf** | `~/Library/Application Support/Windsurf/User/workspaceStorage/` | Chat and Cascade sessions from SQLite |
|
|
465
|
+
| **Kiro** | `~/Library/Application Support/Kiro/User/workspaceStorage/` | AWS Kiro chat and agent sessions from SQLite |
|
|
466
|
+
| **Google Antigravity** | `~/Library/Application Support/Antigravity/User/workspaceStorage/` | Antigravity chat and agent sessions from SQLite |
|
|
467
|
+
| **opencode** | `~/.local/share/opencode/opencode.db` | sst/opencode SQLite database with session/message/part tables (Vercel AI SDK part shape) |
|
|
468
|
+
|
|
469
|
+
Run `spooling init` to see which providers are detected on your system.
|
|
470
|
+
|
|
471
|
+
No data is sent to external servers. Everything runs locally.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "spooling"
|
|
3
|
+
version = "0.1.1"
|
|
4
|
+
description = "Local session tracker and semantic search for AI coding assistants"
|
|
5
|
+
license = "MIT"
|
|
6
|
+
license-files = ["LICENSE"]
|
|
7
|
+
authors = [{ name = "Parsed Analytics, Inc." }]
|
|
8
|
+
classifiers = [
|
|
9
|
+
"Programming Language :: Python :: 3",
|
|
10
|
+
"Programming Language :: Python :: 3.11",
|
|
11
|
+
"Programming Language :: Python :: 3.12",
|
|
12
|
+
]
|
|
13
|
+
requires-python = ">=3.11"
|
|
14
|
+
dependencies = [
|
|
15
|
+
"click>=8.1",
|
|
16
|
+
"psycopg[binary]>=3.1",
|
|
17
|
+
"sentence-transformers>=3.0",
|
|
18
|
+
"fastapi>=0.111",
|
|
19
|
+
"uvicorn[standard]>=0.30",
|
|
20
|
+
"jinja2>=3.1",
|
|
21
|
+
"watchdog>=4.0",
|
|
22
|
+
"rich>=13.0",
|
|
23
|
+
"httpx>=0.27",
|
|
24
|
+
"anthropic>=0.40",
|
|
25
|
+
"strands-agents[ollama]>=1.35",
|
|
26
|
+
"strands-agents-evals>=0.1",
|
|
27
|
+
"mcp>=1.27",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
[project.scripts]
|
|
31
|
+
spooling = "spooling.cli:cli"
|
|
32
|
+
|
|
33
|
+
[tool.setuptools.packages.find]
|
|
34
|
+
include = ["spooling*"]
|
|
35
|
+
|
|
36
|
+
[project.optional-dependencies]
|
|
37
|
+
dev = [
|
|
38
|
+
"pytest>=8.0",
|
|
39
|
+
"pytest-mock>=3.14",
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
[tool.pytest.ini_options]
|
|
43
|
+
testpaths = ["tests"]
|
|
44
|
+
|
|
45
|
+
[build-system]
|
|
46
|
+
requires = ["setuptools>=68"]
|
|
47
|
+
build-backend = "setuptools.build_meta"
|
spooling-0.1.1/setup.cfg
ADDED