superdario 1.6.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 +193 -0
- package/bin/dario +45 -0
- package/dist/main.js +4591 -0
- package/hooks/agent_from_env.sh +9 -0
- package/hooks/agent_hook.sh +9 -0
- package/hooks/notification.sh +8 -0
- package/hooks/post_tool_use.sh +8 -0
- package/hooks/pre_tool_use.sh +8 -0
- package/hooks/stop.sh +8 -0
- package/hooks/user_prompt_submit.sh +8 -0
- package/package.json +48 -0
- package/skills/dario/SKILL.md +116 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Eventually Solutions
|
|
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
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
# Super Dario
|
|
2
|
+
|
|
3
|
+
Claude's pixel mascot in a Super Mario flavoured endless runner for your terminal.
|
|
4
|
+
Stomp bugs, bonk ? blocks, jump the pipes, duck under ghosts, collect gold tokens and
|
|
5
|
+
chase the global high score.
|
|
6
|
+
It plugs into Claude Code: every prompt you send opens Dario in a fresh terminal
|
|
7
|
+
tab so you can play while Claude works, and the HUD tells you when Claude is done
|
|
8
|
+
or needs your input.
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
DARIO TOKENS 7 SCORE 00412 HI 01230 CLAUDE: working...
|
|
12
|
+
|
|
13
|
+
▄▄ ▄▄▄▄
|
|
14
|
+
▄███▄ ▀▀▀ ▄██████▄
|
|
15
|
+
▐█ ▀ █▌ ▀ █▀▀█ ▀
|
|
16
|
+
▀█▄█▀ ▀▀ ▀▀
|
|
17
|
+
█ █ ▄▄██▄▄
|
|
18
|
+
─────────────────────────────────────────────────────────────────────────────
|
|
19
|
+
SPACE / UP jump DOWN / S duck P pause Q quit
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Requirements
|
|
23
|
+
|
|
24
|
+
- macOS (the "open a new terminal" part uses Warp and iTerm as a new tab in the active window; a new window in Terminal.app, Ghostty, WezTerm, kitty, Alacritty, Tabby and Rio; or the integrated terminal of Cursor, VS Code, VS Code Insiders, VSCodium, Windsurf, Kiro and Trae through a tiny launcher extension)
|
|
25
|
+
- Node.js >= 22.18 (runs TypeScript directly, no build step, no runtime dependencies)
|
|
26
|
+
|
|
27
|
+
## Install
|
|
28
|
+
|
|
29
|
+
```sh
|
|
30
|
+
curl -fsSL https://dario-xxx.web.app/install.sh | sh # downloads ~/.dario/app, runs the first-run wizard, wires Claude Code
|
|
31
|
+
dario update # later: fetch the newest release from the site
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Or from npm (the package is `superdario`, the command is still `dario`):
|
|
35
|
+
|
|
36
|
+
```sh
|
|
37
|
+
npm install -g superdario && dario install # stable global install; update with npm install -g superdario@latest
|
|
38
|
+
npx superdario install # one-shot: copies itself to ~/.dario/app first, since the npx cache gets pruned
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
From a source checkout instead:
|
|
42
|
+
|
|
43
|
+
```sh
|
|
44
|
+
cd dario
|
|
45
|
+
npm install # only dev tooling for typecheck/tests
|
|
46
|
+
./bin/dario install # hooks into ~/.claude/settings.json, links ~/.claude/skills/dario and ~/.local/bin/dario
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Releases are built with `scripts/build_release.sh` (writes `web/dl/dario-<version>.tgz`, `dario-latest.tgz`, `version.json`) and published with `firebase deploy --only hosting`.
|
|
50
|
+
|
|
51
|
+
`dario install` is idempotent and only adds/removes its own entries.
|
|
52
|
+
`dario uninstall` reverses everything.
|
|
53
|
+
|
|
54
|
+
## Play
|
|
55
|
+
|
|
56
|
+
```sh
|
|
57
|
+
dario # play in the current terminal
|
|
58
|
+
dario launch # open a new tab/window and play there
|
|
59
|
+
dario stop # close the running game
|
|
60
|
+
dario scores # high score, token totals, games played
|
|
61
|
+
dario ranking # global leaderboard (Firebase) and your rank
|
|
62
|
+
dario name Bob # change the name shown on the leaderboard (asked once on first play)
|
|
63
|
+
dario mode pro # PRO CODER: play only while the agent works (vibe = any time, the default)
|
|
64
|
+
dario status # running? hooks installed? auto-launch? Claude state?
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Controls: hold `RIGHT`/`D` to run and release to stop (a tiny helper reads the physical key state on macOS, so this works in every terminal), `LEFT`/`A` walks back (the camera never scrolls back), `SPACE`/`UP`/`W` jump, `DOWN`/`S` duck (fast-fall in the air), `P` pause, `R` restart, `Q`/`ESC` quit. Nothing moves until you run; enemies still walk toward you.
|
|
68
|
+
|
|
69
|
+
You start with 3 lives (shown as `LIVES ♥♥♥` in the HUD; lost ones turn into dots). Touching an enemy costs one: the mascot hops back and blinks
|
|
70
|
+
for a moment, and the run only ends when the last life goes. Some ? blocks pop a red heart instead of
|
|
71
|
+
their logo; grabbing it adds a life (up to 9), credited to the sponsor when it came out of their block ("+1 LIFE by FIGMA").
|
|
72
|
+
|
|
73
|
+
Score grows with distance; each coin is worth 25 points (there is no separate token counter). Landing on a bug squishes
|
|
74
|
+
it for +100, hitting a blinking ? block from below pops out a mushroom (+200 points) or a sponsor's
|
|
75
|
+
logo (+300 points, +100 more each time, shown as "+300 by FIGMA"), and you can stand on blocks. Pipes must be jumped, mid-height
|
|
76
|
+
ghosts ducked (or jumped with perfect timing), high ghosts run under.
|
|
77
|
+
|
|
78
|
+
## Modes
|
|
79
|
+
|
|
80
|
+
`dario mode vibe` (default, **VIBE CODER**) lets you play whenever you like. `dario mode pro` (**PRO CODER**) only lets
|
|
81
|
+
the mascot run while Claude / Codex / Grok is actually working on a prompt: the start, resume and restart keys are
|
|
82
|
+
locked otherwise ("PRO CODER: plays only while CLAUDE is working"), the game pauses itself the moment the agent
|
|
83
|
+
finishes or needs you, and resumes on its own with the next prompt. The mode is also in the in-game settings panel (C).
|
|
84
|
+
|
|
85
|
+
## Characters
|
|
86
|
+
|
|
87
|
+
You play as the agent you launched from: the Claude Code hook starts the game as
|
|
88
|
+
**Claude**, `CODEX_HOME`/`CODEX_SANDBOX` in the environment means **Codex**, `GROK_CLI`
|
|
89
|
+
means **Grok**. The other two agents are the walking enemies you stomp. Force it with
|
|
90
|
+
`dario play --as codex`, `dario launch --as grok` or persistently `dario character grok`
|
|
91
|
+
(`auto` restores detection).
|
|
92
|
+
|
|
93
|
+
## Claude Code integration
|
|
94
|
+
|
|
95
|
+
| Hook | What happens |
|
|
96
|
+
| ------------------ | -------------------------------------------------------------------------------- |
|
|
97
|
+
| `UserPromptSubmit` | writes `working` to `~/.config/dario/claude_status.json`, opens Dario if not running |
|
|
98
|
+
| `Stop` | writes `done`: the game shows **CLAUDE IS DONE - go check your prompt!** |
|
|
99
|
+
| `Notification` | permission / idle prompts write `attention`: **CLAUDE NEEDS YOUR INPUT** |
|
|
100
|
+
| `PreToolUse` / `PostToolUse` | write the running tool ("Bash · npm test", "Edit · game.ts") so the HUD shows live activity; between tools it cycles Claude-Code-style thinking verbs |
|
|
101
|
+
|
|
102
|
+
The hook scripts return immediately (the work runs in the background) and print
|
|
103
|
+
nothing, so prompts are never delayed and no context is injected.
|
|
104
|
+
|
|
105
|
+
When Claude is done or needs input the game pauses itself, and the hook brings
|
|
106
|
+
the app you prompted from back to the front (captured when the prompt was sent).
|
|
107
|
+
If that app was Warp it also presses Cmd+Shift+[ to return to the previous tab,
|
|
108
|
+
which needs Accessibility permission for the app running the hook.
|
|
109
|
+
|
|
110
|
+
```sh
|
|
111
|
+
dario focus off # keep playing; do not switch apps when Claude finishes
|
|
112
|
+
dario off # stop opening the game on every prompt (hooks stay installed)
|
|
113
|
+
dario on # resume
|
|
114
|
+
dario terminal iterm # force a terminal app or IDE; `dario terminal --list` shows what is installed here
|
|
115
|
+
dario ide cursor # install the Dario Launcher extension and open the game inside the IDE's integrated terminal
|
|
116
|
+
# (cursor | vscode | vscode_insiders | vscodium | windsurf | kiro | trae)
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Codex CLI and Grok Build
|
|
120
|
+
|
|
121
|
+
The same hooks exist for OpenAI's Codex CLI and xAI's Grok Build, and the game then plays as
|
|
122
|
+
Codex or Grok with the other agents as enemies. `dario install` writes them automatically when
|
|
123
|
+
it finds `~/.codex` or `~/.grok`; `dario agents` shows the state, `dario agents codex` /
|
|
124
|
+
`dario agents grok` add them later and `dario agents codex off` removes them.
|
|
125
|
+
|
|
126
|
+
| Agent | Where the hooks go | Events |
|
|
127
|
+
| ---------- | ------------------------------- | ---------------------------------------------------------------------- |
|
|
128
|
+
| Codex CLI | `~/.codex/hooks.json` | `UserPromptSubmit`, `Stop`, `PermissionRequest` (attention), `PreToolUse`, `PostToolUse` |
|
|
129
|
+
| Grok Build | `~/.grok/hooks/dario.json` | `UserPromptSubmit`, `Stop`, `Notification` (matcher `permission_prompt\|idle_prompt`), `PreToolUse`, `PostToolUse` |
|
|
130
|
+
|
|
131
|
+
Codex only runs hooks you have trusted: open Codex, type `/hooks` and approve the Dario entries once.
|
|
132
|
+
Grok Build also executes Claude Code's `settings.json` hooks in its compatibility mode; the Dario
|
|
133
|
+
scripts detect that (`GROK_HOOK_EVENT`) and either defer to the Grok hook file or report the event as Grok,
|
|
134
|
+
so the game is never opened twice. `CODEX_HOME` / `GROK_HOME` are honoured when set.
|
|
135
|
+
|
|
136
|
+
The `/dario` skill (linked into `~/.claude/skills/dario`) lets you ask Claude to
|
|
137
|
+
open the game, read scores, or toggle auto-launch from the chat.
|
|
138
|
+
|
|
139
|
+
## Global ranking
|
|
140
|
+
|
|
141
|
+
Scores are submitted to Firestore (project `dario-xxx`) after every game (VIBE and PRO keep separate boards: `highScore` / `proHighScore`) using an
|
|
142
|
+
anonymous Firebase session stored in `~/.config/dario/auth.json`. No SDK: plain
|
|
143
|
+
`fetch` against the Firestore and Identity Toolkit REST APIs. Security rules
|
|
144
|
+
(`firebase/firestore.rules`) let anyone read the board, let only the owner write
|
|
145
|
+
their own document, and never let a high score go down. Deploy rules with
|
|
146
|
+
`firebase deploy --only firestore:rules`.
|
|
147
|
+
|
|
148
|
+
## Website and sponsors
|
|
149
|
+
|
|
150
|
+
`web/` is a static site on Firebase Hosting (https://dario-xxx.web.app): landing page,
|
|
151
|
+
live leaderboard (VIBE / PRO tabs), an autoplay demo of the real engine (`web/demo.js`, built from `src/demo` with
|
|
152
|
+
`scripts/build_demo.sh`) and the sponsor flow. Three tiers, all paid through Polar:
|
|
153
|
+
|
|
154
|
+
- **In-game mystery box sponsor** (30 days, pay what you like from $29): the amount paid becomes the sponsor's
|
|
155
|
+
`priority`, so higher amounts rank higher: more ? boxes and always the first box of a run.
|
|
156
|
+
- **Banner sponsor** ($69.90 per day) and **ranking sponsor** ($29.90 per day): booked per UTC day on a 30-day
|
|
157
|
+
calendar (`/api/sponsor/slots` lists free / held / booked days). Checkout holds the chosen days for 30 minutes
|
|
158
|
+
(`sponsor_slots`), `order.paid` confirms them, and the game shows the sponsor whose `days` include today.
|
|
159
|
+
|
|
160
|
+
After paying, sponsors upload an image that is shrunk to the tier grid (token 16×12 drawn with sextant glyphs into the 8×8 block, banner 66×20),
|
|
161
|
+
reduced to 8 colors and editable pixel by pixel with a terminal-accurate preview.
|
|
162
|
+
|
|
163
|
+
`functions/` holds the Cloud Functions (Node 22): `sponsorCheckout` creates the pending sponsor (holding its days)
|
|
164
|
+
and the Polar checkout, `polarWebhook` activates it on `order.paid` (Standard Webhooks verified, idempotent per order,
|
|
165
|
+
stores the amount as `priority`, confirms the days), `sponsorState` and `sponsorLogo` serve the edit page behind a
|
|
166
|
+
per-sponsor key, `sponsorSlots` serves the calendar. Firestore: `sponsors` (public when active), `sponsor_private`,
|
|
167
|
+
`sponsor_slots` (public). `priority` can also be edited in the console; ties go to whoever paid first. Non-secret parameters live in `functions/.env`
|
|
168
|
+
(see `.env.example`); tokens are Secret Manager secrets:
|
|
169
|
+
|
|
170
|
+
```sh
|
|
171
|
+
firebase functions:secrets:set POLAR_ACCESS_TOKEN
|
|
172
|
+
firebase functions:secrets:set POLAR_WEBHOOK_SECRET
|
|
173
|
+
firebase deploy --only functions,hosting,firestore:rules
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
In the game, active sponsors are fetched once an hour. A **mystery box** sponsor's logo (or a heart) pops out
|
|
177
|
+
of the ? boxes and pays points when grabbed; they are ranked (priority, then who paid first) and the
|
|
178
|
+
top one owns the most boxes and always the first box of a run. The **ranking** sponsor of the day heads the top-10 panel. The single **banner** sponsor (top of the ranking) gets a 66×20 plate, the size of the SUPER DARIO title, with
|
|
179
|
+
"sponsored by NAME" above it: right of the title on the start screen (below it on narrow terminals) and centered on
|
|
180
|
+
top of the pause and game-over screens. All of them are clickable
|
|
181
|
+
(OSC 8 hyperlinks) in Warp, iTerm2, VS Code, kitty, WezTerm and Ghostty. `dario sponsors` lists them.
|
|
182
|
+
|
|
183
|
+
## Development
|
|
184
|
+
|
|
185
|
+
```sh
|
|
186
|
+
npm run typecheck
|
|
187
|
+
npm test
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Layout: `src/game` (physics, spawning, loop), `src/render` (half-block pixel
|
|
191
|
+
renderer, sprites, HUD), `src/launcher` (terminal strategies, pid lock),
|
|
192
|
+
`src/claude` (status file, hook service, settings installer), `src/agents` (Codex / Grok hook files), `src/ide` (launcher extension for VS Code-style IDEs), `src/cli`
|
|
193
|
+
(commands), `hooks/` (scripts Claude Code calls), `skills/dario` (the skill).
|
package/bin/dario
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# Dario launcher: resolves the project root (through symlinks) and runs the TypeScript entry with Node >= 22.18.
|
|
3
|
+
SOURCE="$0"
|
|
4
|
+
while [ -h "$SOURCE" ]; do
|
|
5
|
+
LINK_DIR="$(cd -P "$(dirname "$SOURCE")" && pwd)"
|
|
6
|
+
SOURCE="$(readlink "$SOURCE")"
|
|
7
|
+
case "$SOURCE" in
|
|
8
|
+
/*) ;;
|
|
9
|
+
*) SOURCE="$LINK_DIR/$SOURCE" ;;
|
|
10
|
+
esac
|
|
11
|
+
done
|
|
12
|
+
ROOT="$(cd -P "$(dirname "$SOURCE")/.." && pwd)"
|
|
13
|
+
|
|
14
|
+
find_node() {
|
|
15
|
+
if [ -n "$DARIO_NODE" ] && [ -x "$DARIO_NODE" ]; then
|
|
16
|
+
echo "$DARIO_NODE"
|
|
17
|
+
return 0
|
|
18
|
+
fi
|
|
19
|
+
if command -v node >/dev/null 2>&1; then
|
|
20
|
+
command -v node
|
|
21
|
+
return 0
|
|
22
|
+
fi
|
|
23
|
+
for candidate in /opt/homebrew/bin/node /usr/local/bin/node "$HOME/.volta/bin/node" "$HOME/.local/share/fnm/aliases/default/bin/node"; do
|
|
24
|
+
if [ -x "$candidate" ]; then
|
|
25
|
+
echo "$candidate"
|
|
26
|
+
return 0
|
|
27
|
+
fi
|
|
28
|
+
done
|
|
29
|
+
latest="$(ls -d "$HOME"/.nvm/versions/node/*/bin/node 2>/dev/null | sort -V | tail -n 1)"
|
|
30
|
+
if [ -n "$latest" ]; then
|
|
31
|
+
echo "$latest"
|
|
32
|
+
return 0
|
|
33
|
+
fi
|
|
34
|
+
return 1
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
NODE="$(find_node)" || {
|
|
38
|
+
echo "dario: could not find node (>= 22.18 required). Set DARIO_NODE=/path/to/node." >&2
|
|
39
|
+
exit 1
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
# npm installs ship the bundled dist/main.js (Node will not strip types under node_modules); checkouts run the sources.
|
|
43
|
+
ENTRY="$ROOT/src/main.ts"
|
|
44
|
+
if [ ! -f "$ENTRY" ] && [ -f "$ROOT/dist/main.js" ]; then ENTRY="$ROOT/dist/main.js"; fi
|
|
45
|
+
exec "$NODE" --no-warnings=ExperimentalWarning "$ENTRY" "$@"
|