saikai 0.2.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.
@@ -0,0 +1,12 @@
1
+ __pycache__/
2
+ *.pyc
3
+ *.pyo
4
+ .pytest_cache/
5
+ .mypy_cache/
6
+ .venv/
7
+ dist/
8
+ *.egg-info/
9
+ uv.lock
10
+ docs/assets/saikai-demo.mp4
11
+ .superpowers/
12
+ .serena/
saikai-0.2.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 saikai contributors
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.
saikai-0.2.1/PKG-INFO ADDED
@@ -0,0 +1,308 @@
1
+ Metadata-Version: 2.4
2
+ Name: saikai
3
+ Version: 0.2.1
4
+ Summary: A terminal session browser for Claude Code — browse, search, group, and resume past sessions, with a built-in split-live pane (on by default).
5
+ Project-URL: Homepage, https://github.com/m-morino/saikai
6
+ Project-URL: Repository, https://github.com/m-morino/saikai
7
+ Project-URL: Issues, https://github.com/m-morino/saikai/issues
8
+ Project-URL: Changelog, https://github.com/m-morino/saikai/blob/master/CHANGELOG.md
9
+ Author: saikai contributors
10
+ License: MIT License
11
+
12
+ Copyright (c) 2026 saikai contributors
13
+
14
+ Permission is hereby granted, free of charge, to any person obtaining a copy
15
+ of this software and associated documentation files (the "Software"), to deal
16
+ in the Software without restriction, including without limitation the rights
17
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18
+ copies of the Software, and to permit persons to whom the Software is
19
+ furnished to do so, subject to the following conditions:
20
+
21
+ The above copyright notice and this permission notice shall be included in all
22
+ copies or substantial portions of the Software.
23
+
24
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30
+ SOFTWARE.
31
+ License-File: LICENSE
32
+ Keywords: claude,claude-code,cli,sessions,textual,tui
33
+ Classifier: Environment :: Console
34
+ Classifier: License :: OSI Approved :: MIT License
35
+ Classifier: Operating System :: Microsoft :: Windows
36
+ Classifier: Programming Language :: Python :: 3
37
+ Classifier: Programming Language :: Python :: 3.11
38
+ Classifier: Programming Language :: Python :: 3.12
39
+ Classifier: Programming Language :: Python :: 3.13
40
+ Classifier: Topic :: Utilities
41
+ Requires-Python: >=3.11
42
+ Requires-Dist: platformdirs>=3.6
43
+ Requires-Dist: ptyprocess>=0.7; sys_platform != 'win32'
44
+ Requires-Dist: pyte>=0.8
45
+ Requires-Dist: pywinpty>=2.0; sys_platform == 'win32'
46
+ Requires-Dist: textual>=0.50
47
+ Description-Content-Type: text/markdown
48
+
49
+ # saikai
50
+
51
+ [![CI](https://github.com/m-morino/saikai/actions/workflows/ci.yml/badge.svg)](https://github.com/m-morino/saikai/actions/workflows/ci.yml)
52
+ [![PyPI version](https://img.shields.io/pypi/v/saikai)](https://pypi.org/project/saikai/)
53
+ [![GitHub release](https://img.shields.io/github/v/release/m-morino/saikai)](https://github.com/m-morino/saikai/releases/latest)
54
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
55
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-blue.svg)](https://www.python.org/downloads/)
56
+
57
+ **English** | [日本語](README.ja.md)
58
+
59
+ Dozens of Claude Code sessions, one searchable table. saikai scans your entire
60
+ `~/.claude/projects` history, lets you filter and group by date / project /
61
+ topic, and resumes any session with `Enter`. By default (**split-live**) it keeps
62
+ several sessions running live in tabs beside the list — jump between conversations
63
+ without closing anything or losing scrollback.
64
+
65
+ *saikai* = 再開 "resume" + 再会 "reunion" (Japanese). Complements
66
+ [ccmanager](https://github.com/kbwo/ccmanager), which manages a live multi-agent
67
+ roster; saikai is for navigating and resuming the history.
68
+
69
+ ![saikai demo](docs/assets/saikai-demo.gif)
70
+
71
+ <sub>The demo uses fictional, leak-checked data. Regenerate the animated GIF
72
+ headlessly with `uv run scripts/make_demo_gif.py`; use
73
+ `uv run scripts/record_demo.py --guide` for a native-terminal recording.</sub>
74
+
75
+ ## Highlights
76
+
77
+ - **Every session, one table** — every Claude Code conversation on your
78
+ machine, sorted by real last activity, grouped by date / project / topic,
79
+ filtered as you type.
80
+ - **Resume in place** — `Enter` reopens a session with `claude --resume` in the
81
+ working directory it was started from (worktree-aware).
82
+ - **Split-live panes** — host several live `claude` sessions in tabs beside the
83
+ list; markers show at a glance who is busy `~`, waiting for your input `?`,
84
+ or finished `!`. Quit and `Shift+F4` restores the whole pane set later.
85
+ - **Session hygiene** — favorite `★`, hide, rename; AI one-line titles; an
86
+ inferred parent/child tree and LLM topic clusters for big histories.
87
+ - **RAM-aware** — a memory gate (commit headroom + load + physical floor)
88
+ warns before a new pane would push the machine into thrashing.
89
+ - **Keyboard-first** — everything works without a mouse: `Space` opens a
90
+ mnemonic command menu (`Space f` = favorite, `Space s` = sort …),
91
+ `Alt+←/→` resizes the split, `?` shows the live key map. The mouse is a
92
+ bonus (click to sort, drag the divider), never a requirement.
93
+ - **Unintrusive by design** — read-only over claude's own transcript files; no
94
+ daemon, no database. Two Python files on top of
95
+ [Textual](https://github.com/Textualize/textual), MIT-licensed.
96
+
97
+ > The live pane uses ConPTY on Windows and a POSIX PTY elsewhere — see
98
+ > [Platform support](#platform-support) for the per-OS verification status
99
+ > (Windows is the verified platform today).
100
+
101
+ ## Install
102
+
103
+ Requires **Python ≥ 3.11**. The easiest path is
104
+ [uv](https://docs.astral.sh/uv/) — it installs the PyPI package in an isolated
105
+ environment, no manual venv:
106
+
107
+ ```bash
108
+ uv tool install saikai # stable release → `saikai` on PATH
109
+ ```
110
+
111
+ From a clone:
112
+
113
+ ```bash
114
+ uv run saikai.py # run in place (deps auto-installed)
115
+ uv tool install . # install the `saikai` command on your PATH, then: saikai
116
+ ```
117
+
118
+ Prefer pip / pipx? Both work (deps come from `pyproject.toml`):
119
+
120
+ ```bash
121
+ pipx install saikai # isolated + on PATH
122
+ pip install saikai # into the active environment
123
+ ```
124
+
125
+ The split-live pane needs the PTY deps (`pyte`, and `pywinpty` on Windows /
126
+ `ptyprocess` elsewhere); they install automatically with any command above. If
127
+ they're somehow missing, saikai still runs in list-only mode (see below).
128
+
129
+ ## Usage
130
+
131
+ ```bash
132
+ saikai # every project, full history (the default)
133
+ saikai --here # only the current project (git repo)
134
+ saikai --days 7 # only the last 7 days (one-shot; --save-defaults persists)
135
+ saikai --table # static, non-interactive table
136
+ saikai --help
137
+ ```
138
+
139
+ ### Keys — learn three things
140
+
141
+ Everything else is on screen (the footer, the dropdowns, and the `␣` menu
142
+ that pops up when you pause).
143
+
144
+ 1. **Keys you already know.** `↑` `↓` move · `Enter` resumes · `/` or just
145
+ typing searches · `Tab` toggles the preview · `?` full key list · `Esc`
146
+ leaves the current context (search → list → quit).
147
+ 2. **`Space` is the menu.** Press `Space` in the list, then one mnemonic
148
+ letter. Hesitate after `Space` and the whole menu appears in place,
149
+ grouped by family (which-key style) — nothing to memorise:
150
+
151
+ | Session | View | Panes |
152
+ |---|---|---|
153
+ | `f` ★ favorite | `s` cycle **s**ort column | `n` new session |
154
+ | `h` hide | `o` flip sort **o**rder | `p` restore panes |
155
+ | `e` rename (edit) | `g` cycle grouping | `z` freeze pane |
156
+ | `y` copy prompt (yank) | `t` tree · `c` cluster | `a` next attention |
157
+ | `d` diff (changes) | `l` hide/show list | `x` close tab · `[` `]` tabs |
158
+ | `r` refresh | `,` settings · `/` hide/show bar | `Space` mark for batch launch |
159
+
160
+ Space is a deliberate menu key, not a claim that every TUI should use a
161
+ Space leader: it only arms while the session list owns focus, so search
162
+ fields and live agent panes keep a literal Space. It also avoids taking a
163
+ letter away from type-to-search. The trade-off is that list marking becomes
164
+ `Space Space`; set `[keys] leader = "none"` if conventional Space-to-mark is
165
+ more important to you.
166
+
167
+ 3. **`Ctrl+]` returns focus** from a live claude pane to the list (the pane
168
+ owns every other key, so claude works normally inside it).
169
+
170
+ **Search tokens** (combine with text and each other): `:fav` `:hidden` `:open`
171
+ `:active` `:recent`. The filter bar — search box plus the Group / Sort /
172
+ Status / Age dropdowns — is visible by default: `Tab`/`Shift+Tab` walk into
173
+ the dropdowns, `Enter` opens one, `␣/` reclaims the rows (persists).
174
+
175
+ More keyboard parity: `Alt+←/→` nudges the list/pane divider (persists, like
176
+ dragging it). Every menu action also has a legacy F-key alias — `?` lists
177
+ them all, including your `[keys]` remaps.
178
+
179
+ Don't like the defaults? In `config.toml`: `[keys] leader = "none"` turns the
180
+ mode off (Space then marks directly, as before), `leader = "ctrl+g"` moves it,
181
+ `leader_defaults = false` empties the map, and any `action = "x"` single-letter
182
+ entry remaps one sequence. **Mouse extras** (never required): click a column
183
+ header to sort, drag the divider, click rows and dropdowns.
184
+
185
+ ### Split-live (default)
186
+
187
+ ![Split-live: the session list on the left with a live claude pane running on the right](docs/assets/saikai-split-live.svg)
188
+
189
+ saikai runs real interactive `claude` processes in tabs beside the list whenever
190
+ its PTY deps (`pyte`, `pywinpty`/`ptyprocess`) are present — they ship as
191
+ dependencies, so this is the default. To opt out and use the lightweight
192
+ list-only browser (`Enter` = full-screen takeover resume), set the env var:
193
+
194
+ ```bash
195
+ SAIKAI_SPLIT_LIVE=0 saikai # also: false / no / off
196
+ ```
197
+
198
+ | Key | Action |
199
+ |-----|--------|
200
+ | `Enter` | open / focus a live pane for the selected session |
201
+ | `Shift+F8` | start a NEW claude session in any folder / git worktree |
202
+ | `Shift+F4` | reopen the panes from your last session (snapshot + resume) — anytime |
203
+ | `F2` / `F3` | previous / next live tab |
204
+ | `Shift+F3` | jump to the next pane needing attention (`?` waiting / `!` finished) |
205
+ | `F4` | hide / show the session list (full-width pane) |
206
+ | `Ctrl+]` | return focus from a pane back to the list (`SAIKAI_RELEASE_KEY` to change) |
207
+ | `F10` / `Shift+F10` | close the active tab / close all tabs (explicit close — *not* restored) |
208
+ | `Esc` / `Ctrl+C` | quit: snapshot the open panes, then kill them all (`Shift+F4` reopens them next launch) |
209
+ | scroll up | freeze the pane (copy mode): select/copy while claude keeps running |
210
+
211
+ Markers in the list: `~` busy · `?` waiting for input · `!` finished (unanswered)
212
+ · `@` open · `+` active · `.` recent · `*` favorite · `x` hidden.
213
+
214
+ ## Configuration (environment variables)
215
+
216
+ | Variable | Default | Meaning |
217
+ |---|---|---|
218
+ | `SAIKAI_SPLIT_LIVE` | on | live-pane mode; set `0`/`false`/`no`/`off` to disable → list-only browser + full-takeover resume |
219
+ | `SAIKAI_AUTO_REFRESH` | off | seconds between background re-scans |
220
+ | `SAIKAI_SUMMARIZE_CMD` | — | command to summarize with (prompt on stdin → summary on stdout) instead of `claude -p` |
221
+ | `SAIKAI_AUTO_PERMISSION` | off | opt in to adding `--permission-mode auto` for frequently used workspaces |
222
+ | `SAIKAI_MAX_MEM_LOAD` | 85 | refuse/warn opening a pane above this memory-load % (Win `dwMemoryLoad`; Linux/macOS derived) |
223
+ | `SAIKAI_MIN_COMMIT_MB` | 2048 | keep this much **commit headroom** free — the system-freeze guard (Win/Linux) |
224
+ | `SAIKAI_MIN_FREE_PHYS_PCT` | 8 | keep ≥ this % of physical RAM available (anti-thrash floor, machine-relative) |
225
+ | `SAIKAI_CLAUDE_MB` | 600 | estimated RAM per live pane |
226
+ | `SAIKAI_MIN_FREE_MB` | 0 | optional absolute physical floor (legacy; max'd with the % floor) |
227
+ | `SAIKAI_HARD_RAM_GATE` | off | `1` refuses (vs warns) when the gate would be crossed |
228
+ | `SAIKAI_MAX_LIVE` | 64 | hard cap on concurrent live panes (backstop) |
229
+ | `SAIKAI_SCROLLBACK` | 2000 | per-pane scrollback lines kept in memory. **Biggest lever on the live process's RAM** (a full pane ≈ cols×lines pyte cells); lower it (e.g. 1000) on a memory-tight machine, raise for deeper history |
230
+ | `SAIKAI_COLOR_BY` | project | what tints the session title: `project` / `worktree` / `topic` / `none` |
231
+ | `SAIKAI_SPLIT_RATIO` | 0.34 | initial list/pane split (drag the divider to change; the dragged value persists) |
232
+ | `SAIKAI_RELEASE_KEY` | `ctrl+]` | key that returns focus from a live pane to the list |
233
+
234
+ saikai also reads an optional **TOML config file** for these same knobs (with
235
+ `env > config > default` precedence) plus `[keys]` rebinds. Run `saikai
236
+ --init-config` to write a documented template, `saikai --print-config` to see the
237
+ resolved location and values — or press **`Space ,`** inside the app: the
238
+ Settings screen edits the list options in place and shows every config knob
239
+ with its resolved value and source (`e` there opens config.toml in your editor).
240
+
241
+ Claude Code is the currently integrated provider. Agent-specific launch and
242
+ status contracts live in `saikai_provider.py`; a Codex contract validates the
243
+ extension boundary, but Codex is not selectable until its history discovery and
244
+ live-state integration are complete. Claude history discovery respects
245
+ `CLAUDE_CONFIG_DIR`.
246
+
247
+ ## Platform support
248
+
249
+ **Verified support is deliberately bounded to Windows 10 / 11 on Python ≥
250
+ 3.11.** Linux, WSL2, and macOS remain implemented but experimental until their
251
+ real PTY paths receive sustained native testing. Other platforms are unsupported.
252
+
253
+ saikai itself is pure Python + Textual; the **split-live pane** is the only
254
+ platform-specific part (it drives a real PTY and the clipboard). Honest status:
255
+
256
+ | OS | Live-pane PTY | Clipboard (from a frozen pane) | RAM gate source | Status |
257
+ |---|---|---|---|---|
258
+ | **Windows** 10 / 11 | ConPTY (`pywinpty`) | Win32 `CF_UNICODETEXT` (codepage-safe) | `GlobalMemoryStatusEx` | ✅ **developed & daily-driven** (on WezTerm) |
259
+ | **Linux** *(incl. WSL2)* | POSIX PTY (`ptyprocess`) | OSC-52 *(terminal / tmux / SSH policy must allow it)* | `/proc/meminfo` | ⚠️ **experimental; native reviewers wanted** |
260
+ | **macOS** | POSIX PTY (`ptyprocess`) | local `pbcopy`; OSC-52 fallback for remote-capable terminals | `sysctl` + `vm_stat` *(load + physical; no commit limit)* | ⚠️ **experimental; macOS reviewers wanted** |
261
+
262
+ - **Terminal-agnostic on Windows:** the clipboard goes through the Win32
263
+ `CF_UNICODETEXT` API and the PTY through ConPTY, neither of which depends on
264
+ the host terminal — so **Windows Terminal** uses the same code paths as WezTerm
265
+ (verified terminal) and is expected to behave identically.
266
+ - **List-only mode** (`SAIKAI_SPLIT_LIVE=0`) has no PTY dependency and should run
267
+ anywhere Textual runs.
268
+ - The headless regression tests are platform-independent (they stub out
269
+ textual / pyte / pywinpty) and pass on the dev machine — run them with plain
270
+ `python` (no deps needed):
271
+
272
+ ```bash
273
+ python tests/test_config.py
274
+ python tests/test_providers.py
275
+ python tests/test_sort_recency.py
276
+ python tests/test_split_divider.py
277
+ python tests/test_terminal_concurrency.py
278
+ python tests/test_resource_bounds.py
279
+ python tests/test_terminal_watchdog.py
280
+ python tests/test_keyboard_leader.py
281
+ python tests/test_pty_backend.py
282
+ ```
283
+
284
+ - Linux/WSL2/macOS reviewers are wanted. Please report the terminal, local vs
285
+ SSH/tmux setup, PTY teardown result, key quirks, and clipboard behavior.
286
+ - CI installs each OS's real PTY backend and smoke-tests spawn, resize, output,
287
+ and EOF on Windows, Linux, and macOS. This is not a substitute for interactive
288
+ review across terminal emulators, SSH, tmux, IMEs, and clipboard policies.
289
+
290
+ ## Contributing
291
+
292
+ Issues and PRs welcome — see [CONTRIBUTING.md](CONTRIBUTING.md) for the dev
293
+ setup, how to run the test suites, and the **concurrency invariants** that keep
294
+ the split-live pane from deadlocking (read those before touching threading code).
295
+ Changes are documented in [CHANGELOG.md](CHANGELOG.md).
296
+
297
+ ## Security
298
+
299
+ Please report vulnerabilities privately — see [SECURITY.md](SECURITY.md). Don't
300
+ open a public issue for a security problem.
301
+
302
+ ## License
303
+
304
+ saikai is released under the [MIT License](LICENSE). It depends on a few
305
+ third-party packages installed separately (textual, pyte, pywinpty/ptyprocess) —
306
+ see [THIRD-PARTY-NOTICES.md](THIRD-PARTY-NOTICES.md). Note `pyte` is LGPL-3.0; it
307
+ is used as an unmodified, separately-installed dependency, which keeps saikai's
308
+ own code MIT.
saikai-0.2.1/README.md ADDED
@@ -0,0 +1,260 @@
1
+ # saikai
2
+
3
+ [![CI](https://github.com/m-morino/saikai/actions/workflows/ci.yml/badge.svg)](https://github.com/m-morino/saikai/actions/workflows/ci.yml)
4
+ [![PyPI version](https://img.shields.io/pypi/v/saikai)](https://pypi.org/project/saikai/)
5
+ [![GitHub release](https://img.shields.io/github/v/release/m-morino/saikai)](https://github.com/m-morino/saikai/releases/latest)
6
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
7
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-blue.svg)](https://www.python.org/downloads/)
8
+
9
+ **English** | [日本語](README.ja.md)
10
+
11
+ Dozens of Claude Code sessions, one searchable table. saikai scans your entire
12
+ `~/.claude/projects` history, lets you filter and group by date / project /
13
+ topic, and resumes any session with `Enter`. By default (**split-live**) it keeps
14
+ several sessions running live in tabs beside the list — jump between conversations
15
+ without closing anything or losing scrollback.
16
+
17
+ *saikai* = 再開 "resume" + 再会 "reunion" (Japanese). Complements
18
+ [ccmanager](https://github.com/kbwo/ccmanager), which manages a live multi-agent
19
+ roster; saikai is for navigating and resuming the history.
20
+
21
+ ![saikai demo](docs/assets/saikai-demo.gif)
22
+
23
+ <sub>The demo uses fictional, leak-checked data. Regenerate the animated GIF
24
+ headlessly with `uv run scripts/make_demo_gif.py`; use
25
+ `uv run scripts/record_demo.py --guide` for a native-terminal recording.</sub>
26
+
27
+ ## Highlights
28
+
29
+ - **Every session, one table** — every Claude Code conversation on your
30
+ machine, sorted by real last activity, grouped by date / project / topic,
31
+ filtered as you type.
32
+ - **Resume in place** — `Enter` reopens a session with `claude --resume` in the
33
+ working directory it was started from (worktree-aware).
34
+ - **Split-live panes** — host several live `claude` sessions in tabs beside the
35
+ list; markers show at a glance who is busy `~`, waiting for your input `?`,
36
+ or finished `!`. Quit and `Shift+F4` restores the whole pane set later.
37
+ - **Session hygiene** — favorite `★`, hide, rename; AI one-line titles; an
38
+ inferred parent/child tree and LLM topic clusters for big histories.
39
+ - **RAM-aware** — a memory gate (commit headroom + load + physical floor)
40
+ warns before a new pane would push the machine into thrashing.
41
+ - **Keyboard-first** — everything works without a mouse: `Space` opens a
42
+ mnemonic command menu (`Space f` = favorite, `Space s` = sort …),
43
+ `Alt+←/→` resizes the split, `?` shows the live key map. The mouse is a
44
+ bonus (click to sort, drag the divider), never a requirement.
45
+ - **Unintrusive by design** — read-only over claude's own transcript files; no
46
+ daemon, no database. Two Python files on top of
47
+ [Textual](https://github.com/Textualize/textual), MIT-licensed.
48
+
49
+ > The live pane uses ConPTY on Windows and a POSIX PTY elsewhere — see
50
+ > [Platform support](#platform-support) for the per-OS verification status
51
+ > (Windows is the verified platform today).
52
+
53
+ ## Install
54
+
55
+ Requires **Python ≥ 3.11**. The easiest path is
56
+ [uv](https://docs.astral.sh/uv/) — it installs the PyPI package in an isolated
57
+ environment, no manual venv:
58
+
59
+ ```bash
60
+ uv tool install saikai # stable release → `saikai` on PATH
61
+ ```
62
+
63
+ From a clone:
64
+
65
+ ```bash
66
+ uv run saikai.py # run in place (deps auto-installed)
67
+ uv tool install . # install the `saikai` command on your PATH, then: saikai
68
+ ```
69
+
70
+ Prefer pip / pipx? Both work (deps come from `pyproject.toml`):
71
+
72
+ ```bash
73
+ pipx install saikai # isolated + on PATH
74
+ pip install saikai # into the active environment
75
+ ```
76
+
77
+ The split-live pane needs the PTY deps (`pyte`, and `pywinpty` on Windows /
78
+ `ptyprocess` elsewhere); they install automatically with any command above. If
79
+ they're somehow missing, saikai still runs in list-only mode (see below).
80
+
81
+ ## Usage
82
+
83
+ ```bash
84
+ saikai # every project, full history (the default)
85
+ saikai --here # only the current project (git repo)
86
+ saikai --days 7 # only the last 7 days (one-shot; --save-defaults persists)
87
+ saikai --table # static, non-interactive table
88
+ saikai --help
89
+ ```
90
+
91
+ ### Keys — learn three things
92
+
93
+ Everything else is on screen (the footer, the dropdowns, and the `␣` menu
94
+ that pops up when you pause).
95
+
96
+ 1. **Keys you already know.** `↑` `↓` move · `Enter` resumes · `/` or just
97
+ typing searches · `Tab` toggles the preview · `?` full key list · `Esc`
98
+ leaves the current context (search → list → quit).
99
+ 2. **`Space` is the menu.** Press `Space` in the list, then one mnemonic
100
+ letter. Hesitate after `Space` and the whole menu appears in place,
101
+ grouped by family (which-key style) — nothing to memorise:
102
+
103
+ | Session | View | Panes |
104
+ |---|---|---|
105
+ | `f` ★ favorite | `s` cycle **s**ort column | `n` new session |
106
+ | `h` hide | `o` flip sort **o**rder | `p` restore panes |
107
+ | `e` rename (edit) | `g` cycle grouping | `z` freeze pane |
108
+ | `y` copy prompt (yank) | `t` tree · `c` cluster | `a` next attention |
109
+ | `d` diff (changes) | `l` hide/show list | `x` close tab · `[` `]` tabs |
110
+ | `r` refresh | `,` settings · `/` hide/show bar | `Space` mark for batch launch |
111
+
112
+ Space is a deliberate menu key, not a claim that every TUI should use a
113
+ Space leader: it only arms while the session list owns focus, so search
114
+ fields and live agent panes keep a literal Space. It also avoids taking a
115
+ letter away from type-to-search. The trade-off is that list marking becomes
116
+ `Space Space`; set `[keys] leader = "none"` if conventional Space-to-mark is
117
+ more important to you.
118
+
119
+ 3. **`Ctrl+]` returns focus** from a live claude pane to the list (the pane
120
+ owns every other key, so claude works normally inside it).
121
+
122
+ **Search tokens** (combine with text and each other): `:fav` `:hidden` `:open`
123
+ `:active` `:recent`. The filter bar — search box plus the Group / Sort /
124
+ Status / Age dropdowns — is visible by default: `Tab`/`Shift+Tab` walk into
125
+ the dropdowns, `Enter` opens one, `␣/` reclaims the rows (persists).
126
+
127
+ More keyboard parity: `Alt+←/→` nudges the list/pane divider (persists, like
128
+ dragging it). Every menu action also has a legacy F-key alias — `?` lists
129
+ them all, including your `[keys]` remaps.
130
+
131
+ Don't like the defaults? In `config.toml`: `[keys] leader = "none"` turns the
132
+ mode off (Space then marks directly, as before), `leader = "ctrl+g"` moves it,
133
+ `leader_defaults = false` empties the map, and any `action = "x"` single-letter
134
+ entry remaps one sequence. **Mouse extras** (never required): click a column
135
+ header to sort, drag the divider, click rows and dropdowns.
136
+
137
+ ### Split-live (default)
138
+
139
+ ![Split-live: the session list on the left with a live claude pane running on the right](docs/assets/saikai-split-live.svg)
140
+
141
+ saikai runs real interactive `claude` processes in tabs beside the list whenever
142
+ its PTY deps (`pyte`, `pywinpty`/`ptyprocess`) are present — they ship as
143
+ dependencies, so this is the default. To opt out and use the lightweight
144
+ list-only browser (`Enter` = full-screen takeover resume), set the env var:
145
+
146
+ ```bash
147
+ SAIKAI_SPLIT_LIVE=0 saikai # also: false / no / off
148
+ ```
149
+
150
+ | Key | Action |
151
+ |-----|--------|
152
+ | `Enter` | open / focus a live pane for the selected session |
153
+ | `Shift+F8` | start a NEW claude session in any folder / git worktree |
154
+ | `Shift+F4` | reopen the panes from your last session (snapshot + resume) — anytime |
155
+ | `F2` / `F3` | previous / next live tab |
156
+ | `Shift+F3` | jump to the next pane needing attention (`?` waiting / `!` finished) |
157
+ | `F4` | hide / show the session list (full-width pane) |
158
+ | `Ctrl+]` | return focus from a pane back to the list (`SAIKAI_RELEASE_KEY` to change) |
159
+ | `F10` / `Shift+F10` | close the active tab / close all tabs (explicit close — *not* restored) |
160
+ | `Esc` / `Ctrl+C` | quit: snapshot the open panes, then kill them all (`Shift+F4` reopens them next launch) |
161
+ | scroll up | freeze the pane (copy mode): select/copy while claude keeps running |
162
+
163
+ Markers in the list: `~` busy · `?` waiting for input · `!` finished (unanswered)
164
+ · `@` open · `+` active · `.` recent · `*` favorite · `x` hidden.
165
+
166
+ ## Configuration (environment variables)
167
+
168
+ | Variable | Default | Meaning |
169
+ |---|---|---|
170
+ | `SAIKAI_SPLIT_LIVE` | on | live-pane mode; set `0`/`false`/`no`/`off` to disable → list-only browser + full-takeover resume |
171
+ | `SAIKAI_AUTO_REFRESH` | off | seconds between background re-scans |
172
+ | `SAIKAI_SUMMARIZE_CMD` | — | command to summarize with (prompt on stdin → summary on stdout) instead of `claude -p` |
173
+ | `SAIKAI_AUTO_PERMISSION` | off | opt in to adding `--permission-mode auto` for frequently used workspaces |
174
+ | `SAIKAI_MAX_MEM_LOAD` | 85 | refuse/warn opening a pane above this memory-load % (Win `dwMemoryLoad`; Linux/macOS derived) |
175
+ | `SAIKAI_MIN_COMMIT_MB` | 2048 | keep this much **commit headroom** free — the system-freeze guard (Win/Linux) |
176
+ | `SAIKAI_MIN_FREE_PHYS_PCT` | 8 | keep ≥ this % of physical RAM available (anti-thrash floor, machine-relative) |
177
+ | `SAIKAI_CLAUDE_MB` | 600 | estimated RAM per live pane |
178
+ | `SAIKAI_MIN_FREE_MB` | 0 | optional absolute physical floor (legacy; max'd with the % floor) |
179
+ | `SAIKAI_HARD_RAM_GATE` | off | `1` refuses (vs warns) when the gate would be crossed |
180
+ | `SAIKAI_MAX_LIVE` | 64 | hard cap on concurrent live panes (backstop) |
181
+ | `SAIKAI_SCROLLBACK` | 2000 | per-pane scrollback lines kept in memory. **Biggest lever on the live process's RAM** (a full pane ≈ cols×lines pyte cells); lower it (e.g. 1000) on a memory-tight machine, raise for deeper history |
182
+ | `SAIKAI_COLOR_BY` | project | what tints the session title: `project` / `worktree` / `topic` / `none` |
183
+ | `SAIKAI_SPLIT_RATIO` | 0.34 | initial list/pane split (drag the divider to change; the dragged value persists) |
184
+ | `SAIKAI_RELEASE_KEY` | `ctrl+]` | key that returns focus from a live pane to the list |
185
+
186
+ saikai also reads an optional **TOML config file** for these same knobs (with
187
+ `env > config > default` precedence) plus `[keys]` rebinds. Run `saikai
188
+ --init-config` to write a documented template, `saikai --print-config` to see the
189
+ resolved location and values — or press **`Space ,`** inside the app: the
190
+ Settings screen edits the list options in place and shows every config knob
191
+ with its resolved value and source (`e` there opens config.toml in your editor).
192
+
193
+ Claude Code is the currently integrated provider. Agent-specific launch and
194
+ status contracts live in `saikai_provider.py`; a Codex contract validates the
195
+ extension boundary, but Codex is not selectable until its history discovery and
196
+ live-state integration are complete. Claude history discovery respects
197
+ `CLAUDE_CONFIG_DIR`.
198
+
199
+ ## Platform support
200
+
201
+ **Verified support is deliberately bounded to Windows 10 / 11 on Python ≥
202
+ 3.11.** Linux, WSL2, and macOS remain implemented but experimental until their
203
+ real PTY paths receive sustained native testing. Other platforms are unsupported.
204
+
205
+ saikai itself is pure Python + Textual; the **split-live pane** is the only
206
+ platform-specific part (it drives a real PTY and the clipboard). Honest status:
207
+
208
+ | OS | Live-pane PTY | Clipboard (from a frozen pane) | RAM gate source | Status |
209
+ |---|---|---|---|---|
210
+ | **Windows** 10 / 11 | ConPTY (`pywinpty`) | Win32 `CF_UNICODETEXT` (codepage-safe) | `GlobalMemoryStatusEx` | ✅ **developed & daily-driven** (on WezTerm) |
211
+ | **Linux** *(incl. WSL2)* | POSIX PTY (`ptyprocess`) | OSC-52 *(terminal / tmux / SSH policy must allow it)* | `/proc/meminfo` | ⚠️ **experimental; native reviewers wanted** |
212
+ | **macOS** | POSIX PTY (`ptyprocess`) | local `pbcopy`; OSC-52 fallback for remote-capable terminals | `sysctl` + `vm_stat` *(load + physical; no commit limit)* | ⚠️ **experimental; macOS reviewers wanted** |
213
+
214
+ - **Terminal-agnostic on Windows:** the clipboard goes through the Win32
215
+ `CF_UNICODETEXT` API and the PTY through ConPTY, neither of which depends on
216
+ the host terminal — so **Windows Terminal** uses the same code paths as WezTerm
217
+ (verified terminal) and is expected to behave identically.
218
+ - **List-only mode** (`SAIKAI_SPLIT_LIVE=0`) has no PTY dependency and should run
219
+ anywhere Textual runs.
220
+ - The headless regression tests are platform-independent (they stub out
221
+ textual / pyte / pywinpty) and pass on the dev machine — run them with plain
222
+ `python` (no deps needed):
223
+
224
+ ```bash
225
+ python tests/test_config.py
226
+ python tests/test_providers.py
227
+ python tests/test_sort_recency.py
228
+ python tests/test_split_divider.py
229
+ python tests/test_terminal_concurrency.py
230
+ python tests/test_resource_bounds.py
231
+ python tests/test_terminal_watchdog.py
232
+ python tests/test_keyboard_leader.py
233
+ python tests/test_pty_backend.py
234
+ ```
235
+
236
+ - Linux/WSL2/macOS reviewers are wanted. Please report the terminal, local vs
237
+ SSH/tmux setup, PTY teardown result, key quirks, and clipboard behavior.
238
+ - CI installs each OS's real PTY backend and smoke-tests spawn, resize, output,
239
+ and EOF on Windows, Linux, and macOS. This is not a substitute for interactive
240
+ review across terminal emulators, SSH, tmux, IMEs, and clipboard policies.
241
+
242
+ ## Contributing
243
+
244
+ Issues and PRs welcome — see [CONTRIBUTING.md](CONTRIBUTING.md) for the dev
245
+ setup, how to run the test suites, and the **concurrency invariants** that keep
246
+ the split-live pane from deadlocking (read those before touching threading code).
247
+ Changes are documented in [CHANGELOG.md](CHANGELOG.md).
248
+
249
+ ## Security
250
+
251
+ Please report vulnerabilities privately — see [SECURITY.md](SECURITY.md). Don't
252
+ open a public issue for a security problem.
253
+
254
+ ## License
255
+
256
+ saikai is released under the [MIT License](LICENSE). It depends on a few
257
+ third-party packages installed separately (textual, pyte, pywinpty/ptyprocess) —
258
+ see [THIRD-PARTY-NOTICES.md](THIRD-PARTY-NOTICES.md). Note `pyte` is LGPL-3.0; it
259
+ is used as an unmodified, separately-installed dependency, which keeps saikai's
260
+ own code MIT.
@@ -0,0 +1,26 @@
1
+ # Third-party notices
2
+
3
+ saikai is licensed under the MIT License (see `LICENSE`). It depends on the
4
+ following third-party packages, installed separately via your package manager
5
+ (pip / uv) — saikai does **not** bundle or modify their source.
6
+
7
+ | Package | License | Role |
8
+ |---|---|---|
9
+ | [textual](https://github.com/Textualize/textual) | MIT | TUI framework |
10
+ | [rich](https://github.com/Textualize/rich) | MIT | text rendering (via textual) |
11
+ | [pyte](https://github.com/selectel/pyte) | **LGPL-3.0** | in-memory terminal emulator (split-live pane) |
12
+ | [pywinpty](https://github.com/andfoy/pywinpty) | MIT | Windows ConPTY backend (`sys_platform == 'win32'`) |
13
+ | [ptyprocess](https://github.com/pexpect/ptyprocess) | ISC | POSIX PTY backend (non-Windows) |
14
+
15
+ ## Note on pyte (LGPL-3.0)
16
+
17
+ saikai imports `pyte` as an ordinary, unmodified dependency installed by the user
18
+ (pip/uv). It is **not** copied into this repository or statically combined with
19
+ saikai's source. Under the LGPL-3.0 this "use as a separately-installed library"
20
+ case does not impose the LGPL on saikai's own code, and the dynamic Python import
21
+ satisfies the requirement that the library remain user-replaceable. saikai's own
22
+ source therefore remains under the MIT License.
23
+
24
+ If you redistribute saikai together with a copy of pyte (e.g. a vendored bundle
25
+ or a frozen binary), review the LGPL-3.0 terms — in that case you must keep pyte
26
+ under the LGPL and allow it to be replaced.