pocketshell 0.3.2__tar.gz → 0.3.5__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 (27) hide show
  1. {pocketshell-0.3.2 → pocketshell-0.3.5}/PKG-INFO +54 -1
  2. {pocketshell-0.3.2 → pocketshell-0.3.5}/README.md +53 -0
  3. {pocketshell-0.3.2 → pocketshell-0.3.5}/pyproject.toml +1 -1
  4. {pocketshell-0.3.2 → pocketshell-0.3.5}/src/pocketshell/cli.py +4 -0
  5. pocketshell-0.3.5/src/pocketshell/env.py +681 -0
  6. pocketshell-0.3.5/src/pocketshell/hooks.py +926 -0
  7. pocketshell-0.3.5/tests/test_env.py +415 -0
  8. pocketshell-0.3.5/tests/test_hooks.py +521 -0
  9. {pocketshell-0.3.2 → pocketshell-0.3.5}/uv.lock +1 -1
  10. {pocketshell-0.3.2 → pocketshell-0.3.5}/.gitignore +0 -0
  11. {pocketshell-0.3.2 → pocketshell-0.3.5}/src/pocketshell/__init__.py +0 -0
  12. {pocketshell-0.3.2 → pocketshell-0.3.5}/src/pocketshell/__main__.py +0 -0
  13. {pocketshell-0.3.2 → pocketshell-0.3.5}/src/pocketshell/agent_log.py +0 -0
  14. {pocketshell-0.3.2 → pocketshell-0.3.5}/src/pocketshell/daemon.py +0 -0
  15. {pocketshell-0.3.2 → pocketshell-0.3.5}/src/pocketshell/jobs.py +0 -0
  16. {pocketshell-0.3.2 → pocketshell-0.3.5}/src/pocketshell/qr_share.py +0 -0
  17. {pocketshell-0.3.2 → pocketshell-0.3.5}/src/pocketshell/repos.py +0 -0
  18. {pocketshell-0.3.2 → pocketshell-0.3.5}/src/pocketshell/sessions.py +0 -0
  19. {pocketshell-0.3.2 → pocketshell-0.3.5}/src/pocketshell/usage.py +0 -0
  20. {pocketshell-0.3.2 → pocketshell-0.3.5}/tests/__init__.py +0 -0
  21. {pocketshell-0.3.2 → pocketshell-0.3.5}/tests/test_agent_log.py +0 -0
  22. {pocketshell-0.3.2 → pocketshell-0.3.5}/tests/test_daemon.py +0 -0
  23. {pocketshell-0.3.2 → pocketshell-0.3.5}/tests/test_jobs.py +0 -0
  24. {pocketshell-0.3.2 → pocketshell-0.3.5}/tests/test_qr_share.py +0 -0
  25. {pocketshell-0.3.2 → pocketshell-0.3.5}/tests/test_repos.py +0 -0
  26. {pocketshell-0.3.2 → pocketshell-0.3.5}/tests/test_sessions.py +0 -0
  27. {pocketshell-0.3.2 → pocketshell-0.3.5}/tests/test_usage.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pocketshell
3
- Version: 0.3.2
3
+ Version: 0.3.5
4
4
  Summary: Unified server-side Python utility for the PocketShell Android client.
5
5
  Project-URL: Homepage, https://github.com/alexeygrigorev/pocketshell
6
6
  Project-URL: Issues, https://github.com/alexeygrigorev/pocketshell/issues
@@ -173,6 +173,59 @@ Requires the optional `qr` extra (see [Optional extras](#optional-extras)).
173
173
  Without it, the command exits 127 with the install hint and every other
174
174
  subcommand keeps working.
175
175
 
176
+ ### `pocketshell hooks`
177
+
178
+ Installs agent **stop / idle-detection** hooks across Claude Code,
179
+ Codex, and OpenCode and normalizes their events into a single
180
+ append-only JSONL bus the app can read back. Server-side only;
181
+ integration only — no "tell the agent to continue" action yet (deferred;
182
+ see issue #267 and locked decision **D26** in `docs/decisions.md`).
183
+
184
+ ```bash
185
+ pocketshell hooks install [--engine claude|codex|opencode|all] # default: all
186
+ pocketshell hooks status [--engine ...] [--json] [--last N]
187
+ pocketshell hooks events [--since ISO8601] [--limit N] [--json]
188
+ pocketshell hooks uninstall [--engine ...]
189
+ ```
190
+
191
+ `install` is **non-destructive — it merges, it never clobbers**:
192
+
193
+ - **Claude Code** — adds a `{type: "command", command: "python3 <handler>"}`
194
+ entry under the `Stop`, `SubagentStop`, and `Notification` hook events
195
+ in `~/.claude/settings.json`, only when absent. All other top-level
196
+ keys and any pre-existing user hooks are preserved.
197
+ - **Codex** — sets the top-level `notify` program in `~/.codex/config.toml`
198
+ to our handler (Codex hooks do not fire under `codex exec`, so `notify`
199
+ is the headless-safe signal). If `notify` is already set to something
200
+ else, it warns and **skips** rather than overwriting. The rest of the
201
+ TOML is preserved.
202
+ - **OpenCode** — drops a `pocketshell-idle-signal.js` plugin into
203
+ `~/.config/opencode/plugin/` without disturbing other plugins.
204
+
205
+ `install` is idempotent (running twice adds nothing new). Handler scripts
206
+ and the event bus live under `~/.cache/pocketshell/hooks/` (override with
207
+ `$POCKETSHELL_HOOKS_DIR`); each handler appends a normalized record
208
+ `{ts, engine, state, source, session_id, cwd, ...}` to
209
+ `events.jsonl`.
210
+
211
+ **Per-engine uninstall** (`pocketshell hooks uninstall`) removes only what
212
+ we added and is idempotent:
213
+
214
+ - **Claude Code** — drops our command group from each hook event; an
215
+ event key (and the top-level `hooks` object) is deleted only if we
216
+ created it and it ends up empty. A user's pre-existing hooks always
217
+ survive, so a pre-populated `settings.json` comes back
218
+ byte-equivalent for the unrelated parts.
219
+ - **Codex** — removes the top-level `notify` line only when it still
220
+ points at our handler. A `notify` the user pointed elsewhere is left
221
+ alone.
222
+ - **OpenCode** — deletes our plugin file; other plugins and the dir
223
+ itself are left in place.
224
+
225
+ The event bus (`events.jsonl`) is preserved on uninstall so
226
+ already-emitted records stay readable; only the generated handler
227
+ scripts are cleaned up.
228
+
176
229
  ## Development
177
230
 
178
231
  ```bash
@@ -145,6 +145,59 @@ Requires the optional `qr` extra (see [Optional extras](#optional-extras)).
145
145
  Without it, the command exits 127 with the install hint and every other
146
146
  subcommand keeps working.
147
147
 
148
+ ### `pocketshell hooks`
149
+
150
+ Installs agent **stop / idle-detection** hooks across Claude Code,
151
+ Codex, and OpenCode and normalizes their events into a single
152
+ append-only JSONL bus the app can read back. Server-side only;
153
+ integration only — no "tell the agent to continue" action yet (deferred;
154
+ see issue #267 and locked decision **D26** in `docs/decisions.md`).
155
+
156
+ ```bash
157
+ pocketshell hooks install [--engine claude|codex|opencode|all] # default: all
158
+ pocketshell hooks status [--engine ...] [--json] [--last N]
159
+ pocketshell hooks events [--since ISO8601] [--limit N] [--json]
160
+ pocketshell hooks uninstall [--engine ...]
161
+ ```
162
+
163
+ `install` is **non-destructive — it merges, it never clobbers**:
164
+
165
+ - **Claude Code** — adds a `{type: "command", command: "python3 <handler>"}`
166
+ entry under the `Stop`, `SubagentStop`, and `Notification` hook events
167
+ in `~/.claude/settings.json`, only when absent. All other top-level
168
+ keys and any pre-existing user hooks are preserved.
169
+ - **Codex** — sets the top-level `notify` program in `~/.codex/config.toml`
170
+ to our handler (Codex hooks do not fire under `codex exec`, so `notify`
171
+ is the headless-safe signal). If `notify` is already set to something
172
+ else, it warns and **skips** rather than overwriting. The rest of the
173
+ TOML is preserved.
174
+ - **OpenCode** — drops a `pocketshell-idle-signal.js` plugin into
175
+ `~/.config/opencode/plugin/` without disturbing other plugins.
176
+
177
+ `install` is idempotent (running twice adds nothing new). Handler scripts
178
+ and the event bus live under `~/.cache/pocketshell/hooks/` (override with
179
+ `$POCKETSHELL_HOOKS_DIR`); each handler appends a normalized record
180
+ `{ts, engine, state, source, session_id, cwd, ...}` to
181
+ `events.jsonl`.
182
+
183
+ **Per-engine uninstall** (`pocketshell hooks uninstall`) removes only what
184
+ we added and is idempotent:
185
+
186
+ - **Claude Code** — drops our command group from each hook event; an
187
+ event key (and the top-level `hooks` object) is deleted only if we
188
+ created it and it ends up empty. A user's pre-existing hooks always
189
+ survive, so a pre-populated `settings.json` comes back
190
+ byte-equivalent for the unrelated parts.
191
+ - **Codex** — removes the top-level `notify` line only when it still
192
+ points at our handler. A `notify` the user pointed elsewhere is left
193
+ alone.
194
+ - **OpenCode** — deletes our plugin file; other plugins and the dir
195
+ itself are left in place.
196
+
197
+ The event bus (`events.jsonl`) is preserved on uninstall so
198
+ already-emitted records stay readable; only the generated handler
199
+ scripts are cleaned up.
200
+
148
201
  ## Development
149
202
 
150
203
  ```bash
@@ -8,7 +8,7 @@ name = "pocketshell"
8
8
  # scripts/check-pypi-version.sh enforces this; .github/workflows/build.yml
9
9
  # runs that check before publishing to PyPI. See
10
10
  # tools/pocketshell/README.md ("Release flow") for the bump procedure.
11
- version = "0.3.2"
11
+ version = "0.3.5"
12
12
  description = "Unified server-side Python utility for the PocketShell Android client."
13
13
  readme = "README.md"
14
14
  requires-python = ">=3.11"
@@ -23,6 +23,8 @@ import click
23
23
 
24
24
  from pocketshell import __version__
25
25
  from pocketshell.agent_log import agent_log_command
26
+ from pocketshell.env import env_group
27
+ from pocketshell.hooks import hooks_group
26
28
  from pocketshell.jobs import jobs_group
27
29
  from pocketshell.qr_share import qr_share_command
28
30
  from pocketshell.repos import repos_group
@@ -50,6 +52,8 @@ cli.add_command(jobs_group, name="jobs")
50
52
  cli.add_command(sessions_group, name="sessions")
51
53
  cli.add_command(agent_log_command, name="agent-log")
52
54
  cli.add_command(repos_group, name="repos")
55
+ cli.add_command(env_group, name="env")
56
+ cli.add_command(hooks_group, name="hooks")
53
57
  cli.add_command(qr_share_command, name="qr-share")
54
58
 
55
59