tomari 0.0.0-stage → 0.3.0-rc.0
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.
- package/LICENSE +21 -0
- package/README.md +111 -2
- package/bin/tomari.js +27 -0
- package/lib/platform.js +7 -0
- package/package.json +27 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jose Ramon Montes Hermida
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,112 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Tomari
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<p align="center">
|
|
4
|
+
<img src="https://raw.githubusercontent.com/elrincondeldev/tomari/main/images/creatures.gif" alt="Eight pixel-art creatures, one per session state: working, needs permission, asking you, compacting, done, asleep, error and closed" width="100%">
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
A floating strip on the edge of your Mac's screen with one animated pixel-art creature per Claude Code session. Each creature shows what its session is doing, and the ones waiting for you are hard to miss. Click a creature and its session opens in the Claude desktop app.
|
|
8
|
+
|
|
9
|
+
> **Not an official Anthropic project.** It is not affiliated with or endorsed by Anthropic. "Claude" is a trademark of Anthropic, PBC.
|
|
10
|
+
|
|
11
|
+
> **Early development.** Expect rough edges. macOS 14 or newer only.
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npx tomari setup
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
That's all: the strip appears on the right edge with a **+** to pin your sessions, and it comes back at every login. Setup:
|
|
20
|
+
|
|
21
|
+
- copies Tomari's binaries into `~/Library/Application Support/tomari/bin`;
|
|
22
|
+
- adds hooks to `~/.claude/settings.json`, after backing it up, so Claude Code reports each event to Tomari's agent;
|
|
23
|
+
- starts the agent and the strip now and at every login, as LaunchAgents;
|
|
24
|
+
- replaces [claude-panel](https://github.com/elrincondeldev/claude-panel)'s agent if you have it, keeping its pinned sessions, their looks and its pairing token;
|
|
25
|
+
- moves an install from when Tomari was called Perch (`@elrincondeldev/perch`) into Tomari's places, keeping its pins, icons and token.
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npx tomari status # what's installed and running
|
|
29
|
+
npx tomari uninstall # remove everything; asks before deleting pins and icons
|
|
30
|
+
npx tomari setup --pi # also let a claude-panel Raspberry Pi connect over your network
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
You need the Claude desktop app (sessions in its Code tab), the Claude Code CLI 2.1.285 or newer, and Node.js 18 or newer for `npx`.
|
|
34
|
+
|
|
35
|
+
## Features
|
|
36
|
+
|
|
37
|
+
- **The sessions you choose**: the **+** at the end of the strip lists every session in the Claude desktop app, recent or old, running or stopped; pick one to pin it. Sessions you haven't pinned show up only while they work or wait for you, and for five minutes after they finish, so a fresh install starts with just the +.
|
|
38
|
+
- **One creature per session**, animated by its state: working, needs permission, asking you, compacting, done, error or closed. Finished sessions fall asleep after five minutes.
|
|
39
|
+
- **Hard to miss when it needs you**: a permission request blinks the creature's tile in orange; a question rings it in orange. A working creature hops with typing dots over its head, and one that finished its turn holds up a green check, ringed in green, until you reply or it falls asleep.
|
|
40
|
+
- **Hover** for the session's name and status, e.g. `Bash: npm test` or `done · 5m`.
|
|
41
|
+
- **Click** to open the session in the Claude desktop app, even one the app has stopped. The session in front is ringed in white.
|
|
42
|
+
- **Right-click** (or control-click) to pin or unpin the session and pick its character and color.
|
|
43
|
+
- **Stays out of the way**: the strip floats over every Space and full-screen app and never takes focus from the app you're using. The arrow tab beside it slides the strip off the edge, leaving just the tab, which blinks orange when a session needs you; click it again to bring the strip back.
|
|
44
|
+
- **Menu bar item** to show or hide the strip, move it to the left or right edge, and see how many sessions are waiting for you. Quit Tomari there; it starts again at your next login.
|
|
45
|
+
|
|
46
|
+
## How it works
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
Claude Code ─ hooks ─▶ tomari agent ◀─ WebSocket (127.0.0.1:7778, token) ─ tomari-overlay ─ menu bar
|
|
50
|
+
claude agents ─ poll ─▶ └ SQLite: pins, icons └ claude-panel Pi (with --pi)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
- **`tomari`** (`agent/`, Bun and TypeScript compiled into one binary) holds the CLI and the agent. The agent tracks every session's state from Claude Code hooks and `claude agents --json`, keeps pins and icons in SQLite, and opens sessions in the desktop app. It listens on 127.0.0.1 only, unless you set it up with `--pi`.
|
|
54
|
+
- **`tomari-overlay`** (`Sources/`, Swift) is a native AppKit and Core Animation app that runs as an accessory: no Dock icon, just the strip and a menu bar item. It costs about 0.5 % of one CPU core and 13 MB of memory while it animates.
|
|
55
|
+
- **`shared/protocol.ts`** is the contract between them, and the Pi panel speaks it too.
|
|
56
|
+
|
|
57
|
+
| What the agent reads from Claude | Used for | Documented? |
|
|
58
|
+
|---|---|---|
|
|
59
|
+
| Hooks in `~/.claude/settings.json` | Instant state changes | Yes |
|
|
60
|
+
| `claude agents --json` | Names, who is alive, corrections for missed hooks | Yes |
|
|
61
|
+
| `claude --desktop --resume <id>` | Opening a session the desktop app doesn't know | Yes |
|
|
62
|
+
| `claude://code/continue?session=local_…` | Opening any desktop-app session, running or stopped | No |
|
|
63
|
+
| `~/Library/Application Support/Claude/claude-code-sessions/` | The app's sessions, and their `local_…` ids | No |
|
|
64
|
+
| `setFocusedSession` in `~/Library/Logs/Claude/main.log` | Which session is in front | No |
|
|
65
|
+
|
|
66
|
+
If a Claude update breaks an undocumented source, only the feature it feeds stops working.
|
|
67
|
+
|
|
68
|
+
## Customizing the creatures
|
|
69
|
+
|
|
70
|
+
The characters are 16×16 text templates in [`Sources/TomariCore/Resources/characters.json`](Sources/TomariCore/Resources/characters.json):
|
|
71
|
+
|
|
72
|
+
| Field | Meaning |
|
|
73
|
+
|---|---|
|
|
74
|
+
| `body` | 16 rows of 16 cells: `B` body (the session's color), `D` darker, `L` lighter, `F` face plate, `P` pink, `.` empty |
|
|
75
|
+
| `walk` | Optional rows that replace the body from `row` down on alternate frames while the session works |
|
|
76
|
+
| `eyes` | Top-left corners of the two 2×2 eyes, which blink, close and squint on their own |
|
|
77
|
+
| `eyeColor` | Optional `#rrggbb` |
|
|
78
|
+
|
|
79
|
+
After editing, check the templates with `swift run TomariCoreTests` and rebuild.
|
|
80
|
+
|
|
81
|
+
## Development
|
|
82
|
+
|
|
83
|
+
You need the Command Line Tools for Xcode (`xcode-select --install`) and [Bun](https://bun.sh) 1.3 or newer.
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
(cd agent && bun install)
|
|
87
|
+
bun test agent npm # agent, CLI and npm launcher
|
|
88
|
+
swift run TomariCoreTests # protocol, session list, status rules, sprites and layout
|
|
89
|
+
swift build # debug overlay: .build/debug/tomari-overlay
|
|
90
|
+
bun scripts/release.ts --arch arm64 # npm packages in dist/npm
|
|
91
|
+
dist/npm/tomari-darwin-arm64/bin/tomari setup # install that build
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
The Command Line Tools for Xcode 15 ship without XCTest, so the Swift tests are a plain executable that exits non-zero when a check fails.
|
|
95
|
+
|
|
96
|
+
Pushing a `v*` tag runs `.github/workflows/release.yml`: it tests, builds for Apple Silicon and Intel, publishes the three npm packages through npm's Trusted Publishing, with no token, and attaches the binaries to a GitHub release. Pull requests that touch what ships run the same build without publishing.
|
|
97
|
+
|
|
98
|
+
## Privacy
|
|
99
|
+
|
|
100
|
+
- Everything stays on your Mac: the overlay only talks to the agent on 127.0.0.1, and the agent only listens there unless you choose `--pi`. No telemetry.
|
|
101
|
+
- The WebSocket needs the pairing token in `~/Library/Application Support/tomari/config.json`, and accepts only `open`, `pin`, `icon` and `library`, with validated arguments.
|
|
102
|
+
- Tomari keeps its data in `~/Library/Application Support/tomari/`, its logs in `~/Library/Logs/tomari/`, and the strip's edge in the `com.elrincondeldev.tomari` defaults.
|
|
103
|
+
- The hover label can show tool details such as a shell command, so anyone who can see your screen can read them.
|
|
104
|
+
|
|
105
|
+
## Roadmap
|
|
106
|
+
|
|
107
|
+
- Homebrew: `brew install elrincondeldev/tap/tomari`, from the same release binaries.
|
|
108
|
+
- Drag the strip to any edge, global shortcuts to open sessions, and notifications when a session needs you.
|
|
109
|
+
|
|
110
|
+
## License
|
|
111
|
+
|
|
112
|
+
[MIT](LICENSE)
|
package/bin/tomari.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// npm installs only the optional dependency that matches this Mac; run the `tomari` binary it holds.
|
|
3
|
+
import { spawnSync } from "node:child_process";
|
|
4
|
+
import { createRequire } from "node:module";
|
|
5
|
+
import { dirname, join } from "node:path";
|
|
6
|
+
import { platformPackage } from "../lib/platform.js";
|
|
7
|
+
|
|
8
|
+
const name = platformPackage(process.platform, process.arch);
|
|
9
|
+
if (!name) {
|
|
10
|
+
console.error(`tomari runs on macOS only (this is ${process.platform}-${process.arch}).`);
|
|
11
|
+
process.exit(1);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
let binary;
|
|
15
|
+
try {
|
|
16
|
+
binary = join(dirname(createRequire(import.meta.url).resolve(`${name}/package.json`)), "bin", "tomari");
|
|
17
|
+
} catch {
|
|
18
|
+
console.error(`tomari: ${name} is not installed. Install again without --omit=optional.`);
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const result = spawnSync(binary, process.argv.slice(2), { stdio: "inherit" });
|
|
23
|
+
if (result.error) {
|
|
24
|
+
console.error(`tomari: ${result.error.message}`);
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
process.exit(result.status ?? 1);
|
package/lib/platform.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
const SUPPORTED = new Set(["darwin-arm64", "darwin-x64"]);
|
|
2
|
+
|
|
3
|
+
/** The npm package holding the binaries for this OS and CPU, or null where Tomari doesn't run. */
|
|
4
|
+
export function platformPackage(platform, arch) {
|
|
5
|
+
const target = `${platform}-${arch}`;
|
|
6
|
+
return SUPPORTED.has(target) ? `@elrincondeldev/tomari-${target}` : null;
|
|
7
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tomari",
|
|
3
|
-
"version": "0.0.0
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.3.0-rc.0",
|
|
4
|
+
"description": "Your Claude Code sessions as animated pixel-art creatures on the edge of your Mac's screen",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"homepage": "https://github.com/elrincondeldev/tomari",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/elrincondeldev/tomari.git"
|
|
10
|
+
},
|
|
11
|
+
"type": "module",
|
|
12
|
+
"bin": {
|
|
13
|
+
"tomari": "bin/tomari.js"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"bin",
|
|
17
|
+
"lib/platform.js"
|
|
18
|
+
],
|
|
19
|
+
"os": [
|
|
20
|
+
"darwin"
|
|
21
|
+
],
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">=18"
|
|
24
|
+
},
|
|
25
|
+
"optionalDependencies": {
|
|
26
|
+
"@elrincondeldev/tomari-darwin-arm64": "0.3.0-rc.0",
|
|
27
|
+
"@elrincondeldev/tomari-darwin-x64": "0.3.0-rc.0"
|
|
28
|
+
}
|
|
29
|
+
}
|