lifeline 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,30 @@
1
+ # Changelog
2
+
3
+ ## 0.2.1
4
+
5
+ - Fixed native Windows ConPTY keyboard input by sending text values to
6
+ `pywinpty` instead of unsupported byte strings.
7
+ - Stopped injecting the removed Gemini CLI `--session-id` argument and preserved
8
+ exact-session discovery through the newly created transcript and workspace.
9
+ - Made Claude, Codex, and Gemini transcript readers tolerate Windows encoding
10
+ differences and malformed bytes.
11
+ - Added Windows workspace-path parsing for Gemini sessions.
12
+
13
+ ## 0.2.0 - Public Beta
14
+
15
+ - Added bidirectional Claude Code, Codex, and Gemini handoffs.
16
+ - Added exact session tracking and live protected-session switching.
17
+ - Resumed targets now stay under Lifeline protection and start in the captured
18
+ project directory.
19
+ - Added immediate new-terminal handoffs on macOS and native Windows.
20
+ - Added native Windows ConPTY support through a Windows-only `pywinpty` dependency.
21
+ - Pinned native Windows support to the compatible `pywinpty` 2.x line.
22
+ - Windows npm command shims now use their PowerShell companions to preserve
23
+ arbitrary handoff text and reject unsafe batch-only launch paths.
24
+ - Added Linux and WSL fallback behavior.
25
+ - Added diagnostics, expanded secret redaction, secret-safe handoff storage,
26
+ packaging, and reliability tests.
27
+
28
+ ## 0.1.0
29
+
30
+ - Initial Claude Code to Codex handoff demo.
@@ -0,0 +1,17 @@
1
+ # Contributing
2
+
3
+ Use Python 3.9 or newer and keep runtime dependencies platform-specific and minimal.
4
+
5
+ Before opening a pull request:
6
+
7
+ ```bash
8
+ python -m unittest discover -s tests -v
9
+ python watch.py --selftest
10
+ python -m compileall -q .
11
+ python -m build
12
+ python -m twine check dist/*
13
+ ```
14
+
15
+ Never commit raw AI transcripts, handoff files, API keys, or other credentials.
16
+ Parser fixtures must be synthetic or fully sanitized. Compatibility reports should
17
+ include CLI versions and `lifeline doctor` output with private paths removed.
lifeline-0.2.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Avnish Raj
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.
@@ -0,0 +1,5 @@
1
+ include CHANGELOG.md
2
+ include CONTRIBUTING.md
3
+ include SECURITY.md
4
+ recursive-include docs *.md
5
+ recursive-include tests *.py *.jsonl
@@ -0,0 +1,414 @@
1
+ Metadata-Version: 2.4
2
+ Name: lifeline
3
+ Version: 0.2.1
4
+ Summary: When your AI hits its limit, your work shouldn't - resume your AI CLI session in another tool with full context.
5
+ Home-page: https://github.com/AvnishR4j/lifeline
6
+ Author: Avnish Raj
7
+ Author-email: AvnishR4j@users.noreply.github.com
8
+ License: MIT
9
+ Project-URL: Repository, https://github.com/AvnishR4j/lifeline
10
+ Project-URL: Issues, https://github.com/AvnishR4j/lifeline/issues
11
+ Keywords: ai,cli,context,handoff,claude,codex,gemini
12
+ Classifier: Environment :: Console
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Operating System :: MacOS
20
+ Classifier: Operating System :: Microsoft :: Windows
21
+ Classifier: Operating System :: POSIX :: Linux
22
+ Classifier: Topic :: Software Development :: Build Tools
23
+ Requires-Python: >=3.9
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Requires-Dist: pywinpty<3,>=2; platform_system == "Windows"
27
+ Dynamic: license-file
28
+
29
+ # Lifeline
30
+
31
+ > When your AI hits its limit, your work shouldn't.
32
+
33
+ [![CI](https://github.com/AvnishR4j/lifeline/actions/workflows/ci.yml/badge.svg)](https://github.com/AvnishR4j/lifeline/actions/workflows/ci.yml)
34
+ [![Python 3.9+](https://img.shields.io/badge/python-3.9%2B-3776AB)](https://www.python.org/)
35
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
36
+
37
+ **v0.2.1 public beta** — macOS is the primary supported platform. Native
38
+ Windows, Linux, and WSL are beta-supported.
39
+
40
+ Lifeline runs Claude Code, Codex, or Gemini under protection. When the active AI
41
+ hits its usage limit, Lifeline captures that exact session and opens another AI
42
+ with the useful context already loaded.
43
+
44
+ ```text
45
+ lifeline codex
46
+
47
+ ├── Codex works normally
48
+
49
+ ├── Codex hits its usage limit
50
+
51
+ └── Lifeline opens Claude or Gemini with the same context
52
+ ```
53
+
54
+ No re-explanation. No guessing which session you meant. The original session
55
+ stays available.
56
+
57
+ ## Watch The Demo
58
+
59
+ See Lifeline detect an interrupted AI coding session, capture its context, and
60
+ continue the work in another CLI.
61
+
62
+
63
+
64
+ https://github.com/user-attachments/assets/0ca13818-888b-4fa7-a208-780cca28b752
65
+
66
+
67
+
68
+ The video plays directly on GitHub; no download is required.
69
+
70
+ ## The Important Rule
71
+
72
+ Start the AI from a **normal terminal** using Lifeline:
73
+
74
+ ```bash
75
+ lifeline codex
76
+ ```
77
+
78
+ Do not launch plain `codex` and expect Lifeline to detect its limit. Lifeline can
79
+ only automatically watch sessions that were started with `lifeline claude`,
80
+ `lifeline codex`, or `lifeline gemini`.
81
+
82
+ Also, do not type `lifeline switch ...` into an AI chat prompt. Run manual switch
83
+ commands from a **second normal terminal window or tab**.
84
+
85
+ ## Use Lifeline In Three Steps
86
+
87
+ ### 1. Start a protected session
88
+
89
+ ```bash
90
+ lifeline codex
91
+ ```
92
+
93
+ Lifeline asks where it should hand the session over if Codex reaches its limit:
94
+
95
+ ```text
96
+ Start Codex under Lifeline protection.
97
+ When Codex hits its limit, switch to:
98
+ 1. Claude (default)
99
+ 2. Gemini
100
+ Choose [1-2] (default 1):
101
+ ```
102
+
103
+ ### 2. Work normally
104
+
105
+ Use Codex, Claude, or Gemini exactly as usual. Lifeline watches in the background
106
+ and tracks the exact transcript belonging to this protected launch.
107
+
108
+ You should see:
109
+
110
+ ```text
111
+ ⚡ Lifeline watching `codex` for usage limits (handoff target: claude)
112
+ Protection active.
113
+ ```
114
+
115
+ If that message was not shown when the AI started, the session is not protected.
116
+
117
+ ### 3. Let Lifeline switch automatically
118
+
119
+ When Lifeline sees a real usage-limit message, it captures the exact protected
120
+ session and opens the selected target with its context. The target starts in the
121
+ captured project directory and remains protected, so a later limit can hand the
122
+ work back again.
123
+
124
+ You can also switch before the limit. Open another normal terminal and run:
125
+
126
+ ```bash
127
+ lifeline switch claude
128
+ ```
129
+
130
+ ## Install And Run On Your Computer
131
+
132
+ ### macOS
133
+
134
+ Requirements: Python 3.9+, and at least two authenticated supported AI CLIs.
135
+
136
+ ```bash
137
+ # Install Lifeline directly from GitHub
138
+ python3 -m pip install --user --upgrade git+https://github.com/AvnishR4j/lifeline.git
139
+
140
+ # Confirm your setup
141
+ lifeline doctor
142
+
143
+ # Start a protected AI session
144
+ lifeline codex
145
+ ```
146
+
147
+ If `lifeline` is not found after installation, add your user Python scripts
148
+ directory to `PATH`, then restart Terminal:
149
+
150
+ ```bash
151
+ echo 'export PATH="$HOME/.local/bin:$HOME/Library/Python/3.9/bin:$PATH"' >> ~/.zshrc
152
+ source ~/.zshrc
153
+ ```
154
+
155
+ On macOS, Lifeline opens the target in a new Terminal.app window while keeping
156
+ the limited session open. The resumed target remains under Lifeline protection.
157
+
158
+ ### Windows
159
+
160
+ Use PowerShell or cmd. Python 3.9+ is required. Windows Terminal is recommended.
161
+
162
+ ```powershell
163
+ # Install or update to the latest GitHub version
164
+ py -m pip install --upgrade --force-reinstall git+https://github.com/AvnishR4j/lifeline.git
165
+
166
+ # Confirm the installed version and inspect the environment
167
+ lifeline version
168
+ lifeline doctor
169
+
170
+ # Start a protected session
171
+ lifeline codex
172
+ ```
173
+
174
+ Native Windows automatically installs `pywinpty` for interactive ConPTY support.
175
+ For immediate handoffs, Lifeline tries Windows Terminal, PowerShell, then cmd.
176
+ Git Bash is best-effort.
177
+
178
+ Windows users upgrading from `v0.2.0` should use the force-reinstall command
179
+ above. `v0.2.1` fixes native ConPTY keyboard input, supports current Gemini CLI
180
+ launches without the removed `--session-id` argument, and tolerates Windows
181
+ transcript encoding differences.
182
+
183
+ ### Linux
184
+
185
+ ```bash
186
+ python3 -m pip install --user --upgrade git+https://github.com/AvnishR4j/lifeline.git
187
+ lifeline doctor
188
+ lifeline codex
189
+ ```
190
+
191
+ On Linux, Lifeline watches the protected session and performs the handoff after
192
+ the limited CLI exits.
193
+
194
+ ### WSL
195
+
196
+ Install and run Lifeline inside WSL using the Linux commands:
197
+
198
+ ```bash
199
+ python3 -m pip install --user --upgrade git+https://github.com/AvnishR4j/lifeline.git
200
+ lifeline doctor
201
+ lifeline codex
202
+ ```
203
+
204
+ WSL uses the Unix PTY backend. Native Windows and WSL sessions remain separate.
205
+
206
+ ## Supported AI Tools
207
+
208
+ Install and authenticate at least two:
209
+
210
+ | CLI | Command | Login |
211
+ |---|---|---|
212
+ | [Claude Code](https://docs.anthropic.com/en/docs/claude-code) | `claude` | Follow Claude Code sign-in |
213
+ | [Codex CLI](https://github.com/openai/codex) | `codex` | `codex login` |
214
+ | [Gemini CLI](https://github.com/google-gemini/gemini-cli) | `gemini` | Run `gemini` and sign in |
215
+
216
+ All six directions are supported:
217
+
218
+ ```text
219
+ Claude → Codex Claude → Gemini
220
+ Codex → Claude Codex → Gemini
221
+ Gemini → Claude Gemini → Codex
222
+ ```
223
+
224
+ ## Commands You Will Use
225
+
226
+ ```bash
227
+ # Start protected sessions
228
+ lifeline claude
229
+ lifeline codex
230
+ lifeline gemini
231
+
232
+ # Choose the fallback without being asked
233
+ lifeline codex --to gemini
234
+
235
+ # Switch a currently protected session from another terminal
236
+ lifeline switch claude
237
+
238
+ # Check installation, backends, CLIs, and transcript parsing
239
+ lifeline doctor
240
+
241
+ # Preview a manual handoff without launching the target
242
+ lifeline handoff --from codex --to gemini --dry-run
243
+ ```
244
+
245
+ Other AI CLI arguments pass through:
246
+
247
+ ```bash
248
+ lifeline claude --to gemini --model opus
249
+ ```
250
+
251
+ The friendly launcher reserves `--to` for Lifeline. Put a literal underlying CLI
252
+ `--to` option after `--`:
253
+
254
+ ```bash
255
+ lifeline codex --to gemini -- --to some-codex-value
256
+ ```
257
+
258
+ ## Why Did Lifeline Not Switch?
259
+
260
+ If the AI displays a usage limit but nothing happens:
261
+
262
+ 1. Check whether the session was started with `lifeline codex`, `lifeline
263
+ claude`, or `lifeline gemini`.
264
+ 2. Look for the `⚡ Lifeline watching ...` startup message.
265
+ 3. Run `lifeline doctor` from a normal terminal.
266
+ 4. If the session was started directly, use a manual handoff:
267
+
268
+ ```bash
269
+ lifeline handoff --from codex --to claude
270
+ ```
271
+
272
+ Manual `lifeline switch` only sees sessions started under Lifeline protection.
273
+
274
+ ## Advanced Usage
275
+
276
+ Use the full commands when you need an explicit source, target, dry run, or
277
+ confirmation behavior:
278
+
279
+ ```bash
280
+ lifeline watch --to gemini -- claude
281
+ lifeline watch --yes --to codex -- claude
282
+ lifeline watch --new-terminal --to codex -- claude
283
+ lifeline handoff --from codex --to gemini --dry-run
284
+ lifeline handoff --from codex --to gemini --session-file ~/.codex/sessions/...jsonl
285
+ ```
286
+
287
+ Explicit `--from` is the most reliable bidirectional manual form:
288
+
289
+ ```bash
290
+ lifeline handoff --from claude --to codex
291
+ lifeline handoff --from claude --to gemini
292
+ lifeline handoff --from codex --to claude
293
+ lifeline handoff --from codex --to gemini
294
+ lifeline handoff --from gemini --to claude
295
+ lifeline handoff --from gemini --to codex
296
+
297
+ # Auto-detect is convenient, but explicit --from avoids ambiguity:
298
+ lifeline handoff --to codex
299
+
300
+ # Preview what would be sent without launching anything:
301
+ lifeline handoff --from codex --to gemini --dry-run
302
+ ```
303
+
304
+ **Sources** (capture *from*, via `--from`): `claude`, `codex`, `gemini` (default: `auto`).
305
+ **Targets** (resume *in*, via `--to`): `codex`, `gemini`, `claude`.
306
+ (Gemini uses `gemini -i "<prompt>"`; verify the flag against your installed
307
+ `@google/gemini-cli` version.)
308
+
309
+ This will:
310
+ 1. Resolve the selected source CLI session (Claude Code, Codex, or Gemini).
311
+ 2. Extract the task, recent conversation, last prompt, and uncommitted `git diff`.
312
+ 3. **Redact secrets** (see below) and warn you about what was scrubbed.
313
+ 4. Write a secret-safe handoff file to `~/.lifeline/handoffs/`.
314
+ 5. Launch the target CLI seeded with that context, in the captured project
315
+ directory and under continued Lifeline protection when the source CLI is
316
+ still installed.
317
+
318
+ ### Diagnostics
319
+
320
+ ```bash
321
+ lifeline doctor
322
+ ```
323
+
324
+ `doctor` checks which supported CLIs are on `PATH`, whether each session root
325
+ exists, whether the latest session for each source can be parsed, and prints the
326
+ supported source→target matrix. Use it first if a specific direction such as
327
+ Codex→Claude or Gemini→Codex is not working.
328
+
329
+ ## How it works
330
+
331
+ | File | Role |
332
+ |------|------|
333
+ | `watch.py` | Wraps an AI CLI in a PTY, watches output for a usage limit, auto-fires the handoff. |
334
+ | `terminal_backends.py` | Runs protected sessions through Unix PTY or native Windows ConPTY. |
335
+ | `terminal_launchers.py` | Opens immediate handoffs through Terminal.app or Windows Terminal/PowerShell/cmd. |
336
+ | `session_tracker.py` | Pins protected launches to exact transcripts and maintains the live-session registry used by `lifeline switch`. |
337
+ | `sources.py` | Registry of CLIs Lifeline can capture *from*; auto-detects the most recent session. |
338
+ | `extractor.py` | Reads the latest Claude session JSONL → normalized handoff data + renderer. |
339
+ | `codex_reader.py` | Reads the latest Codex `rollout-*.jsonl` session into the same normalized shape. |
340
+ | `gemini_reader.py` | Reads the latest Gemini chat session (`~/.gemini/tmp/*/chats/`) into the same shape. |
341
+ | `redact.py` | Scrubs secrets from text before it leaves the machine. |
342
+ | `handoff.py` | Orchestrates select source → capture → redact → write → launch target CLI. |
343
+
344
+ ## Security model
345
+
346
+ The handoff ships session content to another AI provider, so:
347
+
348
+ - **Secret redaction** — `redact.py` scans for OpenAI/GitHub/AWS/Google/Slack
349
+ keys, common service tokens, JWTs, credentials embedded in URLs, Bearer
350
+ tokens, PEM private keys, and `.env`-style secret assignments, and replaces
351
+ them with `[REDACTED:<kind>]`. It runs locally (regex only, no network, no
352
+ cost) and prints a summary of what was redacted before launch.
353
+ - **Safe process launch** — native executables receive argv lists directly.
354
+ Windows npm `.cmd` shims are replaced with their PowerShell companions so
355
+ handoff text stays data instead of being re-parsed by a batch shell. Lifeline
356
+ rejects batch-only targets that cannot safely preserve arbitrary context.
357
+ - **Private local storage** — handoff files live under
358
+ `~/.lifeline/handoffs/`. Unix uses `0600` files in `0700` directories;
359
+ Windows relies on the current user's profile-directory access controls.
360
+ - **Path safety** — `--project-dir` is validated to live under the selected
361
+ source CLI's session root. Exact `--session-file` paths receive the same
362
+ validation.
363
+ - **Metadata-only active registry** — live protected sessions are recorded under
364
+ `~/.lifeline/active/` using `0700`/`0600` permissions. Records contain source,
365
+ target, working directory, PID, session ID/path, and status; they do not copy
366
+ transcript content.
367
+
368
+ ### Known limitations (v0)
369
+
370
+ - **Beta support**: native Windows, Linux, and WSL are public-beta platforms.
371
+ PowerShell and cmd are tested on Windows; Git Bash is best-effort.
372
+ - **Source coverage**: Lifeline can capture from **Claude Code**, **Codex**, and
373
+ **Gemini** — all three work as both source and target (e.g. Codex→Claude,
374
+ Gemini→Claude). Other CLIs (Cursor, …) are not yet supported (see roadmap).
375
+ - **Prompt injection**: session content is wrapped and labeled as historical
376
+ context, but a determined injection inside the session could still influence the
377
+ resuming CLI. Acceptable for v0 since the session is your own.
378
+ - The redacted inline handoff may be temporarily visible to local process-list
379
+ inspection tools while the target CLI starts.
380
+ - Manual `lifeline switch` only targets live sessions launched under Lifeline.
381
+ Advanced `lifeline handoff` retains latest-session discovery for unprotected
382
+ sessions, so use explicit `--from` and `--session-file` when exact selection is
383
+ required there.
384
+ - Redaction is pattern-based; novel secret formats may slip through. Review the
385
+ `--dry-run` output for anything sensitive before a real handoff.
386
+
387
+ ## Troubleshooting
388
+
389
+ Run `lifeline doctor` first. It reports the selected terminal backend, target CLI
390
+ paths, session roots, parser health, and native Windows `pywinpty` availability.
391
+
392
+ On Windows, update with:
393
+
394
+ ```powershell
395
+ py -m pip install --upgrade --force-reinstall git+https://github.com/AvnishR4j/lifeline.git
396
+ lifeline version
397
+ lifeline doctor
398
+ ```
399
+
400
+ Use this update if keyboard input crashes with a `bytes ... PyString` error,
401
+ Gemini reports `Unknown arguments: session-id`, or ConPTY support is missing.
402
+ If immediate handoff cannot open a new terminal, the generated handoff remains
403
+ under `~/.lifeline/handoffs/` and the error includes the next action.
404
+
405
+ Uninstall with `pipx uninstall lifeline` or `py -m pip uninstall lifeline`.
406
+
407
+ ## Roadmap
408
+
409
+ - **Any→any handoff.** ✅ The source is pluggable via a `sources.py` registry and
410
+ a `--from` flag, with `claude`, `codex`, and `gemini` readers all registered as
411
+ launch targets — so any pair works (Codex→Claude, Gemini→Claude, …). The
412
+ auto-detect wrapper (`watch.py`) recognizes all three CLIs' real limit messages
413
+ and wires the wrapped CLI through as the capture source.
414
+ - More sources/targets: `cursor`, and others.