sessiontools 0.3.1__tar.gz → 0.3.3__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 (106) hide show
  1. {sessiontools-0.3.1 → sessiontools-0.3.3}/PKG-INFO +96 -32
  2. {sessiontools-0.3.1 → sessiontools-0.3.3}/README.md +93 -31
  3. sessiontools-0.3.3/pyproject.toml +42 -0
  4. sessiontools-0.3.1/pyproject.toml → sessiontools-0.3.3/pyproject.toml.orig +11 -1
  5. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/account/cli.py +52 -13
  6. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/account/limits.py +6 -4
  7. sessiontools-0.3.3/src/sessiontools/account/profile.py +147 -0
  8. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/account/status.py +139 -35
  9. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/account/use.py +26 -6
  10. sessiontools-0.3.3/src/sessiontools/account/verify.py +419 -0
  11. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/band.py +1 -1
  12. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/busy.py +283 -22
  13. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/cli.py +37 -2
  14. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/default_model_cli.py +1 -1
  15. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/default_model_watch.py +6 -3
  16. sessiontools-0.3.3/src/sessiontools/identity_block.py +169 -0
  17. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/listing.py +101 -6
  18. sessiontools-0.3.3/src/sessiontools/migrate.py +572 -0
  19. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/operator.py +66 -13
  20. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/pane_state_agent.py +8 -3
  21. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/park.py +16 -7
  22. sessiontools-0.3.3/src/sessiontools/paths.py +322 -0
  23. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/reap.py +7 -5
  24. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/session_info.py +52 -5
  25. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/settings.py +398 -14
  26. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/snapshot.py +5 -7
  27. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/sound/__init__.py +6 -8
  28. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/sound/engine.swift +1 -1
  29. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/sound/service.py +29 -8
  30. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/start/__init__.py +135 -26
  31. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/start/agents.py +54 -20
  32. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/start/args.py +5 -3
  33. sessiontools-0.3.3/src/sessiontools/start/boot_identity.py +427 -0
  34. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/start/claude_settings.py +71 -5
  35. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/start/default_seat.py +5 -2
  36. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/start/environment.py +10 -1
  37. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/start/holders.py +89 -13
  38. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/start/placement.py +35 -3
  39. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/start/plan.py +69 -20
  40. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/start/policy.py +0 -2
  41. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/start/run.py +33 -1
  42. sessiontools-0.3.3/src/sessiontools/web/__init__.py +23 -0
  43. sessiontools-0.3.3/src/sessiontools/web/auth.py +756 -0
  44. sessiontools-0.3.3/src/sessiontools/web/bind.py +69 -0
  45. sessiontools-0.3.3/src/sessiontools/web/cli.py +196 -0
  46. sessiontools-0.3.3/src/sessiontools/web/passkey.js +94 -0
  47. sessiontools-0.3.3/src/sessiontools/web/passkey.py +187 -0
  48. sessiontools-0.3.3/src/sessiontools/web/proxy.py +189 -0
  49. sessiontools-0.3.3/src/sessiontools/web/rooms.py +256 -0
  50. sessiontools-0.3.3/src/sessiontools/web/server.py +600 -0
  51. sessiontools-0.3.3/src/sessiontools/web/settings_page.py +351 -0
  52. sessiontools-0.3.3/src/sessiontools/web/supervisor.py +216 -0
  53. sessiontools-0.3.3/src/sessiontools/web/unixhttp.py +197 -0
  54. {sessiontools-0.3.1 → sessiontools-0.3.3}/LICENSE +0 -0
  55. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/__init__.py +0 -0
  56. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/account/__init__.py +0 -0
  57. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/account/keychain.py +0 -0
  58. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/account/leakscan.py +0 -0
  59. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/account/movehome.py +0 -0
  60. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/account/new.py +0 -0
  61. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/account/registry.py +0 -0
  62. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/account/setuptoken.py +0 -0
  63. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/account/tokenfile.py +0 -0
  64. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/account/tokenstore.py +0 -0
  65. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/claude_code.py +0 -0
  66. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/clockline.py +0 -0
  67. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/completion.py +0 -0
  68. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/context_parts/__init__.py +0 -0
  69. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/context_parts/boot.py +0 -0
  70. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/context_parts/breakdown.py +0 -0
  71. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/context_parts/hooks.py +0 -0
  72. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/context_parts/nnls.py +0 -0
  73. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/context_parts/render.py +0 -0
  74. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/context_parts/slash_context.py +0 -0
  75. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/context_parts/tools.py +0 -0
  76. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/context_parts/transcript.py +0 -0
  77. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/default_model.py +0 -0
  78. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/get.py +0 -0
  79. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/ledger/__init__.py +0 -0
  80. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/ledger/_tiktoken_child.py +0 -0
  81. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/ledger/count.py +0 -0
  82. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/ledger/render.py +0 -0
  83. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/ledger/transcript.py +0 -0
  84. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/pane_state.py +0 -0
  85. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/procs.py +0 -0
  86. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/py.typed +0 -0
  87. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/send.py +0 -0
  88. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/settle.py +0 -0
  89. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/sound/event.swift +0 -0
  90. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/start/agentfile.py +0 -0
  91. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/start/context.py +0 -0
  92. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/start/default_seat.md +0 -0
  93. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/start/errors.py +0 -0
  94. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/start/homefolder.py +0 -0
  95. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/start/identity.py +0 -0
  96. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/start/record.py +0 -0
  97. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/start/resume.py +0 -0
  98. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/start/secrets.py +0 -0
  99. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/start/vendor.py +0 -0
  100. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/statusline/__init__.py +0 -0
  101. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/statusline/sample.json +0 -0
  102. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/statusline/statusline.sh +0 -0
  103. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/tmux.py +0 -0
  104. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/turn.py +0 -0
  105. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/verbs.py +0 -0
  106. {sessiontools-0.3.1 → sessiontools-0.3.3}/src/sessiontools/window.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sessiontools
3
- Version: 0.3.1
3
+ Version: 0.3.3
4
4
  Summary: The harness layer: sessions, status and idle, one driver per harness - a library first
5
5
  Author: Mike Bailey
6
6
  Author-email: Mike Bailey <mike@sessionkit.ai>
@@ -9,9 +9,11 @@ License-File: LICENSE
9
9
  Classifier: Development Status :: 3 - Alpha
10
10
  Requires-Dist: pyyaml>=6
11
11
  Requires-Dist: jsonschema>=4
12
+ Requires-Dist: cryptography>=42 ; extra == 'passkey'
12
13
  Requires-Python: >=3.11, <3.15
13
14
  Project-URL: Homepage, https://github.com/sessionkit/sessiontools
14
15
  Project-URL: Repository, https://github.com/sessionkit/sessiontools
16
+ Provides-Extra: passkey
15
17
  Description-Content-Type: text/markdown
16
18
 
17
19
  # sessiontools
@@ -61,6 +63,8 @@ eval "$(session completion bash)"
61
63
  category.
62
64
  - `session ledger --short`: each file read and command run, by tokens.
63
65
  - `session account status`: which Claude account this Mac is on.
66
+ - `session account verify`: which account the API bills for this seat's
67
+ token, from one 1-token request.
64
68
  - `session start --list-agents`: the agents it can start.
65
69
  - `session reap`: seats idle past 1h, each CLOSE or KEEP, and why. A dry
66
70
  run.
@@ -129,9 +133,11 @@ it. Each line says what puts it there and what takes it away.
129
133
  sessiontools` drops this package's entries, and `uv cache prune` drops
130
134
  the ones nothing uses.
131
135
  - **Folders, each made by a verb you run:**
132
- - `~/.session/state/list/`: the list cache, `snapshot.json` and
133
- `list.lock`, at the first `session list`.
134
- - `~/.session/sessions/<session-id>/`: one for each `session start`,
136
+ - `~/.sessionkit/tools/state/list/`: the list cache, `snapshot.json`
137
+ and `list.lock`, at the first `session list`. The state folders here
138
+ and below are on a fresh host; a host that still has
139
+ `~/.session/` keeps using its folders there until they are moved.
140
+ - `~/.sessionkit/tools/state/sessions/<session-id>/`: one for each `session start`,
135
141
  holding `launch/`, `log/settings.jsonl` and `session-id`. It also
136
142
  gets `settings/<tool>.d/50-env.json`, one for each tool whose
137
143
  settings name a variable that is set when the session starts. Each
@@ -139,14 +145,19 @@ it. Each line says what puts it there and what takes it away.
139
145
  `log/settings.jsonl` names each variable it read, never its value.
140
146
  The plugin's hooks and `session park` write only inside a folder
141
147
  that is already there.
142
- - `~/.session/state/reap.log`: `session reap --yes`.
143
- - `~/.session/state/pane-state/watch.lock`: the pane signal's service.
144
- - `~/.session/state/default-model/`: `backups/` and `log.jsonl`, the
145
- first time `session default-model enforce` changes settings.json.
148
+ - `~/.sessionkit/tools/state/pane-state/watch.lock`: the pane signal's
149
+ service.
150
+ - `~/.sessionkit/tools/state/default-model/`: `backups/` and
151
+ `log.jsonl`, the first time `session default-model enforce` changes
152
+ settings.json.
146
153
  - `~/.sessionkit/tools/accounts/`: `session account new` and `use`.
147
- - `~/.local/share/sessiontools/sound/bin/`: `session sound engine on`
148
- builds the sound engine there with `swiftc`.
149
- - `~/Library/Logs/sessiontools/`: the two services' logs.
154
+ - `~/.sessionkit/tools/state/sound/bin/`: `session sound engine on`
155
+ builds the sound engine there with `swiftc` (in
156
+ `~/.local/share/sessiontools/sound/bin/` while that old folder is
157
+ still there).
158
+ - `~/.sessionkit/tools/log/`: the services' logs and `reap.log`
159
+ (Logs, below). An older release wrote them elsewhere, and those
160
+ files stay where they were.
150
161
  - `SESSIONS_DIR`, `SESSION_STATE_DIR` and `SESSIONTOOLS_SOUND_HOME`
151
162
  move these folders when set.
152
163
  - **Services (launchd agents):** none until you turn one on. Each `on`
@@ -188,6 +199,12 @@ it. Each line says what puts it there and what takes it away.
188
199
  With `model.default` set, `session default-model enforce` (and the
189
200
  unit or `watch` that runs it) rewrites the top-level `"model"` in
190
201
  `~/.claude/settings.json`, after a backup.
202
+ - **Not changed by an upgrade: a live tmux server.** One born inside the
203
+ default seat by sessiontools 0.3.1 or earlier still hands
204
+ `CLAUDE_CODE_AGENT=claude` to every pane it makes, so a raw `claude`
205
+ there hears the seat's mail. Restarting that server, or running
206
+ `tmux set-environment -g -u CLAUDE_CODE_AGENT` on it, is yours to do
207
+ ([the default seat][default-seat]).
191
208
 
192
209
  ## Uninstall
193
210
 
@@ -208,23 +225,27 @@ uv tool uninstall sessiontools
208
225
  ```
209
226
 
210
227
  That leaves what the verbs made, listed above. The plugin's cached
211
- copy, the services' logs and the engine's folder are sessiontools'
212
- alone. To delete them:
228
+ copy and the engine's folder are sessiontools' alone. To delete them:
213
229
 
214
230
  ```bash
215
231
  rm -rf "${HOME:?}/.claude/plugins/cache/sessiontools"
216
- rm -rf "${HOME:?}/Library/Logs/sessiontools"
217
232
  rm -rf "${HOME:?}/.local/share/sessiontools"
233
+ rm -rf "${HOME:?}/.sessionkit/tools/state/sound"
218
234
  ```
219
235
 
236
+ The logs are left in place: the new ones in `~/.sessionkit/tools/log/`,
237
+ and an older release's in `~/Library/Logs/sessiontools/`. Nothing here
238
+ deletes from `~/Library/Logs`.
239
+
220
240
  uv's cache stays too, with the other things uv installed; `uv cache
221
241
  clean sessiontools` drops this package's entries.
222
242
 
223
243
  The rest is your data: delete it by hand only if you want it gone.
224
- `~/.sessionkit/tools/` holds your settings and accounts, and the
225
- accounts folder keeps the backups of every token `session account use`
226
- replaced. `~/.session/` holds the session folders and the list cache,
227
- and the kit's other packages keep their files in it too.
244
+ `~/.sessionkit/tools/` holds your settings, accounts, state and logs,
245
+ and the accounts folder keeps the backups of every token `session
246
+ account use` replaced. `~/.session/` holds the session folders (and, on
247
+ a host that has not moved it, the old state folder), and the kit's other
248
+ packages keep their files in it too.
228
249
 
229
250
  ## Docs
230
251
 
@@ -236,6 +257,10 @@ and the kit's other packages keep their files in it too.
236
257
  - [The `session list` cache][cache]: one computation, many readers
237
258
  - [Operator and privileged seats][operator]: who seats ask
238
259
  - [Closing idle seats][reap]: `session reap`, a dry run by default
260
+ - [Where tools keeps its state][state-paths]: each folder, old and new,
261
+ the rule, and `session path`, the verb peers ask
262
+ - [Moving tools' state][state-migrate]: `session path migrate`, one host
263
+ at a time, dry run first
239
264
  - [Shell completion][completion]: `session completion bash|zsh`, a static
240
265
  script built from the verbs' own parsers
241
266
  - [The Claude Code plugin][plugin]: the skill and the hooks
@@ -244,6 +269,8 @@ and the kit's other packages keep their files in it too.
244
269
  - [The busy sound][busy]: a sound while a tool batch runs long
245
270
  - [The session-info hooks][session-info]: the short session id as the
246
271
  session title, and the session's facts in context, both off by default
272
+ - [The identity block][identity]: who a launched session is, in its
273
+ context on turn one and from `session identity`
247
274
  - [The sound engine][engine]: the busy sound from one resident process
248
275
  - [The status line][status-line]: `session statusline install` puts it in the
249
276
  kit's claude-code layer, never `~/.claude`. `session start` seats show it;
@@ -266,11 +293,30 @@ be set, and where each one lives ([configuration][configuration]):
266
293
  - **Settings files**, JSON in layers: `~/.sessionkit/tools/settings/session.json`
267
294
  (the operator, the list cache, the pane signal, accounts, a session's
268
295
  home, the default model), `~/.sessionkit/tools/settings/sounds.json` (the busy sound), and
269
- `~/.sessionkit/tools/settings/claude-code.json` (the model, effort
270
- and status line `session start` passes on). Every key, its default and
296
+ `~/.sessionkit/tools/settings/claude-code.json` (the model, effort,
297
+ status line and renderer `session start` passes on). Every key, its default and
271
298
  which layers it is read from: [settings][settings].
272
- - **Folders of its own:** `~/.session/` (sessions, seats, agent files, the
273
- state dir) and `~/.sessionkit/tools/accounts/` (`session account`).
299
+ - **Folders of its own:** `~/.sessionkit/tools/accounts/` (`session
300
+ account`), and its state, each leaf with an old and a new folder. A
301
+ fresh host, one with no `~/.session/`, starts every leaf in the new
302
+ folder; an existing one stays put until it is moved, and a moved one
303
+ is followed
304
+ ([where tools keeps its state][state-paths]):
305
+ - `state`: `~/.session/state/`, new `~/.sessionkit/tools/state/`.
306
+ - `sessions`, `seats`, `agent` and `backups`: `~/.session/<leaf>/`, new
307
+ `~/.sessionkit/tools/state/<leaf>/`.
308
+ - `sound`: `~/.local/share/sessiontools/sound/`, new
309
+ `~/.sessionkit/tools/state/sound/`.
310
+ - **The rule, per leaf:** its variable when set; else the old folder
311
+ while it is real; else the new one when it exists; else the new one
312
+ for `state` and `sound`, and for the rest the new one on a fresh host
313
+ and the old one on a host that has `~/.session/`.
314
+ - **To see what is used:** `session path LEAF`, or `session path --json`.
315
+ - **To move `state` and `sound`:** `session path migrate --dry-run`,
316
+ then a real run with that host's go ([moving tools' state][state-migrate]).
317
+ - **Upgrade every copy of sessiontools on a host together,** other
318
+ packages' copies included: an older copy writes the old `state`
319
+ folder, and `session path --json` shows `stranded` when one lags.
274
320
  - **Environment variables:** the settle alert's `SESSION_SETTLE_AT`, the
275
321
  clock line's `SESSION_CLOCK_WARN_AT`, the hooks' `SESSIONTOOLS_HOOK_*`
276
322
  switches (`SESSIONTOOLS_HOOK_CLOCK=on` switches the clock line on), and
@@ -280,31 +326,46 @@ be set, and where each one lives ([configuration][configuration]):
280
326
 
281
327
  ## Logs
282
328
 
283
- - **The sound engine:** `~/Library/Logs/sessiontools/sound-engine.log`,
329
+ - **The sound engine:** `~/.sessionkit/tools/log/sound-engine.log`,
284
330
  once `session sound engine on` has run.
285
- - **The pane signal's agent:** `~/Library/Logs/sessiontools/pane-state.log`,
331
+ - **The pane signal's agent:** `~/.sessionkit/tools/log/pane-state.log`,
286
332
  once `session pane-state agent on` has run.
287
- - **The default model:** `~/.session/state/default-model/log.jsonl`, one
288
- line per write to settings.json, and
289
- `~/Library/Logs/sessiontools/default-model.log`, once you have loaded
333
+ - **The default model:** `~/.sessionkit/tools/state/default-model/log.jsonl`
334
+ (`~/.session/state/default-model/log.jsonl` on a Mac that still has
335
+ its old state folder), one line per write to settings.json, and
336
+ `~/.sessionkit/tools/log/default-model.log`, once you have loaded
290
337
  the launchd agent `session default-model unit launchd` prints.
291
- - **`session reap --yes`:** `~/.session/state/reap.log`, one line for each
292
- seat it closed or failed to close.
338
+ - **`session reap --yes`:** `~/.sessionkit/tools/log/reap.log`, one line
339
+ for each seat it closed or failed to close.
340
+ - **Busy detection:** `~/.sessionkit/tools/log/busy.log`, one line each
341
+ time voice could not be asked where its mouth is, naming why and the
342
+ folder used instead ([the busy sound][busy]).
293
343
  - **Each session's settings at birth:**
294
344
  `~/.session/sessions/<session-id>/log/settings.jsonl`, what `session
295
345
  start` read into that session's settings: each environment variable
296
346
  by name, never its value.
297
347
  - **The status line:** `~/.config/session/statusline-log.jsonl`, one line
298
348
  per render, only when `~/.config/session/` already exists.
349
+ - **Old logs, 0.3.1 and before:** the three services logged to
350
+ `~/Library/Logs/sessiontools/`, and `session reap --yes` to
351
+ `$SESSION_STATE_DIR/reap.log` (`~/.session/state/reap.log`). Those
352
+ files are left in place. A service an older release installed keeps
353
+ writing its old log, at every login too, until its plist is written
354
+ again: `on` for the sound engine and the pane signal, the steps in
355
+ [the default model][default-model] for its agent. The sound engine's
356
+ and the pane signal's `status` name an old log while it is still there.
299
357
 
300
358
  Follow one as it grows with `tail -F`, for example
301
- `tail -F ~/Library/Logs/sessiontools/pane-state.log`.
359
+ `tail -F ~/.sessionkit/tools/log/pane-state.log`.
302
360
 
303
361
  - **Health:** `session list` prints a row for each live session, with its
304
- state and context. A session you know is running that is not listed is
305
- one sessiontools cannot see.
362
+ state and context, and SEAT names the seat a session holds: `claude`
363
+ for the default seat, or an agent's name for its hand-launched
364
+ holder. A session you know is running that is not listed is one
365
+ sessiontools cannot see.
306
366
 
307
367
  [verbs]: docs/session.md
368
+ [default-seat]: docs/session.md#the-default-seat
308
369
  [start]: docs/session-start-launcher.md
309
370
  [credentials]: docs/session-start-launcher.md#credentials-are-never-handed-down
310
371
  [account]: docs/account.md
@@ -312,11 +373,14 @@ Follow one as it grows with `tail -F`, for example
312
373
  [operator]: docs/operator-privileged-seats.md
313
374
  [reap]: docs/session-reap.md
314
375
  [completion]: docs/shell-completion.md
376
+ [state-paths]: docs/tools-state-paths.md
377
+ [state-migrate]: docs/tools-state-migrate.md
315
378
  [plugin]: docs/claude-code-plugin.md
316
379
  [settle]: docs/settle-alert-hook.md
317
380
  [clock]: docs/clock-line-hook.md
318
381
  [busy]: docs/busy-sound-hook.md
319
382
  [session-info]: docs/session-info-hook.md
383
+ [identity]: docs/identity-block.md
320
384
  [engine]: docs/sound-engine-agent.md
321
385
  [status-line]: docs/status-line-script.md
322
386
  [pane-state]: docs/pane-state-signal.md
@@ -45,6 +45,8 @@ eval "$(session completion bash)"
45
45
  category.
46
46
  - `session ledger --short`: each file read and command run, by tokens.
47
47
  - `session account status`: which Claude account this Mac is on.
48
+ - `session account verify`: which account the API bills for this seat's
49
+ token, from one 1-token request.
48
50
  - `session start --list-agents`: the agents it can start.
49
51
  - `session reap`: seats idle past 1h, each CLOSE or KEEP, and why. A dry
50
52
  run.
@@ -113,9 +115,11 @@ it. Each line says what puts it there and what takes it away.
113
115
  sessiontools` drops this package's entries, and `uv cache prune` drops
114
116
  the ones nothing uses.
115
117
  - **Folders, each made by a verb you run:**
116
- - `~/.session/state/list/`: the list cache, `snapshot.json` and
117
- `list.lock`, at the first `session list`.
118
- - `~/.session/sessions/<session-id>/`: one for each `session start`,
118
+ - `~/.sessionkit/tools/state/list/`: the list cache, `snapshot.json`
119
+ and `list.lock`, at the first `session list`. The state folders here
120
+ and below are on a fresh host; a host that still has
121
+ `~/.session/` keeps using its folders there until they are moved.
122
+ - `~/.sessionkit/tools/state/sessions/<session-id>/`: one for each `session start`,
119
123
  holding `launch/`, `log/settings.jsonl` and `session-id`. It also
120
124
  gets `settings/<tool>.d/50-env.json`, one for each tool whose
121
125
  settings name a variable that is set when the session starts. Each
@@ -123,14 +127,19 @@ it. Each line says what puts it there and what takes it away.
123
127
  `log/settings.jsonl` names each variable it read, never its value.
124
128
  The plugin's hooks and `session park` write only inside a folder
125
129
  that is already there.
126
- - `~/.session/state/reap.log`: `session reap --yes`.
127
- - `~/.session/state/pane-state/watch.lock`: the pane signal's service.
128
- - `~/.session/state/default-model/`: `backups/` and `log.jsonl`, the
129
- first time `session default-model enforce` changes settings.json.
130
+ - `~/.sessionkit/tools/state/pane-state/watch.lock`: the pane signal's
131
+ service.
132
+ - `~/.sessionkit/tools/state/default-model/`: `backups/` and
133
+ `log.jsonl`, the first time `session default-model enforce` changes
134
+ settings.json.
130
135
  - `~/.sessionkit/tools/accounts/`: `session account new` and `use`.
131
- - `~/.local/share/sessiontools/sound/bin/`: `session sound engine on`
132
- builds the sound engine there with `swiftc`.
133
- - `~/Library/Logs/sessiontools/`: the two services' logs.
136
+ - `~/.sessionkit/tools/state/sound/bin/`: `session sound engine on`
137
+ builds the sound engine there with `swiftc` (in
138
+ `~/.local/share/sessiontools/sound/bin/` while that old folder is
139
+ still there).
140
+ - `~/.sessionkit/tools/log/`: the services' logs and `reap.log`
141
+ (Logs, below). An older release wrote them elsewhere, and those
142
+ files stay where they were.
134
143
  - `SESSIONS_DIR`, `SESSION_STATE_DIR` and `SESSIONTOOLS_SOUND_HOME`
135
144
  move these folders when set.
136
145
  - **Services (launchd agents):** none until you turn one on. Each `on`
@@ -172,6 +181,12 @@ it. Each line says what puts it there and what takes it away.
172
181
  With `model.default` set, `session default-model enforce` (and the
173
182
  unit or `watch` that runs it) rewrites the top-level `"model"` in
174
183
  `~/.claude/settings.json`, after a backup.
184
+ - **Not changed by an upgrade: a live tmux server.** One born inside the
185
+ default seat by sessiontools 0.3.1 or earlier still hands
186
+ `CLAUDE_CODE_AGENT=claude` to every pane it makes, so a raw `claude`
187
+ there hears the seat's mail. Restarting that server, or running
188
+ `tmux set-environment -g -u CLAUDE_CODE_AGENT` on it, is yours to do
189
+ ([the default seat][default-seat]).
175
190
 
176
191
  ## Uninstall
177
192
 
@@ -192,23 +207,27 @@ uv tool uninstall sessiontools
192
207
  ```
193
208
 
194
209
  That leaves what the verbs made, listed above. The plugin's cached
195
- copy, the services' logs and the engine's folder are sessiontools'
196
- alone. To delete them:
210
+ copy and the engine's folder are sessiontools' alone. To delete them:
197
211
 
198
212
  ```bash
199
213
  rm -rf "${HOME:?}/.claude/plugins/cache/sessiontools"
200
- rm -rf "${HOME:?}/Library/Logs/sessiontools"
201
214
  rm -rf "${HOME:?}/.local/share/sessiontools"
215
+ rm -rf "${HOME:?}/.sessionkit/tools/state/sound"
202
216
  ```
203
217
 
218
+ The logs are left in place: the new ones in `~/.sessionkit/tools/log/`,
219
+ and an older release's in `~/Library/Logs/sessiontools/`. Nothing here
220
+ deletes from `~/Library/Logs`.
221
+
204
222
  uv's cache stays too, with the other things uv installed; `uv cache
205
223
  clean sessiontools` drops this package's entries.
206
224
 
207
225
  The rest is your data: delete it by hand only if you want it gone.
208
- `~/.sessionkit/tools/` holds your settings and accounts, and the
209
- accounts folder keeps the backups of every token `session account use`
210
- replaced. `~/.session/` holds the session folders and the list cache,
211
- and the kit's other packages keep their files in it too.
226
+ `~/.sessionkit/tools/` holds your settings, accounts, state and logs,
227
+ and the accounts folder keeps the backups of every token `session
228
+ account use` replaced. `~/.session/` holds the session folders (and, on
229
+ a host that has not moved it, the old state folder), and the kit's other
230
+ packages keep their files in it too.
212
231
 
213
232
  ## Docs
214
233
 
@@ -220,6 +239,10 @@ and the kit's other packages keep their files in it too.
220
239
  - [The `session list` cache][cache]: one computation, many readers
221
240
  - [Operator and privileged seats][operator]: who seats ask
222
241
  - [Closing idle seats][reap]: `session reap`, a dry run by default
242
+ - [Where tools keeps its state][state-paths]: each folder, old and new,
243
+ the rule, and `session path`, the verb peers ask
244
+ - [Moving tools' state][state-migrate]: `session path migrate`, one host
245
+ at a time, dry run first
223
246
  - [Shell completion][completion]: `session completion bash|zsh`, a static
224
247
  script built from the verbs' own parsers
225
248
  - [The Claude Code plugin][plugin]: the skill and the hooks
@@ -228,6 +251,8 @@ and the kit's other packages keep their files in it too.
228
251
  - [The busy sound][busy]: a sound while a tool batch runs long
229
252
  - [The session-info hooks][session-info]: the short session id as the
230
253
  session title, and the session's facts in context, both off by default
254
+ - [The identity block][identity]: who a launched session is, in its
255
+ context on turn one and from `session identity`
231
256
  - [The sound engine][engine]: the busy sound from one resident process
232
257
  - [The status line][status-line]: `session statusline install` puts it in the
233
258
  kit's claude-code layer, never `~/.claude`. `session start` seats show it;
@@ -250,11 +275,30 @@ be set, and where each one lives ([configuration][configuration]):
250
275
  - **Settings files**, JSON in layers: `~/.sessionkit/tools/settings/session.json`
251
276
  (the operator, the list cache, the pane signal, accounts, a session's
252
277
  home, the default model), `~/.sessionkit/tools/settings/sounds.json` (the busy sound), and
253
- `~/.sessionkit/tools/settings/claude-code.json` (the model, effort
254
- and status line `session start` passes on). Every key, its default and
278
+ `~/.sessionkit/tools/settings/claude-code.json` (the model, effort,
279
+ status line and renderer `session start` passes on). Every key, its default and
255
280
  which layers it is read from: [settings][settings].
256
- - **Folders of its own:** `~/.session/` (sessions, seats, agent files, the
257
- state dir) and `~/.sessionkit/tools/accounts/` (`session account`).
281
+ - **Folders of its own:** `~/.sessionkit/tools/accounts/` (`session
282
+ account`), and its state, each leaf with an old and a new folder. A
283
+ fresh host, one with no `~/.session/`, starts every leaf in the new
284
+ folder; an existing one stays put until it is moved, and a moved one
285
+ is followed
286
+ ([where tools keeps its state][state-paths]):
287
+ - `state`: `~/.session/state/`, new `~/.sessionkit/tools/state/`.
288
+ - `sessions`, `seats`, `agent` and `backups`: `~/.session/<leaf>/`, new
289
+ `~/.sessionkit/tools/state/<leaf>/`.
290
+ - `sound`: `~/.local/share/sessiontools/sound/`, new
291
+ `~/.sessionkit/tools/state/sound/`.
292
+ - **The rule, per leaf:** its variable when set; else the old folder
293
+ while it is real; else the new one when it exists; else the new one
294
+ for `state` and `sound`, and for the rest the new one on a fresh host
295
+ and the old one on a host that has `~/.session/`.
296
+ - **To see what is used:** `session path LEAF`, or `session path --json`.
297
+ - **To move `state` and `sound`:** `session path migrate --dry-run`,
298
+ then a real run with that host's go ([moving tools' state][state-migrate]).
299
+ - **Upgrade every copy of sessiontools on a host together,** other
300
+ packages' copies included: an older copy writes the old `state`
301
+ folder, and `session path --json` shows `stranded` when one lags.
258
302
  - **Environment variables:** the settle alert's `SESSION_SETTLE_AT`, the
259
303
  clock line's `SESSION_CLOCK_WARN_AT`, the hooks' `SESSIONTOOLS_HOOK_*`
260
304
  switches (`SESSIONTOOLS_HOOK_CLOCK=on` switches the clock line on), and
@@ -264,31 +308,46 @@ be set, and where each one lives ([configuration][configuration]):
264
308
 
265
309
  ## Logs
266
310
 
267
- - **The sound engine:** `~/Library/Logs/sessiontools/sound-engine.log`,
311
+ - **The sound engine:** `~/.sessionkit/tools/log/sound-engine.log`,
268
312
  once `session sound engine on` has run.
269
- - **The pane signal's agent:** `~/Library/Logs/sessiontools/pane-state.log`,
313
+ - **The pane signal's agent:** `~/.sessionkit/tools/log/pane-state.log`,
270
314
  once `session pane-state agent on` has run.
271
- - **The default model:** `~/.session/state/default-model/log.jsonl`, one
272
- line per write to settings.json, and
273
- `~/Library/Logs/sessiontools/default-model.log`, once you have loaded
315
+ - **The default model:** `~/.sessionkit/tools/state/default-model/log.jsonl`
316
+ (`~/.session/state/default-model/log.jsonl` on a Mac that still has
317
+ its old state folder), one line per write to settings.json, and
318
+ `~/.sessionkit/tools/log/default-model.log`, once you have loaded
274
319
  the launchd agent `session default-model unit launchd` prints.
275
- - **`session reap --yes`:** `~/.session/state/reap.log`, one line for each
276
- seat it closed or failed to close.
320
+ - **`session reap --yes`:** `~/.sessionkit/tools/log/reap.log`, one line
321
+ for each seat it closed or failed to close.
322
+ - **Busy detection:** `~/.sessionkit/tools/log/busy.log`, one line each
323
+ time voice could not be asked where its mouth is, naming why and the
324
+ folder used instead ([the busy sound][busy]).
277
325
  - **Each session's settings at birth:**
278
326
  `~/.session/sessions/<session-id>/log/settings.jsonl`, what `session
279
327
  start` read into that session's settings: each environment variable
280
328
  by name, never its value.
281
329
  - **The status line:** `~/.config/session/statusline-log.jsonl`, one line
282
330
  per render, only when `~/.config/session/` already exists.
331
+ - **Old logs, 0.3.1 and before:** the three services logged to
332
+ `~/Library/Logs/sessiontools/`, and `session reap --yes` to
333
+ `$SESSION_STATE_DIR/reap.log` (`~/.session/state/reap.log`). Those
334
+ files are left in place. A service an older release installed keeps
335
+ writing its old log, at every login too, until its plist is written
336
+ again: `on` for the sound engine and the pane signal, the steps in
337
+ [the default model][default-model] for its agent. The sound engine's
338
+ and the pane signal's `status` name an old log while it is still there.
283
339
 
284
340
  Follow one as it grows with `tail -F`, for example
285
- `tail -F ~/Library/Logs/sessiontools/pane-state.log`.
341
+ `tail -F ~/.sessionkit/tools/log/pane-state.log`.
286
342
 
287
343
  - **Health:** `session list` prints a row for each live session, with its
288
- state and context. A session you know is running that is not listed is
289
- one sessiontools cannot see.
344
+ state and context, and SEAT names the seat a session holds: `claude`
345
+ for the default seat, or an agent's name for its hand-launched
346
+ holder. A session you know is running that is not listed is one
347
+ sessiontools cannot see.
290
348
 
291
349
  [verbs]: docs/session.md
350
+ [default-seat]: docs/session.md#the-default-seat
292
351
  [start]: docs/session-start-launcher.md
293
352
  [credentials]: docs/session-start-launcher.md#credentials-are-never-handed-down
294
353
  [account]: docs/account.md
@@ -296,11 +355,14 @@ Follow one as it grows with `tail -F`, for example
296
355
  [operator]: docs/operator-privileged-seats.md
297
356
  [reap]: docs/session-reap.md
298
357
  [completion]: docs/shell-completion.md
358
+ [state-paths]: docs/tools-state-paths.md
359
+ [state-migrate]: docs/tools-state-migrate.md
299
360
  [plugin]: docs/claude-code-plugin.md
300
361
  [settle]: docs/settle-alert-hook.md
301
362
  [clock]: docs/clock-line-hook.md
302
363
  [busy]: docs/busy-sound-hook.md
303
364
  [session-info]: docs/session-info-hook.md
365
+ [identity]: docs/identity-block.md
304
366
  [engine]: docs/sound-engine-agent.md
305
367
  [status-line]: docs/status-line-script.md
306
368
  [pane-state]: docs/pane-state-signal.md
@@ -0,0 +1,42 @@
1
+ [project]
2
+ name = "sessiontools"
3
+ version = "0.3.3"
4
+ description = "The harness layer: sessions, status and idle, one driver per harness - a library first"
5
+ readme = "README.md"
6
+ license = "AGPL-3.0-or-later"
7
+ license-files = ["LICENSE"]
8
+ classifiers = ["Development Status :: 3 - Alpha"]
9
+ requires-python = ">=3.11,<3.15"
10
+ dependencies = [
11
+ "PyYAML>=6",
12
+ "jsonschema>=4",
13
+ ]
14
+
15
+ [[project.authors]]
16
+ name = "Mike Bailey"
17
+ email = "mike@sessionkit.ai"
18
+
19
+ [project.optional-dependencies]
20
+ passkey = ["cryptography>=42"]
21
+
22
+ [project.urls]
23
+ Homepage = "https://github.com/sessionkit/sessiontools"
24
+ Repository = "https://github.com/sessionkit/sessiontools"
25
+
26
+ [project.scripts]
27
+ session = "sessiontools.cli:main"
28
+
29
+ [build-system]
30
+ requires = ["uv_build>=0.11.9,<0.12.0"]
31
+ build-backend = "uv_build"
32
+
33
+ [dependency-groups]
34
+ dev = [
35
+ "pytest>=8",
36
+ "ruff>=0.6",
37
+ "cryptography>=42",
38
+ ]
39
+
40
+ [tool.pytest.ini_options]
41
+ testpaths = ["tests"]
42
+ addopts = "--strict-markers"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "sessiontools"
3
- version = "0.3.1"
3
+ version = "0.3.3"
4
4
  description = "The harness layer: sessions, status and idle, one driver per harness - a library first"
5
5
  readme = "README.md"
6
6
  license = "AGPL-3.0-or-later"
@@ -34,6 +34,14 @@ dependencies = ["PyYAML>=6", "jsonschema>=4"]
34
34
  # aside: sessiontools provides it, same verbs, ported as package code.
35
35
  # Exactly one package owns `session` on the PATH; from here it is this one.
36
36
  # argparse and the library; PyYAML for `session start` alone (above).
37
+ # The front door's passkey (`session web serve`, PROPOSED door-passkey):
38
+ # WebAuthn verifies ECDSA and RSA signatures, which the standard library
39
+ # cannot, so `cryptography` comes only with this extra and only
40
+ # `sessiontools.web.passkey` imports it. Without it the front door is the
41
+ # pairing code alone. Rule 3: an extra is the maintainer's call too.
42
+ [project.optional-dependencies]
43
+ passkey = ["cryptography>=42"]
44
+
37
45
  [project.urls]
38
46
  Homepage = "https://github.com/sessionkit/sessiontools"
39
47
  Repository = "https://github.com/sessionkit/sessiontools"
@@ -49,6 +57,8 @@ build-backend = "uv_build"
49
57
  dev = [
50
58
  "pytest>=8",
51
59
  "ruff>=0.6",
60
+ # the passkey extra's tests run its ceremonies with a software authenticator
61
+ "cryptography>=42",
52
62
  ]
53
63
 
54
64
  [tool.pytest.ini_options]