hatcheck 0.2.0__tar.gz → 0.3.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.
- {hatcheck-0.2.0 → hatcheck-0.3.0}/Cargo.lock +1 -67
- {hatcheck-0.2.0 → hatcheck-0.3.0}/Cargo.toml +1 -1
- {hatcheck-0.2.0 → hatcheck-0.3.0}/PKG-INFO +239 -65
- {hatcheck-0.2.0 → hatcheck-0.3.0}/README.md +238 -64
- {hatcheck-0.2.0 → hatcheck-0.3.0}/crates/hatcheck/Cargo.toml +15 -1
- hatcheck-0.3.0/crates/hatcheck/LICENSE +21 -0
- hatcheck-0.3.0/crates/hatcheck/README.md +56 -0
- {hatcheck-0.2.0 → hatcheck-0.3.0}/crates/hatcheck/src/args.rs +22 -0
- {hatcheck-0.2.0 → hatcheck-0.3.0}/crates/hatcheck/src/best.rs +261 -36
- {hatcheck-0.2.0 → hatcheck-0.3.0}/crates/hatcheck/src/bind.rs +1 -1
- {hatcheck-0.2.0 → hatcheck-0.3.0}/crates/hatcheck/src/cli.rs +89 -16
- {hatcheck-0.2.0 → hatcheck-0.3.0}/crates/hatcheck/src/lib.rs +4 -0
- {hatcheck-0.2.0 → hatcheck-0.3.0}/crates/hatcheck/src/move_cmd.rs +168 -169
- {hatcheck-0.2.0 → hatcheck-0.3.0}/crates/hatcheck/src/ospath.rs +2 -1
- hatcheck-0.3.0/crates/hatcheck/src/relocate.rs +815 -0
- {hatcheck-0.2.0 → hatcheck-0.3.0}/crates/hatcheck/src/usage.rs +296 -117
- {hatcheck-0.2.0 → hatcheck-0.3.0}/LICENSE +0 -0
- {hatcheck-0.2.0 → hatcheck-0.3.0}/crates/hatcheck/src/bin/cl.rs +0 -0
- {hatcheck-0.2.0 → hatcheck-0.3.0}/crates/hatcheck/src/bin/claude-k.rs +0 -0
- {hatcheck-0.2.0 → hatcheck-0.3.0}/crates/hatcheck/src/bin/claude-z.rs +0 -0
- {hatcheck-0.2.0 → hatcheck-0.3.0}/crates/hatcheck/src/bin/cx.rs +0 -0
- {hatcheck-0.2.0 → hatcheck-0.3.0}/crates/hatcheck/src/bin/hat.rs +0 -0
- {hatcheck-0.2.0 → hatcheck-0.3.0}/crates/hatcheck/src/conv.rs +0 -0
- {hatcheck-0.2.0 → hatcheck-0.3.0}/crates/hatcheck/src/desktop.rs +0 -0
- {hatcheck-0.2.0 → hatcheck-0.3.0}/crates/hatcheck/src/facts.rs +0 -0
- {hatcheck-0.2.0 → hatcheck-0.3.0}/crates/hatcheck/src/find.rs +0 -0
- {hatcheck-0.2.0 → hatcheck-0.3.0}/crates/hatcheck/src/launch.rs +0 -0
- {hatcheck-0.2.0 → hatcheck-0.3.0}/crates/hatcheck/src/main.rs +0 -0
- {hatcheck-0.2.0 → hatcheck-0.3.0}/crates/hatcheck/src/open_cmd.rs +0 -0
- {hatcheck-0.2.0 → hatcheck-0.3.0}/crates/hatcheck/src/out.rs +0 -0
- {hatcheck-0.2.0 → hatcheck-0.3.0}/crates/hatcheck/src/paths.rs +0 -0
- {hatcheck-0.2.0 → hatcheck-0.3.0}/crates/hatcheck/src/provider.rs +0 -0
- {hatcheck-0.2.0 → hatcheck-0.3.0}/crates/hatcheck/src/py.rs +0 -0
- {hatcheck-0.2.0 → hatcheck-0.3.0}/crates/hatcheck/src/serve.rs +0 -0
- {hatcheck-0.2.0 → hatcheck-0.3.0}/crates/hatcheck/src/sessions.rs +0 -0
- {hatcheck-0.2.0 → hatcheck-0.3.0}/crates/hatcheck/src/show.rs +0 -0
- {hatcheck-0.2.0 → hatcheck-0.3.0}/crates/hatcheck/src/times.rs +0 -0
- {hatcheck-0.2.0 → hatcheck-0.3.0}/crates/hatcheck/src/where_cmd.rs +0 -0
- {hatcheck-0.2.0 → hatcheck-0.3.0}/crates/hatcheck/src/widths.rs +0 -0
- {hatcheck-0.2.0 → hatcheck-0.3.0}/pyproject.toml +0 -0
|
@@ -41,15 +41,6 @@ version = "2.13.2"
|
|
|
41
41
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
42
42
|
checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06"
|
|
43
43
|
|
|
44
|
-
[[package]]
|
|
45
|
-
name = "block-buffer"
|
|
46
|
-
version = "0.10.4"
|
|
47
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
48
|
-
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
|
49
|
-
dependencies = [
|
|
50
|
-
"generic-array",
|
|
51
|
-
]
|
|
52
|
-
|
|
53
44
|
[[package]]
|
|
54
45
|
name = "bumpalo"
|
|
55
46
|
version = "3.20.3"
|
|
@@ -124,15 +115,6 @@ version = "0.8.7"
|
|
|
124
115
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
125
116
|
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
|
126
117
|
|
|
127
|
-
[[package]]
|
|
128
|
-
name = "cpufeatures"
|
|
129
|
-
version = "0.2.17"
|
|
130
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
131
|
-
checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
|
|
132
|
-
dependencies = [
|
|
133
|
-
"libc",
|
|
134
|
-
]
|
|
135
|
-
|
|
136
118
|
[[package]]
|
|
137
119
|
name = "crc32fast"
|
|
138
120
|
version = "1.5.2"
|
|
@@ -142,32 +124,12 @@ dependencies = [
|
|
|
142
124
|
"cfg-if",
|
|
143
125
|
]
|
|
144
126
|
|
|
145
|
-
[[package]]
|
|
146
|
-
name = "crypto-common"
|
|
147
|
-
version = "0.1.7"
|
|
148
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
149
|
-
checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
|
|
150
|
-
dependencies = [
|
|
151
|
-
"generic-array",
|
|
152
|
-
"typenum",
|
|
153
|
-
]
|
|
154
|
-
|
|
155
127
|
[[package]]
|
|
156
128
|
name = "deranged"
|
|
157
129
|
version = "0.5.9"
|
|
158
130
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
159
131
|
checksum = "9e9de72ce2ad1f90dc62fa25f0f430ef85eb4b0d8fa0be4f30373bc40a21d28e"
|
|
160
132
|
|
|
161
|
-
[[package]]
|
|
162
|
-
name = "digest"
|
|
163
|
-
version = "0.10.7"
|
|
164
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
165
|
-
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
|
166
|
-
dependencies = [
|
|
167
|
-
"block-buffer",
|
|
168
|
-
"crypto-common",
|
|
169
|
-
]
|
|
170
|
-
|
|
171
133
|
[[package]]
|
|
172
134
|
name = "displaydoc"
|
|
173
135
|
version = "0.2.7"
|
|
@@ -269,16 +231,6 @@ dependencies = [
|
|
|
269
231
|
"slab",
|
|
270
232
|
]
|
|
271
233
|
|
|
272
|
-
[[package]]
|
|
273
|
-
name = "generic-array"
|
|
274
|
-
version = "0.14.7"
|
|
275
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
276
|
-
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
|
277
|
-
dependencies = [
|
|
278
|
-
"typenum",
|
|
279
|
-
"version_check",
|
|
280
|
-
]
|
|
281
|
-
|
|
282
234
|
[[package]]
|
|
283
235
|
name = "getrandom"
|
|
284
236
|
version = "0.2.17"
|
|
@@ -310,7 +262,7 @@ checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
|
|
|
310
262
|
|
|
311
263
|
[[package]]
|
|
312
264
|
name = "hatcheck"
|
|
313
|
-
version = "0.
|
|
265
|
+
version = "0.3.0"
|
|
314
266
|
dependencies = [
|
|
315
267
|
"base64 0.22.1",
|
|
316
268
|
"chrono",
|
|
@@ -322,7 +274,6 @@ dependencies = [
|
|
|
322
274
|
"png",
|
|
323
275
|
"serde",
|
|
324
276
|
"serde_json",
|
|
325
|
-
"sha2",
|
|
326
277
|
"terminal_size",
|
|
327
278
|
"ureq",
|
|
328
279
|
"windows-sys 0.59.0",
|
|
@@ -784,17 +735,6 @@ dependencies = [
|
|
|
784
735
|
"zmij",
|
|
785
736
|
]
|
|
786
737
|
|
|
787
|
-
[[package]]
|
|
788
|
-
name = "sha2"
|
|
789
|
-
version = "0.10.9"
|
|
790
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
791
|
-
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
|
|
792
|
-
dependencies = [
|
|
793
|
-
"cfg-if",
|
|
794
|
-
"cpufeatures",
|
|
795
|
-
"digest",
|
|
796
|
-
]
|
|
797
|
-
|
|
798
738
|
[[package]]
|
|
799
739
|
name = "shlex"
|
|
800
740
|
version = "2.0.1"
|
|
@@ -914,12 +854,6 @@ dependencies = [
|
|
|
914
854
|
"zerovec",
|
|
915
855
|
]
|
|
916
856
|
|
|
917
|
-
[[package]]
|
|
918
|
-
name = "typenum"
|
|
919
|
-
version = "1.20.1"
|
|
920
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
921
|
-
checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20"
|
|
922
|
-
|
|
923
857
|
[[package]]
|
|
924
858
|
name = "unicode-ident"
|
|
925
859
|
version = "1.0.27"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hatcheck
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Classifier: Development Status :: 4 - Beta
|
|
5
5
|
Classifier: Environment :: Console
|
|
6
6
|
Classifier: Intended Audience :: Developers
|
|
@@ -52,12 +52,21 @@ keeping one profile per account: `cl` and `cx` run Claude Code and Codex with a
|
|
|
52
52
|
`hatcheck` lists the recent sessions in all of them, with the command that resumes each one and
|
|
53
53
|
what's left of each plan. `hatcheck usage` shows the plans, `hatcheck best` says which account to use
|
|
54
54
|
now, `hatcheck where` finds a session, `hatcheck open` resumes one in a new terminal, and
|
|
55
|
-
`hatcheck move` carries one over to another profile, or converts it between Claude Code and Codex
|
|
56
|
-
`hatcheck
|
|
57
|
-
|
|
55
|
+
`hatcheck move` carries one over to another profile, or converts it between Claude Code and Codex,
|
|
56
|
+
and `hatcheck fork` brings one in there as a new session, keeping the original.
|
|
57
|
+
`hatcheck relocate` brings a moved project folder's sessions along, `hatcheck bind` ties a folder
|
|
58
|
+
to a profile, so `cl` and `cx` pick it there, and `--json` gives the sessions and plans to scripts
|
|
59
|
+
and status bars. `claude-z` and `claude-k` run Claude Code on Z.ai's
|
|
58
60
|
GLM or Kimi's models instead, in any profile. See
|
|
59
61
|
[Claude Code and Codex CLI profiles](#claude-code-and-codex-cli-profiles).
|
|
60
62
|
|
|
63
|
+
**Not a gateway.** Hatcheck is never between an agent and its model. It rewrites no agent's
|
|
64
|
+
config, holds no login, and runs nothing in the background. Tools such as
|
|
65
|
+
[magpie](https://github.com/yetone/magpie) put a local gateway in that path so any agent can use
|
|
66
|
+
any model and accounts can take over from each other when a quota runs out. If that is what you
|
|
67
|
+
want, use one of those. Hatcheck is for the opposite case: keeping a work account and a personal
|
|
68
|
+
account apart, and knowing which one each session ran on. See [Rules it keeps](#rules-it-keeps).
|
|
69
|
+
|
|
61
70
|
| | macOS | Linux | Windows |
|
|
62
71
|
|---------------------------------|:-----:|:-----:|:-------:|
|
|
63
72
|
| Claude Desktop instances | yes | no official Desktop app | [planned](#roadmap) |
|
|
@@ -350,6 +359,11 @@ which is listed too. Codex files its sessions by the date they started, archived
|
|
|
350
359
|
`hat` is the short name: `hat`, `hat usage`, `hat move …` and so on work the same. `hat check` is the name
|
|
351
360
|
in two words, so it's `hat` again: `hat check` lists sessions and `hat check usage` is `hat usage`.
|
|
352
361
|
|
|
362
|
+
A subcommand can be cut to its first letters, after `hat` or `hatcheck`: `hat m …` is `hat move …`
|
|
363
|
+
and `hat f …` is `hat fork …`. Where two share a letter, it goes to the one used more: `b` is
|
|
364
|
+
`best`, `s` is `show` and `u` is `usage`, so `bind` and `unbind` take two letters, `bi` and `un`.
|
|
365
|
+
What it prints, and the commands it suggests, use the whole name.
|
|
366
|
+
|
|
353
367
|
Lists the Claude Code sessions from every `~/.claude*` profile, and the Codex sessions from every
|
|
354
368
|
`~/.codex*` home, that were active in the last 24 hours or are still open, grouped by folder and
|
|
355
369
|
newest first. Run from a folder that has sessions, it lists
|
|
@@ -377,7 +391,7 @@ cd ~/notes
|
|
|
377
391
|
9h Write release notes · main
|
|
378
392
|
cl work --resume 7e8f9a0b-1c2d-4e3f-8a4b-5c6d7e8f9a0b
|
|
379
393
|
Profiles: ~/.claude (1), ~/.claude-personal (1), ~/.claude-work (4)
|
|
380
|
-
Usage from Claude Code's last snapshot (
|
|
394
|
+
Usage from Claude Code's last snapshot (Claude Code's /usage couldn't fetch new numbers; offline, or rate limited?): ~/.claude-personal 9h ago
|
|
381
395
|
```
|
|
382
396
|
|
|
383
397
|
- Run the folder's `cd` line, then the session's command. Sessions still open in a terminal are
|
|
@@ -403,8 +417,11 @@ Usage from Claude Code's last snapshot (token expired; run claude in this profil
|
|
|
403
417
|
like Desktop ones, and Codex's own approval reviews aren't listed.
|
|
404
418
|
- Since the usage is a shell comment, pasting the whole line runs just the command (zsh needs
|
|
405
419
|
`setopt interactivecomments`).
|
|
406
|
-
- Usage is fetched live
|
|
407
|
-
|
|
420
|
+
- Usage is fetched live: Claude Code's `/usage` is run once per account, in its profile, and the
|
|
421
|
+
snapshot it saves is read (see [`hatcheck usage`](#hatcheck-usage-plan-usage-for-every-profile)
|
|
422
|
+
below); ChatGPT's usage endpoint is asked once per Codex account. When that gives nothing new
|
|
423
|
+
(offline, not signed in, rate limited), the last saved snapshot is used instead and named at the
|
|
424
|
+
bottom with its age.
|
|
408
425
|
- A session that ran in a folder [bound](#hatcheck-bind-tie-a-folder-to-a-profile) to another
|
|
409
426
|
profile is marked `⚠ folder bound to ~/.claude-work`, so it's easy to spot and `hatcheck move`.
|
|
410
427
|
- What it reads from each session file is cached, in `sessions.json` in `~/Library/Caches/hatcheck`
|
|
@@ -436,7 +453,7 @@ Sorted by Fable: those with some left first, the soonest reset on top; then thos
|
|
|
436
453
|
~/.claude pro · live
|
|
437
454
|
session (5h) 62% ██████▎░░░ █████▍░░░░ resets 5:01pm (in 2h41m)
|
|
438
455
|
week (all models) 91% █████████▏ ████▍░░░░░ resets Sat 4:20pm (in 3d2h)
|
|
439
|
-
~/.claude-personal pro · cached 9h00m ago (
|
|
456
|
+
~/.claude-personal pro · cached 9h00m ago (Claude Code's /usage couldn't fetch new numbers; offline, or rate limited?)
|
|
440
457
|
session (5h) ? ·········· reset 10:20am, after this snapshot
|
|
441
458
|
week (all models) 97% █████████▊ ███████▎░░ resets Mon 4:20pm (in 5d2h)
|
|
442
459
|
~/.codex-work ChatGPT plus · live
|
|
@@ -446,19 +463,26 @@ Sorted by Fable: those with some left first, the soonest reset on top; then thos
|
|
|
446
463
|
|
|
447
464
|
- Accounts are sorted by their Fable limit. First come those with some Fable left, the soonest
|
|
448
465
|
Fable reset on top: what's left there goes unused once it resets, so that's the one to use first.
|
|
449
|
-
|
|
450
|
-
too, the
|
|
451
|
-
|
|
466
|
+
An account past 90% of its Fable limit goes behind the fresher ones, and past 98% behind those
|
|
467
|
+
too: nearly out, it's the one to use last. Next come those out of Fable, or out of the weekly
|
|
468
|
+
limit for all models, which Fable counts against too, the soonest back on top. Then come accounts
|
|
469
|
+
without a Fable limit, such as Pro plans, and Codex homes. A snapshot saved before its Fable limit
|
|
470
|
+
reset counts as full until the reset after.
|
|
452
471
|
- Each limit has two bars: what's left of it, then how much of its window, 5 hours or a week, is
|
|
453
472
|
left before it resets. In a terminal the second goes from blue with most of the window to go,
|
|
454
473
|
through gold and orange, to red as the reset nears. When the first bar is shorter than the
|
|
455
474
|
second, as for `Fable` here, the limit is being used up faster than its window runs out. A limit
|
|
456
475
|
without a reset time, like an unused 5-hour session, has no time bar.
|
|
457
|
-
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
476
|
+
- A Claude Code account's numbers come from Claude Code itself: `claude -p /usage` is run in the
|
|
477
|
+
profile, with no tools, MCP servers, settings or transcript, which asks Anthropic with the
|
|
478
|
+
profile's own login and saves the answer in the profile's `.claude.json`; that snapshot is what's
|
|
479
|
+
shown. hatcheck never reads a login: the plan's name comes from the account details Claude Code
|
|
480
|
+
keeps beside the snapshot. The runs take about a second each, in parallel, from a folder of
|
|
481
|
+
hatcheck's own (`claude-usage` in its cache folder), so the one empty project folder Claude Code
|
|
482
|
+
makes for the folder it runs in is the same every time.
|
|
483
|
+
- When that gives nothing new (`claude` not on the `PATH`, the profile not signed in, offline, or
|
|
484
|
+
Anthropic rate-limiting the account), Claude Code's last saved snapshot is shown with its age and
|
|
485
|
+
the reason.
|
|
462
486
|
- Profiles signed in to the same account are shown together. Per-model limits such as
|
|
463
487
|
`week (Fable)` are named in violet, with their bar drawn in it, to tell them from `week (all
|
|
464
488
|
models)`; the % keeps the severity's colour. Quota fields the server
|
|
@@ -476,18 +500,19 @@ Sorted by Fable: those with some left first, the soonest reset on top; then thos
|
|
|
476
500
|
|
|
477
501
|
### `hatcheck move`: carry on a session with another profile
|
|
478
502
|
|
|
479
|
-
When one account runs low, continue a session on another profile, or in the other agent. It
|
|
480
|
-
the session
|
|
503
|
+
When one account runs low, continue a session on another profile, or in the other agent. It moves
|
|
504
|
+
the session: the original is deleted once every copied file is checked against it, and an older
|
|
505
|
+
copy never replaces a newer one. `--keep` keeps the original, which copies it instead.
|
|
481
506
|
|
|
482
507
|
```
|
|
483
508
|
$ hatcheck move 9a8b7c6d work
|
|
484
|
-
|
|
509
|
+
Moved session 9a8b7c6d "Add rate limiting to the login endpoint" from ~/.claude to ~/.claude-work:
|
|
485
510
|
transcript 53.0 KB
|
|
486
511
|
subagents and tool output 3 files
|
|
487
512
|
/rewind file snapshots 4 files
|
|
488
513
|
plan quiet-river-plan.md
|
|
489
514
|
Paths in the conversation to these files now point to the copies.
|
|
490
|
-
|
|
515
|
+
Deleted the original from ~/.claude; the plan file stays, since sessions can share one.
|
|
491
516
|
Resume it with:
|
|
492
517
|
cd ~/code/api
|
|
493
518
|
cl work --resume 9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d
|
|
@@ -495,9 +520,9 @@ Resume it now in ~/.claude-work? [y/N]
|
|
|
495
520
|
```
|
|
496
521
|
|
|
497
522
|
- It copies the transcript, the folder of subagent transcripts and saved tool output, the `/rewind`
|
|
498
|
-
file snapshots and the plan file, keeping their timestamps, and checks every copied file
|
|
499
|
-
the conversation that point at those files are changed to point at the
|
|
500
|
-
Claude's thinking, whose signatures would stop matching.
|
|
523
|
+
file snapshots and the plan file, keeping their timestamps, and checks every copied file before it
|
|
524
|
+
deletes anything. Paths in the conversation that point at those files are changed to point at the
|
|
525
|
+
copies, except inside Claude's thinking, whose signatures would stop matching.
|
|
501
526
|
- A session that's open in a terminal is refused: quit it first, so it stops changing.
|
|
502
527
|
`hatcheck` marks those `● open`.
|
|
503
528
|
- Resume it with the printed command, from the directory it ran in, or answer `y` when it asks and
|
|
@@ -506,38 +531,51 @@ Resume it now in ~/.claude-work? [y/N]
|
|
|
506
531
|
permissions, MCP servers, plugins and project memory are the new profile's. If the new account
|
|
507
532
|
rejects the signatures on earlier thinking, Claude Code drops those thinking blocks and carries
|
|
508
533
|
on.
|
|
509
|
-
-
|
|
534
|
+
- The plan file stays in the old profile, since sessions can share one.
|
|
510
535
|
- If the session's last reply came from Z.ai or Kimi, it also prints the `cl -z` or `cl -k` command
|
|
511
536
|
that carries on there instead of on the new profile's Claude plan.
|
|
512
537
|
|
|
513
538
|
#### When the profile already has a copy
|
|
514
539
|
|
|
515
|
-
A session copied to another profile and carried on there can be moved back: the copy
|
|
516
|
-
behind is an older version of it. The two copies are compared line by line:
|
|
540
|
+
A session copied to another profile with `--keep` and carried on there can be moved back: the copy
|
|
541
|
+
it left behind is an older version of it. The two copies are compared line by line:
|
|
517
542
|
|
|
518
543
|
- **The copy there is older**, because the session went on from it: it's brought up to date, and
|
|
519
544
|
each item shows `(updated an older copy)`. Nothing is lost, since the copy being moved starts with
|
|
520
545
|
all of it.
|
|
521
|
-
- **The copy there is newer**, because the session went on there:
|
|
522
|
-
|
|
523
|
-
|
|
546
|
+
- **The copy there is newer**, because the session went on there: it stops and changes nothing,
|
|
547
|
+
since putting this copy there would lose what came after. It prints the command that resumes the
|
|
548
|
+
session there, and the files of the older copy here, to delete if you don't want them.
|
|
549
|
+
- **Both went on** after the copy was made: nothing is moved, since that would lose the prompts
|
|
524
550
|
only the copy there has. It says when they split and how many prompts each has had since.
|
|
525
|
-
|
|
526
|
-
|
|
551
|
+
[`hatcheck fork`](#hatcheck-fork-a-session-as-a-new-one-in-another-profile) brings this one in
|
|
552
|
+
as a new session with its own ID and keeps both. Or delete the copy there first.
|
|
553
|
+
|
|
554
|
+
```
|
|
555
|
+
$ hatcheck move 9a8b7c6d work
|
|
556
|
+
~/.claude-work already has session 9a8b7c6d "Add rate limiting to the login endpoint", with everything in this copy and more: the session went on there. This copy is older, so nothing was moved.
|
|
557
|
+
Resume it there with:
|
|
558
|
+
cd ~/code/api
|
|
559
|
+
cl work --resume 9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d
|
|
560
|
+
To drop the older copy in ~/.claude, delete:
|
|
561
|
+
~/.claude/projects/-Users-me-code-api/9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d.jsonl
|
|
562
|
+
~/.claude/projects/-Users-me-code-api/9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d
|
|
563
|
+
~/.claude/file-history/9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d
|
|
564
|
+
```
|
|
527
565
|
|
|
528
566
|
```
|
|
529
567
|
$ hatcheck move 9a8b7c6d default
|
|
530
|
-
Session 9a8b7c6d went on in both ~/.claude-work and ~/.claude after Oct 15 01:40: 3 new prompts in ~/.claude-work, 1 in ~/.claude.
|
|
568
|
+
Session 9a8b7c6d went on in both ~/.claude-work and ~/.claude after Oct 15 01:40: 3 new prompts in ~/.claude-work, 1 in ~/.claude. Moving this one over would lose what's only in ~/.claude, so nothing was moved.
|
|
531
569
|
To keep both, bring this one in as a new session with its own ID:
|
|
532
|
-
hatcheck
|
|
570
|
+
hatcheck fork 9a8b7c6d default
|
|
533
571
|
Or delete the copy in ~/.claude first, to replace it:
|
|
534
572
|
~/.claude/projects/-Users-me-code-api/9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d.jsonl
|
|
573
|
+
~/.claude/projects/-Users-me-code-api/9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d
|
|
574
|
+
~/.claude/file-history/9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d
|
|
535
575
|
```
|
|
536
576
|
|
|
537
|
-
A
|
|
538
|
-
|
|
539
|
-
Resuming a fork, a round trip and a copy that went on in both profiles were tested with the real
|
|
540
|
-
`claude` (2.1.301).
|
|
577
|
+
A round trip and a copy that went on in both profiles were tested with the real `claude`
|
|
578
|
+
(2.1.301).
|
|
541
579
|
|
|
542
580
|
When more than one profile has the session, you're asked which copy to take. The one used last
|
|
543
581
|
comes first and is the default, and each other one says how it stands to it:
|
|
@@ -565,7 +603,7 @@ Converted Codex session 019a8c1e "Add retries to the uploader" from ~/.codex-wor
|
|
|
565
603
|
tool calls 191, as text with their output shortened
|
|
566
604
|
left out Codex's reasoning, images, goals and subagent sessions
|
|
567
605
|
new session 6f6749d7-0f59-4683-997c-a3595421b93f (241.9 KB)
|
|
568
|
-
The original stays in ~/.codex-work.
|
|
606
|
+
The original stays in ~/.codex-work, since a conversion leaves things out.
|
|
569
607
|
Resume it with:
|
|
570
608
|
cd ~/code/api
|
|
571
609
|
cl work --resume 6f6749d7-0f59-4683-997c-a3595421b93f
|
|
@@ -573,9 +611,8 @@ Resume it now in ~/.claude-work? [y/N]
|
|
|
573
611
|
```
|
|
574
612
|
|
|
575
613
|
- Between Codex homes signed in to the same ChatGPT account, the session file is copied as it is,
|
|
576
|
-
with its ID and its name, and
|
|
577
|
-
|
|
578
|
-
`session_meta` and its events.
|
|
614
|
+
with its ID and its name, and the original is deleted once the copy is checked, as for Claude
|
|
615
|
+
Code. A copy already there is compared the same way.
|
|
579
616
|
- Between Claude Code and Codex (`hatcheck move 3f1c2a9e codex:work` goes the other way), and
|
|
580
617
|
between Codex homes on different accounts, the session is converted into a new one with a new ID,
|
|
581
618
|
and the original is always kept. Codex encrypts its reasoning and its summaries of compacted
|
|
@@ -599,9 +636,87 @@ Resume it now in ~/.claude-work? [y/N]
|
|
|
599
636
|
| `SESSION` | the session ID, or the start of it |
|
|
600
637
|
| `PROFILE` | where it goes: `NAME` for `~/.claude-NAME`, `default` for `~/.claude`, `codex` for `~/.codex`, `codex:NAME` for `~/.codex-NAME`, or a path |
|
|
601
638
|
| `--from PROFILE` | the profile or home to take it from, when more than one has it; without it you're asked, with the one used last as the default, and a script or `--json` gets that one |
|
|
602
|
-
| `--
|
|
603
|
-
| `--
|
|
604
|
-
|
|
639
|
+
| `--keep` | keep the original, which copies the session rather than moving it (a converted session's original is always kept) |
|
|
640
|
+
| `--dry-run` | show what would be moved, copied, converted and deleted, and change nothing |
|
|
641
|
+
|
|
642
|
+
`--no-keep`, which a move needed before it was the default, is still accepted, and so is `--fork`,
|
|
643
|
+
which does what [`hatcheck fork`](#hatcheck-fork-a-session-as-a-new-one-in-another-profile) does.
|
|
644
|
+
|
|
645
|
+
### `hatcheck fork`: a session as a new one in another profile
|
|
646
|
+
|
|
647
|
+
Bring a session into another profile as a new one with its own ID, and keep the original, as
|
|
648
|
+
Claude Code's `claude --resume <id> --fork-session` and `codex fork` do within one profile. It's
|
|
649
|
+
how to keep both when a move stops because the session went on in both profiles.
|
|
650
|
+
|
|
651
|
+
```
|
|
652
|
+
$ hatcheck fork 9a8b7c6d default
|
|
653
|
+
Forked session 9a8b7c6d "Add rate limiting to the login endpoint" from ~/.claude-work to ~/.claude as a new session:
|
|
654
|
+
transcript 61.2 KB
|
|
655
|
+
subagents and tool output 3 files
|
|
656
|
+
/rewind file snapshots 5 files
|
|
657
|
+
plan quiet-river-plan.md (already there)
|
|
658
|
+
new session 5b1e0c4a-7d2f-4e6b-9a3c-8f1d2e3c4b5a
|
|
659
|
+
Paths in the conversation to these files now point to the copies.
|
|
660
|
+
The copy of session 9a8b7c6d that was already in ~/.claude stays as it was.
|
|
661
|
+
The original stays in ~/.claude-work.
|
|
662
|
+
Resume it with:
|
|
663
|
+
cd ~/code/api
|
|
664
|
+
claude --resume 5b1e0c4a-7d2f-4e6b-9a3c-8f1d2e3c4b5a
|
|
665
|
+
Resume it now in ~/.claude? [y/N]
|
|
666
|
+
```
|
|
667
|
+
|
|
668
|
+
- It copies what `move` copies and checks it the same way, and the copy gets the new ID in its
|
|
669
|
+
records, and its own folders for subagents, saved tool output and `/rewind` snapshots. Its
|
|
670
|
+
message IDs stay the same, as in Claude Code's own fork. A Codex session gets the new ID in its
|
|
671
|
+
file name, its `session_meta` and its events.
|
|
672
|
+
- A copy already in the profile stays as it is, so a fork never stops for one, and the original
|
|
673
|
+
always stays where it was. A plan file already there stays too, since the copy there uses it.
|
|
674
|
+
- To the other agent, or to a Codex home on another account, it converts the session, as `move`
|
|
675
|
+
does: a converted session is always a new one.
|
|
676
|
+
- Resuming a fork was tested with the real `claude` (2.1.301).
|
|
677
|
+
|
|
678
|
+
| Option | What it does |
|
|
679
|
+
|------------------|------------------------------------------------------------------------------|
|
|
680
|
+
| `SESSION` | the session ID, or the start of it |
|
|
681
|
+
| `PROFILE` | where it goes, as for [`move`](#hatcheck-move-carry-on-a-session-with-another-profile) |
|
|
682
|
+
| `--from PROFILE` | the profile or home to take it from, when more than one has it, as for `move` |
|
|
683
|
+
| `--dry-run` | show what would be copied or converted, and change nothing |
|
|
684
|
+
|
|
685
|
+
### `hatcheck relocate`: a project folder that moved
|
|
686
|
+
|
|
687
|
+
Claude Code files a session under `projects/<the folder's name>` and records the folder in every
|
|
688
|
+
line, so once a project folder is renamed or moved, `claude --resume` from the new folder doesn't
|
|
689
|
+
list its sessions, and the commands `hatcheck` prints `cd` to a folder that's gone. `hatcheck
|
|
690
|
+
relocate` brings the sessions along, in every profile and home:
|
|
691
|
+
|
|
692
|
+
```console
|
|
693
|
+
$ mv ~/code/api ~/code/api2
|
|
694
|
+
$ hatcheck relocate ~/code/api ~/code/api2
|
|
695
|
+
Relocated 4 sessions from ~/code/api to ~/code/api2:
|
|
696
|
+
~/.claude-work 2 sessions: projects/-Users-me-code-api renamed projects/-Users-me-code-api2, with its memory and index
|
|
697
|
+
~/.claude 1 session: projects/-Users-me-code-api renamed projects/-Users-me-code-api2
|
|
698
|
+
~/.codex 1 session: the folder in the file rewritten
|
|
699
|
+
The folder binding of ~/code/api moved to ~/code/api2.
|
|
700
|
+
Resume them from ~/code/api2. To undo: hatcheck relocate ~/code/api2 ~/code/api
|
|
701
|
+
```
|
|
702
|
+
|
|
703
|
+
- Sessions that ran in the folder, or in a folder under it, come along. Each profile's project
|
|
704
|
+
folder is renamed to the new name when every session in it moves, so its `memory/` and
|
|
705
|
+
`sessions-index.json` come with it, the index's paths updated; when some stay, the sessions are
|
|
706
|
+
moved into the new project folder one by one, with their subagent and tool-output folders. In
|
|
707
|
+
each transcript the lines' top-level `cwd` is rewritten to the new folder, and nothing else:
|
|
708
|
+
what was said about the old path stays as it was. A Codex session, filed by date, stays where
|
|
709
|
+
it is, with the folder in its `session_meta` and `turn_context` lines rewritten, so `codex
|
|
710
|
+
resume` lists it from the new folder. Timestamps are kept, and a folder binding
|
|
711
|
+
([`hatcheck bind`](#hatcheck-bind-tie-a-folder-to-a-profile)) of the old folder moves to the new.
|
|
712
|
+
- A project folder whose name matches but whose sessions ran elsewhere (Claude Code names
|
|
713
|
+
`~/code/api-old` and `~/code/api/old` alike) is left alone and listed.
|
|
714
|
+
- It refuses, and changes nothing, when a session is open, was written in the last minute, is a
|
|
715
|
+
link rather than a file, is already filed under the new folder, or has a line naming the folder
|
|
716
|
+
that isn't JSON; and when NEW doesn't exist, is OLD, or is inside OLD. `--dry-run` shows what
|
|
717
|
+
would move. Running it the other way round, `hatcheck relocate NEW OLD`, undoes it, byte for
|
|
718
|
+
byte.
|
|
719
|
+
- `--json` prints the sessions moved and skipped, the binding and the undo command.
|
|
605
720
|
|
|
606
721
|
### `hatcheck open`: resume a session in a new terminal
|
|
607
722
|
|
|
@@ -635,27 +750,39 @@ cl work --resume 3f1c2a9e-8b7d-4c1e-9f2a-6d5e4c3b2a10
|
|
|
635
750
|
```console
|
|
636
751
|
$ hatcheck best
|
|
637
752
|
Claude Code, best first (sorted by Fable, as hatcheck usage sorts)
|
|
638
|
-
1. ~/.claude-work Fable 31% left, resets Tue 12:00pm · 5h 80% → cl work
|
|
639
|
-
2. ~/.claude-team Fable 100% left, resets Thu 1:00am · 5h 100% → cl team
|
|
640
|
-
3. ~/.claude-personal Fable 0% left, back Sat 4:59pm · 5h 100%
|
|
641
|
-
4. ~/.claude week 64
|
|
753
|
+
1. ~/.claude-work Fable 31% left, resets Tue 12:00pm, 0.5%/h · 5h 80% → cl work
|
|
754
|
+
2. ~/.claude-team Fable 100% left, resets Thu 1:00am, 0.9%/h · 5h 100% → cl team
|
|
755
|
+
3. ~/.claude-personal Fable 0% left, back Sat 4:59pm · 5h 100% → cl personal
|
|
756
|
+
4. ~/.claude week 64%, 1.3%/h · 5h 100% → claude
|
|
642
757
|
Codex, best first
|
|
643
|
-
1. ~/.codex month 100
|
|
758
|
+
1. ~/.codex month 100%, 0.2%/h → codex
|
|
644
759
|
Advice only: nothing is started, moved or switched. hatcheck best --for <session> says where to carry a session.
|
|
645
760
|
$ hatcheck best --for 9a8b7c6d
|
|
646
761
|
Session 9a8b7c6d "Add rate limiting to the login endpoint" is in ~/.claude-personal: Fable 0% left, back Sat 4:59pm · 5h 100%.
|
|
647
|
-
Carry it to ~/.claude-work: Fable 31% left, resets Tue 12:00pm · 5h 80%.
|
|
762
|
+
Carry it to ~/.claude-work: Fable 31% left, resets Tue 12:00pm, 0.5%/h · 5h 80%.
|
|
648
763
|
hatcheck move 9a8b7c6d work --from personal
|
|
649
764
|
It prints the command that resumes it there, and offers to run it.
|
|
765
|
+
$ hatcheck best --wait work && cl work
|
|
766
|
+
No room yet; waiting for ~/.claude-work until Tue 12:00pm (in 2d14h)…
|
|
650
767
|
```
|
|
651
768
|
|
|
652
769
|
- Claude Code accounts come in the order `hatcheck usage` sorts them: those with Fable left first,
|
|
653
|
-
the soonest Fable reset on top
|
|
654
|
-
|
|
655
|
-
|
|
770
|
+
the soonest Fable reset on top, with those past 90% used behind the fresher ones and those past
|
|
771
|
+
98% behind those; then those out of Fable, or out of the weekly limit for all models, the soonest
|
|
772
|
+
back on top; then accounts without a Fable limit, by the limit with the least left. Codex homes
|
|
773
|
+
are ranked by the limit with the least left.
|
|
774
|
+
- The Fable part ends with the account's pace: what's left, divided by the hours until it resets,
|
|
775
|
+
so what the account can spend per hour without running out before the reset. `0.5%/h` with 31%
|
|
776
|
+
left means about 62 hours to go. An account without a Fable limit shows the pace of its tightest
|
|
777
|
+
limit instead.
|
|
656
778
|
- `--for <session>` picks the best other account of the session's agent that has room now, and
|
|
657
779
|
prints the [`hatcheck move`](#hatcheck-move-carry-on-a-session-with-another-profile) command. If
|
|
658
780
|
the session's own account is the best, it says so and prints the resume command.
|
|
781
|
+
- `--wait` sleeps until an account has room, then answers as above: any Claude Code account;
|
|
782
|
+
`--wait NAME` (or `default`, `codex`, `codex:NAME`) that one profile or home; with `--for`, an
|
|
783
|
+
account of the session's agent. It sleeps until the soonest reset the numbers name, says so on
|
|
784
|
+
stderr, then looks again; when nothing says when an account will have room, it stops with an
|
|
785
|
+
error instead of polling. For a script: `hatcheck best --wait work && cl work`.
|
|
659
786
|
- The numbers are the ones `hatcheck usage` shows, live when it can be, with a snapshot's age
|
|
660
787
|
otherwise; `--cached` skips the APIs.
|
|
661
788
|
- **Advice only.** It runs when you ask, prints commands, and never starts, moves or switches
|
|
@@ -741,10 +868,11 @@ $ hatcheck --json
|
|
|
741
868
|
"why": null,
|
|
742
869
|
"limits": [
|
|
743
870
|
{"name": "session (5h)", "short": "5h", "kind": "session", "used_percent": 20, "left_percent": 80,
|
|
744
|
-
"resets_at": "2026-10-16T01:30:00Z", "window_seconds": 18000, "severity": "normal", "per_model": false
|
|
871
|
+
"resets_at": "2026-10-16T01:30:00Z", "window_seconds": 18000, "severity": "normal", "per_model": false,
|
|
872
|
+
"pace": 28.42}
|
|
745
873
|
],
|
|
746
874
|
"extra": null,
|
|
747
|
-
"fable": {"left": true, "resets_at": "2026-10-20T16:00:00Z"}
|
|
875
|
+
"fable": {"left": true, "resets_at": "2026-10-20T16:00:00Z", "band": "fresh"}
|
|
748
876
|
}
|
|
749
877
|
],
|
|
750
878
|
"hidden": {"Desktop": 3},
|
|
@@ -759,12 +887,52 @@ $ hatcheck --json
|
|
|
759
887
|
`--no-usage`). `hatcheck usage --json` gives every account, in its Fable order, with `sorted_by`.
|
|
760
888
|
- **Stable:** absolute paths rather than `~`, times in UTC (ISO 8601), no colours. `version` goes up
|
|
761
889
|
only when a field changes meaning or goes away; new fields can appear at any time.
|
|
762
|
-
- `left_percent` is `null` for a snapshot's limit that has reset since it was saved. `
|
|
763
|
-
|
|
764
|
-
`
|
|
890
|
+
- `left_percent` is `null` for a snapshot's limit that has reset since it was saved. `pace` is what's
|
|
891
|
+
left per hour until the reset (`left_percent` over the hours to go, at least one), `null` without
|
|
892
|
+
a reset ahead. `fable` is `{"left": true, "resets_at": …}`, `{"left": false, "back_at": …}`, or
|
|
893
|
+
`null` without a Fable limit; its `band` is `fresh`, `low` (past 90% used), `nearly out` (past 98%)
|
|
894
|
+
or `out`, the order `hatcheck usage` sorts by. `source` is `live`, `cached` or `none`, with `why`
|
|
895
|
+
when it isn't live.
|
|
765
896
|
- Errors go to stderr with a non-zero exit, so stdout is always valid JSON. Email addresses only with
|
|
766
897
|
`--email`.
|
|
767
898
|
|
|
899
|
+
## Rules it keeps
|
|
900
|
+
|
|
901
|
+
Each rule names the code that keeps it, so it can be checked rather than taken on trust.
|
|
902
|
+
|
|
903
|
+
- **Not in the path.** Nothing of Hatcheck sits between an agent and its model. `cl` and `cx`
|
|
904
|
+
set `CLAUDE_CONFIG_DIR` or `CODEX_HOME` (and, for `cl -z` and `cl -k`, the provider variables
|
|
905
|
+
you set up) and run the agent in their place; nothing stays running
|
|
906
|
+
([`launch.rs`](crates/hatcheck/src/launch.rs), `run`).
|
|
907
|
+
- **No agent's config is rewritten**, except when you ask: `hatcheck bind --hook` adds one
|
|
908
|
+
`SessionStart` hook to each profile's `settings.json` and each Codex home's `hooks.json`, and
|
|
909
|
+
`unbind --hook` removes only what it added ([`bind.rs`](crates/hatcheck/src/bind.rs),
|
|
910
|
+
`add_hooks` and `remove_hooks`).
|
|
911
|
+
- **No credentials.** It never asks for, stores, refreshes or moves a login. For Claude it
|
|
912
|
+
never reads one: Claude Code's own `/usage` is run in the profile and the snapshot it saves is
|
|
913
|
+
read ([`usage.rs`](crates/hatcheck/src/usage.rs), `run_claude_usage` and `claude_live`). For
|
|
914
|
+
Codex, the home's `auth.json` token is sent only to ChatGPT's usage endpoint, as it is, and
|
|
915
|
+
never refreshed (`read_codex_login` and `fetch_codex_usage` there).
|
|
916
|
+
- **Nothing leaves your computer** except those usage requests: Claude Code's to Anthropic, and
|
|
917
|
+
one to ChatGPT per Codex account. `CODEX_USAGE_URL` in `usage.rs` is the one address the
|
|
918
|
+
binary itself calls; `--cached` and `--no-usage` make none. The Z.ai and Kimi endpoints in
|
|
919
|
+
[`provider.rs`](crates/hatcheck/src/provider.rs) are handed to Claude Code, which calls them
|
|
920
|
+
only when you run `cl -z` or `cl -k`.
|
|
921
|
+
- **No automatic switching** between accounts. `hatcheck best` ranks and prints commands, and
|
|
922
|
+
nothing in the binary starts, moves or switches a session on its own
|
|
923
|
+
([`best.rs`](crates/hatcheck/src/best.rs): advice only, `--wait` sleeps and then prints).
|
|
924
|
+
- **Nothing runs in the background.** There's no daemon. `hatcheck serve` is the desktop app's
|
|
925
|
+
engine and lives only while the app does, one command per line
|
|
926
|
+
([`serve.rs`](crates/hatcheck/src/serve.rs)).
|
|
927
|
+
- **Sessions are only ever moved, copied or rewritten in ways you can undo.** `move` deletes the
|
|
928
|
+
original only once every copied file is checked against it, never puts an older copy over a
|
|
929
|
+
newer one, and is undone by moving the session back; `fork` keeps the original; `relocate`
|
|
930
|
+
prints the command that undoes it; and all three have `--dry-run`, which runs every check and
|
|
931
|
+
writes nothing ([`move_cmd.rs`](crates/hatcheck/src/move_cmd.rs),
|
|
932
|
+
[`relocate.rs`](crates/hatcheck/src/relocate.rs)).
|
|
933
|
+
|
|
934
|
+
Function names rather than line numbers, since lines move; `git grep` finds them.
|
|
935
|
+
|
|
768
936
|
## The desktop app
|
|
769
937
|
|
|
770
938
|
A menu-bar app (system tray on Windows and Linux) built on the CLI. It shows what's left of every
|
|
@@ -773,9 +941,9 @@ which opens a terminal in the session's folder, and **Copy**. It also has button
|
|
|
773
941
|
Desktop instances and notifies you when a limit runs low or resets.
|
|
774
942
|
|
|
775
943
|
Its main window browses every session, with search, filters and a read-only preview of the
|
|
776
|
-
conversation. From there you can resume a session, copy its command, or move it to
|
|
777
|
-
profile after a dry run. The window also lists profiles and homes, signs in to a new one
|
|
778
|
-
terminal, and makes Desktop instances.
|
|
944
|
+
conversation. From there you can resume a session, copy its command, or move or fork it to
|
|
945
|
+
another profile after a dry run. The window also lists profiles and homes, signs in to a new one
|
|
946
|
+
in a terminal, and makes Desktop instances.
|
|
779
947
|
|
|
780
948
|
It ships the CLI inside itself, so it needs no Python. It never handles a login, and live usage is
|
|
781
949
|
off until you turn it on. See [desktop/README.md](desktop/README.md) to build it; releases come
|
|
@@ -787,7 +955,10 @@ from `.github/workflows/desktop.yml` for macOS, Windows and Linux. The plan behi
|
|
|
787
955
|
- **`crates/hatcheck/`**: hatcheck in Rust, the commands and the launchers. Its `src/` has a file per
|
|
788
956
|
subcommand (`sessions.rs`, `usage.rs`, `move_cmd.rs`, `open_cmd.rs`, `desktop.rs` and the rest),
|
|
789
957
|
`launch.rs` for `cl`, `cx`, `claude-z` and `claude-k`, and `src/bin/` for those binaries and `hat`.
|
|
790
|
-
It was ported from a Python version with the
|
|
958
|
+
Its own README is the crate's page on crates.io. It was ported from a Python version with the
|
|
959
|
+
same output; see [docs/rust-port.md](docs/rust-port.md).
|
|
960
|
+
- **`CHANGELOG.md`**: what changed in each release of the CLI; a release's notes on GitHub are its
|
|
961
|
+
section there.
|
|
791
962
|
- **`install.sh`** / **`install.ps1`**: build the commands from a clone and put them on your `PATH`
|
|
792
963
|
(`~/.local/bin` by default).
|
|
793
964
|
- **`pyproject.toml`**: the PyPI package, the binaries as wheels built with maturin.
|
|
@@ -799,6 +970,9 @@ from `.github/workflows/desktop.yml` for macOS, Windows and Linux. The plan behi
|
|
|
799
970
|
`logo.svg` and `logo-dark.svg` (the mark), `logo-wordmark.svg` and `logo-wordmark-dark.svg`, `favicon.svg`.
|
|
800
971
|
- **`docs/proposals/`**: the plans these came from: [the CLI features](docs/proposals/cli-features.md)
|
|
801
972
|
and [the desktop app](docs/proposals/desktop-app.md).
|
|
973
|
+
- **`AGENTS.md`** and **`docs/lessons.md`**: notes for coding agents (`CLAUDE.md` imports them): how
|
|
974
|
+
to build and check, the rules the code keeps, and what earlier work got wrong, with the rule that
|
|
975
|
+
would have caught it.
|
|
802
976
|
- **`tests/`**: the command tests, which run the binary against throwaway home folders:
|
|
803
977
|
`python3 -m unittest discover -s tests`, which builds it with cargo first, and the crate's own
|
|
804
978
|
tests with `cargo test -p hatcheck`. They never read your real profiles, Keychain or the network.
|
|
@@ -811,9 +985,9 @@ from `.github/workflows/desktop.yml` for macOS, Windows and Linux. The plan behi
|
|
|
811
985
|
instance with its own icon, and a launcher that brings a running instance forward instead of
|
|
812
986
|
opening a duplicate. It needs testing on a Windows machine first.
|
|
813
987
|
- **Linux.** There's no official Claude Desktop for Linux, so only the CLI tools apply there.
|
|
814
|
-
- **Releases:** the CLI
|
|
815
|
-
|
|
816
|
-
|
|
988
|
+
- **Releases:** the CLI is on GitHub, the Homebrew tap, PyPI and crates.io from 0.2.0
|
|
989
|
+
([CHANGELOG.md](CHANGELOG.md)). Next are winget, then the app's installers, once its release
|
|
990
|
+
workflow has its signing and updater secrets (`desktop.yml` lists them).
|
|
817
991
|
- **Signing:** a Developer ID for the macOS app, and a certificate for the Windows one.
|
|
818
992
|
|
|
819
993
|
## Credits
|