sessiontools 0.1.0__tar.gz → 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. sessiontools-0.2.0/PKG-INFO +166 -0
  2. sessiontools-0.2.0/README.md +150 -0
  3. {sessiontools-0.1.0 → sessiontools-0.2.0}/pyproject.toml +21 -16
  4. {sessiontools-0.1.0 → sessiontools-0.2.0}/src/sessiontools/__init__.py +18 -4
  5. sessiontools-0.2.0/src/sessiontools/account/__init__.py +15 -0
  6. sessiontools-0.2.0/src/sessiontools/account/cli.py +369 -0
  7. sessiontools-0.2.0/src/sessiontools/account/keychain.py +318 -0
  8. sessiontools-0.2.0/src/sessiontools/account/leakscan.py +190 -0
  9. sessiontools-0.2.0/src/sessiontools/account/limits.py +248 -0
  10. sessiontools-0.2.0/src/sessiontools/account/movehome.py +312 -0
  11. sessiontools-0.2.0/src/sessiontools/account/new.py +458 -0
  12. sessiontools-0.2.0/src/sessiontools/account/registry.py +589 -0
  13. sessiontools-0.2.0/src/sessiontools/account/setuptoken.py +1373 -0
  14. sessiontools-0.2.0/src/sessiontools/account/status.py +618 -0
  15. sessiontools-0.2.0/src/sessiontools/account/tokenfile.py +365 -0
  16. sessiontools-0.2.0/src/sessiontools/account/tokenstore.py +462 -0
  17. sessiontools-0.2.0/src/sessiontools/account/use.py +814 -0
  18. sessiontools-0.2.0/src/sessiontools/band.py +130 -0
  19. {sessiontools-0.1.0 → sessiontools-0.2.0}/src/sessiontools/busy.py +206 -63
  20. sessiontools-0.2.0/src/sessiontools/claude_code.py +457 -0
  21. sessiontools-0.2.0/src/sessiontools/cli.py +792 -0
  22. sessiontools-0.2.0/src/sessiontools/completion.py +400 -0
  23. sessiontools-0.2.0/src/sessiontools/context_parts/__init__.py +50 -0
  24. sessiontools-0.2.0/src/sessiontools/context_parts/boot.py +534 -0
  25. sessiontools-0.2.0/src/sessiontools/context_parts/breakdown.py +218 -0
  26. sessiontools-0.2.0/src/sessiontools/context_parts/hooks.py +269 -0
  27. sessiontools-0.2.0/src/sessiontools/context_parts/nnls.py +112 -0
  28. sessiontools-0.2.0/src/sessiontools/context_parts/render.py +478 -0
  29. sessiontools-0.2.0/src/sessiontools/context_parts/slash_context.py +137 -0
  30. sessiontools-0.2.0/src/sessiontools/context_parts/tools.py +118 -0
  31. sessiontools-0.2.0/src/sessiontools/context_parts/transcript.py +401 -0
  32. {sessiontools-0.1.0 → sessiontools-0.2.0}/src/sessiontools/get.py +6 -4
  33. sessiontools-0.2.0/src/sessiontools/ledger/__init__.py +338 -0
  34. sessiontools-0.2.0/src/sessiontools/ledger/_tiktoken_child.py +65 -0
  35. sessiontools-0.2.0/src/sessiontools/ledger/count.py +176 -0
  36. sessiontools-0.2.0/src/sessiontools/ledger/render.py +262 -0
  37. sessiontools-0.2.0/src/sessiontools/ledger/transcript.py +268 -0
  38. {sessiontools-0.1.0 → sessiontools-0.2.0}/src/sessiontools/listing.py +71 -18
  39. sessiontools-0.2.0/src/sessiontools/operator.py +156 -0
  40. sessiontools-0.2.0/src/sessiontools/pane_state.py +663 -0
  41. sessiontools-0.2.0/src/sessiontools/pane_state_agent.py +522 -0
  42. sessiontools-0.2.0/src/sessiontools/park.py +1359 -0
  43. {sessiontools-0.1.0 → sessiontools-0.2.0}/src/sessiontools/procs.py +46 -8
  44. sessiontools-0.2.0/src/sessiontools/reap.py +925 -0
  45. {sessiontools-0.1.0 → sessiontools-0.2.0}/src/sessiontools/send.py +2 -2
  46. sessiontools-0.2.0/src/sessiontools/settings.py +1506 -0
  47. {sessiontools-0.1.0 → sessiontools-0.2.0}/src/sessiontools/settle.py +3 -5
  48. sessiontools-0.2.0/src/sessiontools/snapshot.py +324 -0
  49. sessiontools-0.2.0/src/sessiontools/sound/__init__.py +117 -0
  50. sessiontools-0.2.0/src/sessiontools/sound/engine.swift +2020 -0
  51. sessiontools-0.2.0/src/sessiontools/sound/event.swift +248 -0
  52. sessiontools-0.2.0/src/sessiontools/sound/service.py +596 -0
  53. {sessiontools-0.1.0 → sessiontools-0.2.0}/src/sessiontools/start/__init__.py +9 -10
  54. {sessiontools-0.1.0 → sessiontools-0.2.0}/src/sessiontools/start/agentfile.py +44 -13
  55. {sessiontools-0.1.0 → sessiontools-0.2.0}/src/sessiontools/start/agents.py +10 -14
  56. {sessiontools-0.1.0 → sessiontools-0.2.0}/src/sessiontools/start/args.py +12 -12
  57. sessiontools-0.2.0/src/sessiontools/start/claude_settings.py +333 -0
  58. {sessiontools-0.1.0 → sessiontools-0.2.0}/src/sessiontools/start/context.py +74 -23
  59. {sessiontools-0.1.0 → sessiontools-0.2.0}/src/sessiontools/start/environment.py +128 -14
  60. {sessiontools-0.1.0 → sessiontools-0.2.0}/src/sessiontools/start/errors.py +2 -2
  61. {sessiontools-0.1.0 → sessiontools-0.2.0}/src/sessiontools/start/holders.py +6 -6
  62. {sessiontools-0.1.0 → sessiontools-0.2.0}/src/sessiontools/start/identity.py +83 -18
  63. {sessiontools-0.1.0 → sessiontools-0.2.0}/src/sessiontools/start/placement.py +19 -8
  64. {sessiontools-0.1.0 → sessiontools-0.2.0}/src/sessiontools/start/plan.py +300 -68
  65. {sessiontools-0.1.0 → sessiontools-0.2.0}/src/sessiontools/start/policy.py +59 -53
  66. {sessiontools-0.1.0 → sessiontools-0.2.0}/src/sessiontools/start/record.py +15 -16
  67. {sessiontools-0.1.0 → sessiontools-0.2.0}/src/sessiontools/start/resume.py +11 -11
  68. {sessiontools-0.1.0 → sessiontools-0.2.0}/src/sessiontools/start/run.py +26 -13
  69. {sessiontools-0.1.0 → sessiontools-0.2.0}/src/sessiontools/start/secrets.py +110 -4
  70. {sessiontools-0.1.0 → sessiontools-0.2.0}/src/sessiontools/start/vendor.py +19 -6
  71. sessiontools-0.2.0/src/sessiontools/statusline/__init__.py +1195 -0
  72. sessiontools-0.2.0/src/sessiontools/statusline/sample.json +20 -0
  73. sessiontools-0.2.0/src/sessiontools/statusline/statusline.sh +185 -0
  74. sessiontools-0.2.0/src/sessiontools/tmux.py +178 -0
  75. sessiontools-0.2.0/src/sessiontools/turn.py +191 -0
  76. sessiontools-0.2.0/src/sessiontools/verbs.py +67 -0
  77. {sessiontools-0.1.0 → sessiontools-0.2.0}/src/sessiontools/window.py +81 -14
  78. sessiontools-0.1.0/PKG-INFO +0 -11
  79. sessiontools-0.1.0/src/sessiontools/claude_code.py +0 -179
  80. sessiontools-0.1.0/src/sessiontools/cli.py +0 -347
  81. sessiontools-0.1.0/src/sessiontools/settings.py +0 -764
  82. sessiontools-0.1.0/src/sessiontools/tmux.py +0 -90
  83. {sessiontools-0.1.0 → sessiontools-0.2.0}/LICENSE +0 -0
  84. {sessiontools-0.1.0 → sessiontools-0.2.0}/src/sessiontools/py.typed +0 -0
@@ -0,0 +1,166 @@
1
+ Metadata-Version: 2.4
2
+ Name: sessiontools
3
+ Version: 0.2.0
4
+ Summary: The harness layer: sessions, status and idle, one driver per harness - a library first
5
+ Author: Mike Bailey
6
+ Author-email: Mike Bailey <mike@sessionkit.ai>
7
+ License-Expression: AGPL-3.0-or-later
8
+ License-File: LICENSE
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Requires-Dist: pyyaml>=6
11
+ Requires-Dist: jsonschema>=4
12
+ Requires-Python: >=3.11, <3.15
13
+ Project-URL: Homepage, https://github.com/sessionkit/sessiontools
14
+ Project-URL: Repository, https://github.com/sessionkit/sessiontools
15
+ Description-Content-Type: text/markdown
16
+
17
+ # sessiontools
18
+
19
+ `session`: one command for the coding-agent sessions on this machine.
20
+ Which are live, whether each is busy or idle, how full its context is,
21
+ and how to start one from an agent file. For anyone running several
22
+ Claude Code sessions side by side, and for the tools that watch them.
23
+
24
+ ## Install
25
+
26
+ ```console
27
+ uv tool install sessiontools # puts `session` on the PATH
28
+ ```
29
+
30
+ Python 3.11 to 3.14. Optional: [the Claude Code plugin][plugin] adds
31
+ the `session` skill and two hooks.
32
+
33
+ Shell completion, one line per shell ([shell completion][completion]):
34
+
35
+ ```console
36
+ eval "$(session completion zsh)" # zsh: in ~/.zshrc, after compinit
37
+ session completion bash > ~/.local/share/bash-completion/completions/session # bash with bash-completion 2
38
+ eval "$(session completion bash)" # bash 3.2 or any bash without it: in ~/.bashrc
39
+ ```
40
+
41
+ ## Quick start
42
+
43
+ ```console
44
+ session list # the live sessions: panes, state, context
45
+ session get state # this session: busy, idle with children, idle
46
+ session context # how full this session's context window is
47
+ session context --parts # what filled it: boot, then growth by category
48
+ session ledger --short # each file read and command run, by tokens
49
+ session account status # which Claude account this Mac is on
50
+ session start --list-agents # the agents it can start
51
+ session reap # seats idle past 1h: CLOSE or KEEP, and why (a dry run)
52
+ session --help # every verb
53
+ ```
54
+
55
+ ## Switching accounts
56
+
57
+ `session account use NAME` moves this Mac to another Claude account from
58
+ a token you already hold: no browser, no restart, and it never prints a
59
+ token. On a Keychain host it moves **every** seat, not one:
60
+
61
+ | route | moves | cache cost | reversible by | gate |
62
+ |---|---|---|---|---|
63
+ | `account use` (Keychain) | every seat on the Mac with no env token, within ~50 s | the sum of their contexts (2.07M / 1.10M measured) | `use` back, or restore from the backup | witness, `--yes`, preflight, backup |
64
+ | `account use` (token file) | no live seat; each one that relaunches from a shell that reads the file | none now; each seat's context when it restarts | `use` back, or restore from the backup | witness, `--yes`, preflight, backup |
65
+
66
+ A host whose shell exports `CLAUDE_CODE_OAUTH_TOKEN` from a file names it
67
+ in the `session` setting `account.token_file`, and `use` swaps the file.
68
+ Without `--yes`, `use` shows the plan and writes nothing. To add an
69
+ account, `session account new NAME --email E` signs in through `claude
70
+ setup-token`, saves the token to passage, reads it back and registers
71
+ it; the token is never shown. See [Switching Claude accounts][account].
72
+
73
+ ## Uninstall
74
+
75
+ ```console
76
+ uv tool uninstall sessiontools
77
+ ```
78
+
79
+ It leaves `~/.session/` (session dirs, the list cache) and
80
+ `~/.sessionkit/tools/settings/`; remove them by hand to leave nothing
81
+ behind.
82
+
83
+ ## Docs
84
+
85
+ - [The `session` verbs][verbs]: list, get, context, ledger, account,
86
+ settings, operator, reap
87
+ - [Starting a session][start]: agent files, flags, tmux, one holder
88
+ - [Switching Claude accounts][account]: `session account`, its blast
89
+ radius, and `new`, which adds an account
90
+ - [The `session list` cache][cache]: one computation, many readers
91
+ - [Operator and privileged seats][operator]: who seats ask
92
+ - [Closing idle seats][reap]: `session reap`, a dry run by default
93
+ - [Shell completion][completion]: `session completion bash|zsh`, a static
94
+ script built from the verbs' own parsers
95
+ - [The Claude Code plugin][plugin]: the skill and the hooks
96
+ - [The settle alert][settle]: one line past a context threshold
97
+ - [The busy sound][busy]: a sound while a tool batch runs long
98
+ - [The sound engine][engine]: the busy sound from one resident process
99
+ - [The status line][status-line]: `session statusline install` puts it in the
100
+ kit's claude-code layer, never `~/.claude`. `session start` seats show it;
101
+ a bare `claude` does not (`alias claude='session start -'`)
102
+ - [The pane signal][pane-state]: BUSY / FREE on each seat's tmux pane,
103
+ and `session pane-state agent`, the launchd agent that publishes it
104
+ - [The Python library][library]: `from sessiontools import sessions`
105
+ - [Building and testing][building]: make targets, specs, releases
106
+ - [CHANGELOG][changelog]; licence AGPL-3.0-or-later ([LICENSE][license])
107
+
108
+ ## Configuration
109
+
110
+ Nothing needs configuring: unset, every part uses its default. What can
111
+ be set, and where each one lives ([configuration][configuration]):
112
+
113
+ - **Settings files**, JSON in layers: `~/.sessionkit/tools/settings/session.json`
114
+ (the operator, the list cache, the pane signal, accounts, a session's
115
+ home), `~/.sessionkit/tools/settings/sounds.json` (the busy sound), and
116
+ `~/.sessionkit/tools/settings/claude-code.json` (the model, effort
117
+ and status line `session start` passes on). Every key, its default and
118
+ which layers it is read from: [settings][settings].
119
+ - **Folders of its own:** `~/.session/` (sessions, seats, agent files, the
120
+ state dir) and `~/.sessionkit/tools/accounts/` (`session account`).
121
+ - **Environment variables:** the settle alert's `SESSION_SETTLE_AT`, the
122
+ hooks' `SESSIONTOOLS_HOOK_*` switches, and the paths it reads, such as
123
+ `SESSIONS_DIR` and `SESSION_STATE_DIR`. The configuration page lists
124
+ each one with its default, under the part that reads it.
125
+
126
+ ## Logs
127
+
128
+ - **The sound engine:** `~/Library/Logs/sessiontools/sound-engine.log`,
129
+ once `session sound engine on` has run.
130
+ - **The pane signal's agent:** `~/Library/Logs/sessiontools/pane-state.log`,
131
+ once `session pane-state agent on` has run.
132
+ - **`session reap --yes`:** `~/.session/state/reap.log`, one line for each
133
+ seat it closed or failed to close.
134
+ - **Each session's settings at birth:**
135
+ `~/.session/sessions/<session-id>/log/settings.jsonl`, what `session
136
+ start` read into that session's settings: each environment variable
137
+ by name, never its value.
138
+ - **The status line:** `~/.config/session/statusline-log.jsonl`, one line
139
+ per render, only when `~/.config/session/` already exists.
140
+
141
+ Follow one as it grows with `tail -F`, for example
142
+ `tail -F ~/Library/Logs/sessiontools/pane-state.log`.
143
+
144
+ - **Health:** `session list` prints a row for each live session, with its
145
+ state and context. A session you know is running that is not listed is
146
+ one sessiontools cannot see.
147
+
148
+ [verbs]: docs/session-command-verbs.md
149
+ [start]: docs/session-start-launcher.md
150
+ [account]: docs/account.md
151
+ [cache]: docs/list-snapshot-cache.md
152
+ [operator]: docs/operator-privileged-seats.md
153
+ [reap]: docs/session-reap.md
154
+ [completion]: docs/shell-completion.md
155
+ [plugin]: docs/claude-code-plugin.md
156
+ [settle]: docs/settle-alert-hook.md
157
+ [busy]: docs/busy-sound-hook.md
158
+ [engine]: docs/sound-engine-agent.md
159
+ [status-line]: docs/status-line-script.md
160
+ [pane-state]: docs/pane-state-signal.md
161
+ [library]: docs/python-library-api.md
162
+ [building]: docs/building-and-testing.md
163
+ [changelog]: CHANGELOG.md
164
+ [license]: LICENSE
165
+ [configuration]: docs/configuration.md
166
+ [settings]: docs/settings.md
@@ -0,0 +1,150 @@
1
+ # sessiontools
2
+
3
+ `session`: one command for the coding-agent sessions on this machine.
4
+ Which are live, whether each is busy or idle, how full its context is,
5
+ and how to start one from an agent file. For anyone running several
6
+ Claude Code sessions side by side, and for the tools that watch them.
7
+
8
+ ## Install
9
+
10
+ ```console
11
+ uv tool install sessiontools # puts `session` on the PATH
12
+ ```
13
+
14
+ Python 3.11 to 3.14. Optional: [the Claude Code plugin][plugin] adds
15
+ the `session` skill and two hooks.
16
+
17
+ Shell completion, one line per shell ([shell completion][completion]):
18
+
19
+ ```console
20
+ eval "$(session completion zsh)" # zsh: in ~/.zshrc, after compinit
21
+ session completion bash > ~/.local/share/bash-completion/completions/session # bash with bash-completion 2
22
+ eval "$(session completion bash)" # bash 3.2 or any bash without it: in ~/.bashrc
23
+ ```
24
+
25
+ ## Quick start
26
+
27
+ ```console
28
+ session list # the live sessions: panes, state, context
29
+ session get state # this session: busy, idle with children, idle
30
+ session context # how full this session's context window is
31
+ session context --parts # what filled it: boot, then growth by category
32
+ session ledger --short # each file read and command run, by tokens
33
+ session account status # which Claude account this Mac is on
34
+ session start --list-agents # the agents it can start
35
+ session reap # seats idle past 1h: CLOSE or KEEP, and why (a dry run)
36
+ session --help # every verb
37
+ ```
38
+
39
+ ## Switching accounts
40
+
41
+ `session account use NAME` moves this Mac to another Claude account from
42
+ a token you already hold: no browser, no restart, and it never prints a
43
+ token. On a Keychain host it moves **every** seat, not one:
44
+
45
+ | route | moves | cache cost | reversible by | gate |
46
+ |---|---|---|---|---|
47
+ | `account use` (Keychain) | every seat on the Mac with no env token, within ~50 s | the sum of their contexts (2.07M / 1.10M measured) | `use` back, or restore from the backup | witness, `--yes`, preflight, backup |
48
+ | `account use` (token file) | no live seat; each one that relaunches from a shell that reads the file | none now; each seat's context when it restarts | `use` back, or restore from the backup | witness, `--yes`, preflight, backup |
49
+
50
+ A host whose shell exports `CLAUDE_CODE_OAUTH_TOKEN` from a file names it
51
+ in the `session` setting `account.token_file`, and `use` swaps the file.
52
+ Without `--yes`, `use` shows the plan and writes nothing. To add an
53
+ account, `session account new NAME --email E` signs in through `claude
54
+ setup-token`, saves the token to passage, reads it back and registers
55
+ it; the token is never shown. See [Switching Claude accounts][account].
56
+
57
+ ## Uninstall
58
+
59
+ ```console
60
+ uv tool uninstall sessiontools
61
+ ```
62
+
63
+ It leaves `~/.session/` (session dirs, the list cache) and
64
+ `~/.sessionkit/tools/settings/`; remove them by hand to leave nothing
65
+ behind.
66
+
67
+ ## Docs
68
+
69
+ - [The `session` verbs][verbs]: list, get, context, ledger, account,
70
+ settings, operator, reap
71
+ - [Starting a session][start]: agent files, flags, tmux, one holder
72
+ - [Switching Claude accounts][account]: `session account`, its blast
73
+ radius, and `new`, which adds an account
74
+ - [The `session list` cache][cache]: one computation, many readers
75
+ - [Operator and privileged seats][operator]: who seats ask
76
+ - [Closing idle seats][reap]: `session reap`, a dry run by default
77
+ - [Shell completion][completion]: `session completion bash|zsh`, a static
78
+ script built from the verbs' own parsers
79
+ - [The Claude Code plugin][plugin]: the skill and the hooks
80
+ - [The settle alert][settle]: one line past a context threshold
81
+ - [The busy sound][busy]: a sound while a tool batch runs long
82
+ - [The sound engine][engine]: the busy sound from one resident process
83
+ - [The status line][status-line]: `session statusline install` puts it in the
84
+ kit's claude-code layer, never `~/.claude`. `session start` seats show it;
85
+ a bare `claude` does not (`alias claude='session start -'`)
86
+ - [The pane signal][pane-state]: BUSY / FREE on each seat's tmux pane,
87
+ and `session pane-state agent`, the launchd agent that publishes it
88
+ - [The Python library][library]: `from sessiontools import sessions`
89
+ - [Building and testing][building]: make targets, specs, releases
90
+ - [CHANGELOG][changelog]; licence AGPL-3.0-or-later ([LICENSE][license])
91
+
92
+ ## Configuration
93
+
94
+ Nothing needs configuring: unset, every part uses its default. What can
95
+ be set, and where each one lives ([configuration][configuration]):
96
+
97
+ - **Settings files**, JSON in layers: `~/.sessionkit/tools/settings/session.json`
98
+ (the operator, the list cache, the pane signal, accounts, a session's
99
+ home), `~/.sessionkit/tools/settings/sounds.json` (the busy sound), and
100
+ `~/.sessionkit/tools/settings/claude-code.json` (the model, effort
101
+ and status line `session start` passes on). Every key, its default and
102
+ which layers it is read from: [settings][settings].
103
+ - **Folders of its own:** `~/.session/` (sessions, seats, agent files, the
104
+ state dir) and `~/.sessionkit/tools/accounts/` (`session account`).
105
+ - **Environment variables:** the settle alert's `SESSION_SETTLE_AT`, the
106
+ hooks' `SESSIONTOOLS_HOOK_*` switches, and the paths it reads, such as
107
+ `SESSIONS_DIR` and `SESSION_STATE_DIR`. The configuration page lists
108
+ each one with its default, under the part that reads it.
109
+
110
+ ## Logs
111
+
112
+ - **The sound engine:** `~/Library/Logs/sessiontools/sound-engine.log`,
113
+ once `session sound engine on` has run.
114
+ - **The pane signal's agent:** `~/Library/Logs/sessiontools/pane-state.log`,
115
+ once `session pane-state agent on` has run.
116
+ - **`session reap --yes`:** `~/.session/state/reap.log`, one line for each
117
+ seat it closed or failed to close.
118
+ - **Each session's settings at birth:**
119
+ `~/.session/sessions/<session-id>/log/settings.jsonl`, what `session
120
+ start` read into that session's settings: each environment variable
121
+ by name, never its value.
122
+ - **The status line:** `~/.config/session/statusline-log.jsonl`, one line
123
+ per render, only when `~/.config/session/` already exists.
124
+
125
+ Follow one as it grows with `tail -F`, for example
126
+ `tail -F ~/Library/Logs/sessiontools/pane-state.log`.
127
+
128
+ - **Health:** `session list` prints a row for each live session, with its
129
+ state and context. A session you know is running that is not listed is
130
+ one sessiontools cannot see.
131
+
132
+ [verbs]: docs/session-command-verbs.md
133
+ [start]: docs/session-start-launcher.md
134
+ [account]: docs/account.md
135
+ [cache]: docs/list-snapshot-cache.md
136
+ [operator]: docs/operator-privileged-seats.md
137
+ [reap]: docs/session-reap.md
138
+ [completion]: docs/shell-completion.md
139
+ [plugin]: docs/claude-code-plugin.md
140
+ [settle]: docs/settle-alert-hook.md
141
+ [busy]: docs/busy-sound-hook.md
142
+ [engine]: docs/sound-engine-agent.md
143
+ [status-line]: docs/status-line-script.md
144
+ [pane-state]: docs/pane-state-signal.md
145
+ [library]: docs/python-library-api.md
146
+ [building]: docs/building-and-testing.md
147
+ [changelog]: CHANGELOG.md
148
+ [license]: LICENSE
149
+ [configuration]: docs/configuration.md
150
+ [settings]: docs/settings.md
@@ -1,38 +1,43 @@
1
1
  [project]
2
2
  name = "sessiontools"
3
- version = "0.1.0"
3
+ version = "0.2.0"
4
4
  description = "The harness layer: sessions, status and idle, one driver per harness - a library first"
5
+ readme = "README.md"
5
6
  license = "AGPL-3.0-or-later"
6
7
  license-files = ["LICENSE"]
7
8
  authors = [
8
- { name = "Cora 7", email = "ai-cora@failmode.com" }
9
+ { name = "Mike Bailey", email = "mike@sessionkit.ai" }
10
+ ]
11
+ classifiers = [
12
+ "Development Status :: 3 - Alpha",
9
13
  ]
10
14
  # >=3.11, not the recipe's >=3.13: sessionmail (the first consumer) declares
11
15
  # >=3.11, and uv resolves for EVERY version a project allows, so a stricter
12
- # floor here made sessionmail's `uv sync` unsatisfiable (Pip, 13:02 Thu
13
- # 2026-09-17). Measured: the suite passes on 3.11, 3.12 and 3.13; nothing in
14
- # the tree needs 3.13.
15
- requires-python = ">=3.11"
16
- # ONE runtime dependency, and only for `session start`: agent front matter
17
- # is YAML (the same YAML Claude Code reads itself). Mike, voice 00:12 Tue
18
- # 2026-09-29, asked "Can start pull in the YAML library, just for itself?":
19
- # "Um, yes." So PyYAML is declared here and imported by exactly one module,
16
+ # floor here made sessionmail's `uv sync` unsatisfiable.
17
+ # Measured: the suite passes on 3.11, 3.12 and 3.13; nothing in
18
+ # the tree needs 3.13. The ceiling, <3.15, makes 3.14 the newest supported
19
+ # version.
20
+ requires-python = ">=3.11,<3.15"
21
+ # TWO runtime dependencies. The FIRST, PyYAML, for agent front matter, which
22
+ # is YAML (the same YAML Claude Code reads itself), and `session start`
23
+ # may pull in the YAML library for itself alone. So PyYAML is declared here and imported by exactly one module,
20
24
  # `sessiontools.start.agentfile`; `import sessiontools` (the library
21
25
  # sessionmail depends on) still imports nothing outside the standard library.
22
26
  # tests/test_cli.py pins both halves.
23
27
  # The SECOND: jsonschema, for `session settings` alone - each tool ships a
24
28
  # JSON Schema and the reader checks the merged result against it. No
25
- # configuration library for the layering (Mike, voice 19:15 Sat 2026-10-03,
26
- # Cora /RULINGS 4600); imported inside `sessiontools.settings.check_schema`,
29
+ # configuration library for the layering, by design; imported inside `sessiontools.settings.check_schema`,
27
30
  # so `import sessiontools` still reaches nothing outside the standard library.
28
31
  dependencies = ["PyYAML>=6", "jsonschema>=4"]
29
32
 
30
- # THE `session` COMMAND - ruled at the cutover. Mike, voice 23:25-23:28 Mon
31
- # 2026-09-28, the session repo just moved aside: sessiontools provides it
32
- # ("Ah, yes, it should"), same verbs, ported as package code ("port it
33
- # nicely"), superseding his 12:18 Thu 2026-09-17 "not on our path today".
33
+ # THE `session` COMMAND - settled at the cutover, when the session repo moved
34
+ # aside: sessiontools provides it, same verbs, ported as package code.
34
35
  # Exactly one package owns `session` on the PATH; from here it is this one.
35
36
  # argparse and the library; PyYAML for `session start` alone (above).
37
+ [project.urls]
38
+ Homepage = "https://github.com/sessionkit/sessiontools"
39
+ Repository = "https://github.com/sessionkit/sessiontools"
40
+
36
41
  [project.scripts]
37
42
  session = "sessiontools.cli:main"
38
43
 
@@ -1,16 +1,19 @@
1
1
  """sessiontools - the harness layer: sessions, their status, and how long
2
2
  they have been idle - one driver per harness, a library first.
3
3
 
4
- Import it, or use the command it ships: `session` (Mike, voice 23:25-23:28
5
- Mon 2026-09-28, when the session repo was retired). `session list` and
4
+ Import it, or use the command it ships: `session` (since
5
+ 2030-07-29, when the session repo was retired). `session list` and
6
6
  `session get` are built on the functions below; `session start` is its own
7
- package, `sessiontools.start`; `session send` is disabled (2026-09-29).
7
+ package, `sessiontools.start`; `session send` is disabled (2030-07-30).
8
8
 
9
9
  from sessiontools import sessions, live, find, idle_seconds
10
10
  from sessiontools import session_id, current, SESSION_ID_VARS
11
+ from sessiontools import read_operator, Operator # who asks, who is privileged
11
12
 
12
13
  Every function speaks OUR words - busy, not busy, unknown - never a
13
- harness's. The first driver is `claude_code`; the day a harness changes a
14
+ harness's. `Session.state` is one of three: `busy`, `idle with children`
15
+ (the turn is over, a background agent runs) or `idle`. The first driver is
16
+ `claude_code`; the day a harness changes a
14
17
  status word, that driver changes and nothing above it does.
15
18
  """
16
19
 
@@ -19,8 +22,12 @@ from __future__ import annotations
19
22
  from importlib.metadata import PackageNotFoundError, version
20
23
 
21
24
  from sessiontools.claude_code import (
25
+ BUSY,
26
+ IDLE,
27
+ IDLE_WITH_CHILDREN,
22
28
  SESSION_ID_VARS,
23
29
  SIDECAR_DIR_ENV,
30
+ STATES,
24
31
  Session,
25
32
  current,
26
33
  find,
@@ -30,6 +37,7 @@ from sessiontools.claude_code import (
30
37
  sessions,
31
38
  sidecar_dir,
32
39
  )
40
+ from sessiontools.operator import Operator, read_operator
33
41
 
34
42
  try:
35
43
  __version__ = version("sessiontools")
@@ -37,14 +45,20 @@ except PackageNotFoundError: # a checkout that is not installed
37
45
  __version__ = "0+unknown"
38
46
 
39
47
  __all__ = [
48
+ "BUSY",
49
+ "IDLE",
50
+ "IDLE_WITH_CHILDREN",
40
51
  "SESSION_ID_VARS",
41
52
  "SIDECAR_DIR_ENV",
53
+ "STATES",
54
+ "Operator",
42
55
  "Session",
43
56
  "__version__",
44
57
  "current",
45
58
  "find",
46
59
  "idle_seconds",
47
60
  "live",
61
+ "read_operator",
48
62
  "session_id",
49
63
  "sessions",
50
64
  "sidecar_dir",
@@ -0,0 +1,15 @@
1
+ """`session account`: which of the user's Claude accounts the host is on, and
2
+ the switch between them.
3
+
4
+ session account list | status | use NAME | add NAME | remove NAME
5
+
6
+ `main(argv)` is the group (`cli`). The pieces are each their own module:
7
+ the registry of names (`registry`), the Keychain seam (`keychain`), `use`
8
+ (`use`), `status` and `list` (`status`), `add`/`remove` and the argparse
9
+ group (`cli`), and the token-leak scan (`leakscan`). Nothing here prints,
10
+ logs or stores a token.
11
+ """
12
+
13
+ from sessiontools.account.cli import main
14
+
15
+ __all__ = ["main"]