ctxttools 0.3.0__tar.gz → 0.4.0__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.
Files changed (42) hide show
  1. ctxttools-0.4.0/PKG-INFO +434 -0
  2. ctxttools-0.4.0/README.md +416 -0
  3. ctxttools-0.4.0/ctools/__main__.py +4 -0
  4. {ctxttools-0.3.0 → ctxttools-0.4.0}/ctools/agents.py +364 -35
  5. {ctxttools-0.3.0 → ctxttools-0.4.0}/ctools/backup.py +10 -7
  6. {ctxttools-0.3.0 → ctxttools-0.4.0}/ctools/ccat.py +2 -0
  7. {ctxttools-0.3.0 → ctxttools-0.4.0}/ctools/ccopy.py +56 -14
  8. {ctxttools-0.3.0 → ctxttools-0.4.0}/ctools/cdir.py +444 -78
  9. {ctxttools-0.3.0 → ctxttools-0.4.0}/ctools/cdu.py +45 -8
  10. {ctxttools-0.3.0 → ctxttools-0.4.0}/ctools/cextract.py +74 -5
  11. {ctxttools-0.3.0 → ctxttools-0.4.0}/ctools/cgrep.py +126 -4
  12. ctxttools-0.4.0/ctools/config.py +127 -0
  13. {ctxttools-0.3.0 → ctxttools-0.4.0}/ctools/crecover.py +3 -3
  14. {ctxttools-0.3.0 → ctxttools-0.4.0}/ctools/crm.py +134 -4
  15. ctxttools-0.4.0/ctools/ctools-web.py +30 -0
  16. {ctxttools-0.3.0 → ctxttools-0.4.0}/ctools/ctools_mcp.py +162 -0
  17. ctxttools-0.4.0/ctools/dispatch.py +95 -0
  18. {ctxttools-0.3.0 → ctxttools-0.4.0}/ctools/filterlib.py +33 -1
  19. {ctxttools-0.3.0 → ctxttools-0.4.0}/ctools/lib.py +47 -0
  20. ctxttools-0.4.0/ctools/paths.py +51 -0
  21. ctxttools-0.4.0/ctools/remote_search.py +97 -0
  22. {ctxttools-0.3.0 → ctxttools-0.4.0}/ctools/strategy.py +22 -3
  23. ctxttools-0.4.0/ctools/webui.py +3633 -0
  24. ctxttools-0.4.0/ctxttools.egg-info/PKG-INFO +434 -0
  25. {ctxttools-0.3.0 → ctxttools-0.4.0}/ctxttools.egg-info/SOURCES.txt +6 -0
  26. {ctxttools-0.3.0 → ctxttools-0.4.0}/ctxttools.egg-info/entry_points.txt +1 -0
  27. ctxttools-0.4.0/ctxttools.egg-info/requires.txt +13 -0
  28. {ctxttools-0.3.0 → ctxttools-0.4.0}/pyproject.toml +5 -2
  29. ctxttools-0.3.0/PKG-INFO +0 -257
  30. ctxttools-0.3.0/README.md +0 -241
  31. ctxttools-0.3.0/ctools/webui.py +0 -1811
  32. ctxttools-0.3.0/ctxttools.egg-info/PKG-INFO +0 -257
  33. ctxttools-0.3.0/ctxttools.egg-info/requires.txt +0 -9
  34. {ctxttools-0.3.0 → ctxttools-0.4.0}/LICENSE.MIT +0 -0
  35. {ctxttools-0.3.0 → ctxttools-0.4.0}/ctools/__init__.py +0 -0
  36. {ctxttools-0.3.0 → ctxttools-0.4.0}/ctools/cconnect.py +0 -0
  37. {ctxttools-0.3.0 → ctxttools-0.4.0}/ctools/cli.py +0 -0
  38. {ctxttools-0.3.0 → ctxttools-0.4.0}/ctools/log.py +0 -0
  39. {ctxttools-0.3.0 → ctxttools-0.4.0}/ctools/testing.py +0 -0
  40. {ctxttools-0.3.0 → ctxttools-0.4.0}/ctxttools.egg-info/dependency_links.txt +0 -0
  41. {ctxttools-0.3.0 → ctxttools-0.4.0}/ctxttools.egg-info/top_level.txt +0 -0
  42. {ctxttools-0.3.0 → ctxttools-0.4.0}/setup.cfg +0 -0
@@ -0,0 +1,434 @@
1
+ Metadata-Version: 2.4
2
+ Name: ctxttools
3
+ Version: 0.4.0
4
+ Summary: CLI tools for LLM conversations
5
+ Requires-Python: >=3.10
6
+ Description-Content-Type: text/markdown
7
+ License-File: LICENSE.MIT
8
+ Requires-Dist: rich>=13.0.0
9
+ Requires-Dist: tiktoken>=0.5.0
10
+ Requires-Dist: structlog>=24.0
11
+ Requires-Dist: platformdirs>=3.0.0
12
+ Requires-Dist: tomli>=2.0.0; python_version < "3.11"
13
+ Provides-Extra: mcp
14
+ Requires-Dist: mcp<2.0,>=1.2.0; extra == "mcp"
15
+ Provides-Extra: dev
16
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
17
+ Dynamic: license-file
18
+
19
+ # ctools
20
+
21
+ <p align="center">
22
+ <img width="500" alt="ctools" src="https://github.com/user-attachments/assets/ee781bbe-6364-44ed-be2d-72114f1e6d8a" /><br/>
23
+ <a href=https://pypi.org/project/ctxttools><img src=https://badge.fury.io/py/ctxttools.svg/></a>
24
+ <br/><br/><b>Try it now</b><br/>
25
+ <code>uvx --from ctxttools cdir</code><br/>
26
+ <code>uvx --from ctxttools ctools-web</code>
27
+ <br/><br/><b>Then install it</b><br/>
28
+ <code>uv tool install ctxttools</code>
29
+ </p>
30
+
31
+ ------
32
+ **ctools** is a suite of simple tools for navigating through the sessions of the most popular LLM agents and coding tools. It allows you to search your history, transfer conversations, filter them, and even share them among machines and users.
33
+
34
+ It supports [Claude Desktop](https://claude.com/download), [Claude Code](https://github.com/anthropics/claude-code), [Codex](https://github.com/openai/codex), [Pi](https://github.com/earendil-works/pi), [Hermes](https://github.com/NousResearch/hermes-agent), [Goose](https://github.com/aaif-goose/goose), [Kilo](https://github.com/Kilo-Org/kilocode), [FreeBuff](https://github.com/CodebuffAI/freebuff), [Cline](https://github.com/cline/cline), [omp](https://github.com/can1357/oh-my-pi), and [OpenClaw](https://openclaw.ai/).
35
+
36
+ You can use it from the terminal, from a small web dashboard, or from any AI coding agent (via an MCP server).
37
+
38
+ Here's an example:
39
+
40
+ > I look for mentions of snake game in opencode using cgrep
41
+ <pre>
42
+ $ <b>cgrep</b> "snake game" opencode
43
+ opencode/ses_a1d1a5a4df984ee698cab4a7:1:user: make a simple snake game in python
44
+ opencode/ses_a1d1a5a4df984ee698cab4a7:2:assistant: I'll make a terminal-based snake game using `curses` (standard library, no dependencies).
45
+ opencode/ses_a1d1a5a4df984ee698cab4a7:3:assistant: Done — `snake.py` is a terminal snake game using Python's built-in `curses` module (no dependencies).
46
+ </pre>
47
+
48
+ > cool let's look at the status of that session using cdir
49
+ <pre>
50
+ $ <b>cdir</b> -l opencode/ses_a1d1a5a4df984ee698cab4a7
51
+ ID NAME MODIFIED SIZE MSGS PATH
52
+ ses_a1d1a5a4df984ee698cab4a7 make a simple snake game in python 2026-10-07 16:56 2.7 KB 3 /home/chris/.local/share/opencode
53
+
54
+ 1 session(s)
55
+ </pre>
56
+
57
+ > Alright let's copy that session from opencode into pi!
58
+ <pre>
59
+ $ <b>ccopy</b> opencode/ses_a1d1a5a4df984ee698cab4a7 pi
60
+ Copied 3 message(s) from opencode/ses_a1d1a5a4df984ee698cab4a7 to a new pi session: e357f435-f813-463a-b313-f97f1051f3cb
61
+ Resume it with:
62
+ pi --session e357f435-f813-463a-b313-f97f1051f3cb
63
+ </pre>
64
+
65
+ As you can see, these are unix-friendly tools using simple paradigms that you are already familiar with.
66
+
67
+ ## What it can do
68
+
69
+ | Capability | What you get |
70
+ |---|---|
71
+ | **Discover** | See every agent installed on your machine and how many sessions each holds. |
72
+ | **Find** | Search every session at once with grep-style regex, narrowed by agent, session glob, or role. |
73
+ | **Read** | Print a conversation as JSON (pipe it anywhere) or as a readable transcript. |
74
+ | **Continue** | Get the exact command to resume a session in its own tool, or open it in the web UI. |
75
+ | **Copy** | Copy a conversation into a new session in another tool, or the same tool on another machine. |
76
+ | **Measure** | See token usage per agent, per session, and per role. |
77
+ | **Concepts** | Pull out the *intent* of a session: its goal, its constraints, and what was decided. |
78
+ | **Recover** | List and restore the storage backups ctools takes before every local write. |
79
+
80
+ ---
81
+
82
+ ## A quick tour
83
+
84
+ **The overview**: every tool ctools can see, with session counts and token
85
+ totals, plus quick links into the most common actions:
86
+
87
+ ![Overview](docs/screens/overview.png)
88
+
89
+ **Sessions**: browse every conversation from any tool, sorted by recency.
90
+ Click one to open it.
91
+
92
+ ![Sessions](docs/screens/sessions.png)
93
+
94
+ **A conversation**: the full message stream, with the original tool's
95
+ resume command and copy-to-another-tool options.
96
+
97
+ ![Conversation](docs/screens/conversation.png)
98
+
99
+ **Search**: type a phrase and see every matching message across all tools.
100
+
101
+ ![Search](docs/screens/search.png)
102
+
103
+ **Concepts**: ask a session what it's *about*. ctools extracts the intent,
104
+ constraints, and decisions so you can pick up where you left off without
105
+ re-reading everything.
106
+
107
+ ![Concepts](docs/screens/concepts.png)
108
+
109
+ ---
110
+
111
+ ## Install
112
+
113
+ **Python 3.10+** is required.
114
+
115
+ ```bash
116
+ uv tool install ctxttools # or: pip install ctxttools
117
+ ```
118
+
119
+ That gives you the `ctools` command, a short command for each of its verbs,
120
+ and the dashboard and MCP server:
121
+
122
+ | Command | Purpose |
123
+ |---|---|
124
+ | `ctools` | The front door: `ctools <verb> [args...]`. Run `ctools --help` for the list. |
125
+ | `cdir`, `cgrep`, `ccat`, `cdu`, `ccopy`, `cextract`, `cconnect`, `crm`, `crecover` | Shortcuts for the verbs (`cgrep` is `ctools grep`). |
126
+ | `ctools-web` | The dashboard, same as `ctools web`. |
127
+ | `ctools-mcp` | The MCP server, same as `ctools mcp`. Needs the `mcp` extra. |
128
+
129
+ The MCP server's dependency is optional:
130
+
131
+ ```bash
132
+ uv tool install "ctxttools[mcp]" # or: pip install "ctxttools[mcp]"
133
+ ```
134
+
135
+ From a local checkout, `uv` keeps it editable:
136
+
137
+ ```bash
138
+ uv tool install --editable ".[mcp]"
139
+ ```
140
+
141
+ > **Heads up:** `ctools-mcp` needs `mcp<2` (see
142
+ > [mcp dependency](#mcp-dependency) below).
143
+
144
+ ---
145
+
146
+ ## The CLI
147
+
148
+ `ctools` has one verb per job. Each verb is also installed as its own short
149
+ command, named `c` plus the verb, so `ctools grep` and `cgrep` are the same
150
+ program with the same flags. Use whichever you prefer: the long form is easier
151
+ to discover, and the short form is quicker to type.
152
+
153
+ ```text
154
+ $ ctools --help
155
+ usage: ctools <command> [args...]
156
+
157
+ query:
158
+ dir list agents and sessions (cdir)
159
+ grep search session content (cgrep)
160
+ cat print a session (ccat)
161
+ du context usage per session (cdu)
162
+
163
+ transform:
164
+ copy copy a session to another agent (ccopy)
165
+ extract extract concepts from a session (cextract)
166
+ connect pipe concepts between sessions (cconnect)
167
+ rm cut sections out of a session (crm)
168
+ recover restore from a backup (crecover)
169
+
170
+ long-running:
171
+ web run the web dashboard (ctools-web)
172
+ mcp run the MCP server (ctools-mcp)
173
+
174
+ Run 'ctools <command> --help' for a command's options.
175
+ ```
176
+
177
+ Each verb has its own page in [`docs/`](docs/): [dir](docs/cdir.md),
178
+ [grep](docs/cgrep.md), [cat](docs/ccat.md), [du](docs/cdu.md),
179
+ [copy](docs/ccopy.md), [extract](docs/cextract.md),
180
+ [connect](docs/cconnect.md), [rm](docs/crm.md), and
181
+ [recover](docs/crecover.md). Sessions are addressed as `agent/session_id`
182
+ throughout.
183
+
184
+ ### Discover your agents and sessions
185
+
186
+ ```bash
187
+ ctools dir # every known agent, and whether it's installed
188
+ ctools dir opencode # that agent's sessions, and the command that resumes one
189
+ ctools dir -l opencode # with modified time, size, message count, path
190
+ ctools dir . # sessions that ran in this directory, across all agents
191
+ ctools dir opencode/ses_abc # one session's row
192
+ ```
193
+
194
+ ### Find a session
195
+
196
+ `grep` works the way `grep` does, over conversation content instead of files.
197
+
198
+ ```bash
199
+ ctools grep "bug report" # every installed agent
200
+ ctools grep -i "deploy" claude-code # one agent
201
+ ctools grep -C 2 "flaky test" opencode # with context
202
+ ctools grep -l "parser" pi # just the session ids
203
+ ctools grep --user "refactor" # only what you typed
204
+ ctools grep --hosts "mcp config" # also the hosts in ctools.toml
205
+ ```
206
+
207
+ ### Read a session
208
+
209
+ ```bash
210
+ ctools cat opencode/ses_abc # JSON list of {role, content}
211
+ ctools cat --text opencode/ses_abc # a readable transcript
212
+ ctools cat ssh://me@box/pi/<id> # a session on another machine
213
+ ```
214
+
215
+ ### Copy a session to another tool
216
+
217
+ `copy` creates a **new** session in the destination. The source is never
218
+ touched, and ctools prints the command that resumes the copy.
219
+
220
+ ```bash
221
+ ctools copy opencode/ses_abc claude-code # into another tool
222
+ ctools copy opencode/ses_abc codex --dry-run # preview first
223
+ ctools copy opencode/ses_abc ssh://me@box/codex # into a tool on another machine
224
+ ctools copy opencode/ses_abc ssh://me@box/ # into opencode on that machine
225
+ ctools copy ssh://me@box/pi/<id> claude-code # pull one in from another machine
226
+ ```
227
+
228
+ The remote side doesn't need ctools installed; plain `ssh` and `tar` will do.
229
+ See [docs/ccopy.md](docs/ccopy.md) for how that works and where the new
230
+ session lands.
231
+
232
+ ### Token usage
233
+
234
+ ```bash
235
+ ctools du # total across all agents
236
+ ctools du opencode # sessions by token count
237
+ ctools du opencode/ses_abc # breakdown by role
238
+ ```
239
+
240
+ ---
241
+
242
+ ## The web dashboard
243
+
244
+ ```bash
245
+ ctools web # opens at http://127.0.0.1:8765
246
+ ctools web --port 9000 # a different port
247
+ ```
248
+
249
+ `ctools-web` is the same command. The dashboard is a read-mostly surface over
250
+ the same data the CLI uses. You can:
251
+
252
+ - Browse and search sessions (the "Conversation" view mirrors the CLI).
253
+ - Copy a session to another tool right from the UI.
254
+ - Export/download a session.
255
+ - Run **concept extraction** on a session (with optional LLM-backed
256
+ strategies and filters).
257
+
258
+ It binds to `127.0.0.1` only by default, so it's not exposed to your
259
+ network. Use `--host` to change that deliberately.
260
+
261
+ ---
262
+
263
+ ## Concepts: extract the intent of a session
264
+
265
+ A raw session is thousands of tokens. **Concepts** distills it into the few
266
+ things that matter for picking it back up: the goal, the constraints, and
267
+ what was decided.
268
+
269
+ ```bash
270
+ ctools extract @<agent>/<session-id> # or: cextract @<agent>/<session-id>
271
+ ```
272
+
273
+ Concepts are extracted one of three ways. Regex is the default; `-s` and `-F`
274
+ select the others:
275
+
276
+ 1. **Regex (default)**: built-in patterns for goal, decision, constraint,
277
+ and preference. No setup.
278
+ 2. **LLM strategy**: you define a chunking strategy that an LLM applies to
279
+ the session. Best for richer, contextual extraction.
280
+ 3. **Filter**: narrow the regex/LLM output with a rule (drop boilerplate,
281
+ keep only certain types, etc.).
282
+
283
+ Strategies and filters are stored as JSON config files that ctools reads at
284
+ runtime, in the config dir (see below). Create them in the dashboard (the
285
+ **Concepts** tab) or by hand.
286
+
287
+ **Where ctools keeps its config.** Config and data live in a per-user
288
+ directory resolved via `platformdirs` (no hand-rolled platform checks):
289
+
290
+ - Linux: `~/.config/ctools/` (config), `~/.local/share/ctools/` (data)
291
+ - macOS: `~/Library/Application Support/ctools/` (the macOS convention)
292
+ - Windows: `%APPDATA%\ctools\` (config), `%LOCALAPPDATA%\ctools\` (data)
293
+
294
+ Set `$CTOOLS_CONFIG` (and `$CTOOLS_DATA`) to relocate. This holds
295
+ `resume-commands.json`, `strategies/`, `filters/`, and the general
296
+ **`ctools.toml`** config — one file, multiple sections. The first section,
297
+ `[hosts]`, lists the machines `ctools grep --hosts` searches too:
298
+
299
+ ```toml
300
+ # ~/.config/ctools/ctools.toml
301
+ [hosts]
302
+ fatty = "ssh://bobby@fatty.local"
303
+ workie = "ssh://10.0.0.4"
304
+ ```
305
+
306
+ Each value is an `ssh://[user@]host[:port]` reference (the same form `ccat`
307
+ and `ccopy` use for a remote side), so the host may be a `~/.ssh/config`
308
+ alias. A missing/malformed config never breaks a search — it just means
309
+ "local only".
310
+
311
+ The dashboard shows the full extraction pipeline (conversation → extraction
312
+ → filter → concepts) so you can see exactly what was kept and why.
313
+
314
+ ---
315
+
316
+ ## MCP server
317
+
318
+ The MCP server exposes the same capabilities to any MCP-capable coding agent
319
+ (Pi, Claude, OpenCode, etc.). It needs the `mcp` extra (see [Install](#install)).
320
+
321
+ ```bash
322
+ ctools mcp # run the server on stdio (same as ctools-mcp)
323
+ ```
324
+
325
+ ### Install and register with Pi
326
+
327
+ ```bash
328
+ ctools-mcp install
329
+ ```
330
+
331
+ If no working `ctxttools[mcp]` install is found, this installs one with
332
+ `uv tool`. It then registers the server in `~/.pi/agent/mcp.json`. Verify with:
333
+
334
+ ```bash
335
+ pi mcp list # "ctools-mcp … connected"
336
+ ```
337
+
338
+ `ctools-mcp uninstall` removes the entry again (`--all` also removes it from
339
+ Claude Code's and opencode's configs).
340
+
341
+ ### Manual registration (any host)
342
+
343
+ If you'd rather wire it up yourself, `print-config` emits the `mcpServers` JSON
344
+ snippet:
345
+
346
+ ```bash
347
+ ctools-mcp print-config
348
+ ```
349
+
350
+ Add that to your host's MCP config. The server is started with
351
+ `python -m ctools.ctools_mcp` from the install environment.
352
+
353
+ ### Tools exposed
354
+
355
+ | Tool | What it does |
356
+ |---|---|
357
+ | `list_agents` | Agents available and whether they're installed. |
358
+ | `list_sessions` | Recent sessions for one agent. |
359
+ | `search_sessions` | Find sessions by pattern or phrase. |
360
+ | `export_session` | Get the messages of a session. |
361
+ | `extract_concepts` | Extract concepts from a session. |
362
+ | `get_session_concepts` | Get a session's concepts, optionally of one type. |
363
+ | `copy_concepts` | Copy extracted concepts into a destination session. |
364
+
365
+ ---
366
+
367
+ ## MCP dependency
368
+
369
+ `ctools-mcp` pins `mcp>=1.2,<2.0`. The `mcp` package 2.x renamed
370
+ `FastMCP` to `MCPServer`, which breaks the v1 API ctools uses. If a fresh
371
+ install pulls `mcp>=2` and `ctools-mcp` won't start, pin the major version
372
+ (`pip install "mcp<2"`); the released package already does this.
373
+
374
+ ---
375
+
376
+ ## The agents ctools knows about
377
+
378
+ | Name | Tool | Storage |
379
+ |---|---|---|
380
+ | `claude` | Claude Desktop | JSON |
381
+ | `claude-code` | Claude Code CLI | JSONL |
382
+ | `codex` | OpenAI Codex CLI | JSONL |
383
+ | `pi` | Pi coding agent | JSONL |
384
+ | `omp` | omp (oh-my-pi) | JSONL |
385
+ | `opencode` | OpenCode CLI | SQLite |
386
+ | `kilo` | Kilo CLI | SQLite |
387
+ | `goose` | Goose AI agent | SQLite |
388
+ | `hermes` | Hermes agent | SQLite |
389
+ | `openclaw` | OpenClaw | SQLite |
390
+ | `cline` | Cline | JSON |
391
+ | `freebuff` | Freebuff | JSON |
392
+
393
+ An agent is "installed" if ctools can find its session directory (or DB
394
+ file); `ctools dir` shows which are found and where. Only claude-code,
395
+ opencode, kilo, codex, and pi can be a `copy` destination.
396
+
397
+ ---
398
+
399
+ ## How the data is handled
400
+
401
+ - **Read-only by default.** `dir`, `grep`, `cat`, `du`, the MCP read tools,
402
+ and the dashboard's read paths never modify your session files.
403
+ - **Writes are explicit.** `copy` writes a *new* session and never touches the
404
+ source. `extract` and `connect` write only when you name a session as the
405
+ destination, and `rm` only to the session you name.
406
+ - **Backed up first.** Before a local `copy` writes, it snapshots the
407
+ destination agent's storage and restores it automatically if the write goes
408
+ wrong. `ctools recover` lists and restores those snapshots.
409
+ - **Local unless you say otherwise.** The dashboard binds to `127.0.0.1`, and
410
+ the MCP server reads your local storage. Data only crosses the network when you
411
+ name an `ssh://` host or pass `grep --hosts`, and then only over your own ssh.
412
+
413
+ ---
414
+
415
+ ## Development
416
+
417
+ ```bash
418
+ git clone https://github.com/day50-dev/ctools
419
+ cd ctools
420
+ python -m venv .venv && . .venv/bin/activate
421
+ pip install -e ".[dev]"
422
+ python -m pytest
423
+ ```
424
+
425
+ The code is deliberately simple: each agent adapter is a class in
426
+ `ctools/agents.py`, each verb is one module (`ctools/cgrep.py`, …), and
427
+ `ctools/dispatch.py` routes `ctools <verb>` to them. The CLI, dashboard, and
428
+ MCP layers are thin over the shared `ctools.agents` registry.
429
+
430
+ ---
431
+
432
+ ## License
433
+
434
+ [MIT](LICENSE)