honeytree 1.1.6 → 1.2.1
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 +39 -147
- package/bin/honeydew.js +70 -6
- package/package.json +11 -8
- package/src/animation-keyframes.js +890 -0
- package/src/animation.js +151 -0
- package/src/ascii-tree.js +21 -0
- package/src/auth.js +83 -0
- package/src/components/ForestApp.js +404 -0
- package/src/components/ForestScene.js +26 -0
- package/src/components/LiveTree.js +14 -0
- package/src/components/StatsBar.js +70 -0
- package/src/components/TreeInfoPopup.js +28 -0
- package/src/components/UnlockCelebration.js +40 -0
- package/src/growth.js +32 -0
- package/src/init.js +48 -2
- package/src/plant-real.js +129 -0
- package/src/plant.js +39 -17
- package/src/renderer.js +131 -12
- package/src/rewards.js +119 -0
- package/src/session.js +34 -0
- package/src/sprites.js +72 -6
- package/src/stdin.js +28 -0
- package/src/sync.js +44 -0
- package/src/transcript.js +62 -0
- package/src/turn.js +54 -0
- package/src/varieties.js +30 -0
- package/src/viewer2d.js +24 -0
- package/src/markdown.js +0 -77
- package/src/viewer.js +0 -234
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Varun Nukala
|
|
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,186 +1,78 @@
|
|
|
1
1
|
# Honeytree
|
|
2
2
|
|
|
3
|
+
> *your codebase is a forest*
|
|
4
|
+
|
|
3
5
|
[](https://www.npmjs.com/package/honeytree)
|
|
4
6
|
[](https://github.com/Varun2009178/honeytree/blob/main/LICENSE)
|
|
5
7
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
Each prompt plants a new tree. Each tree grows over time. Your forest evolves from a quiet clearing into an ancient woodland — and it never resets.
|
|
9
|
-
|
|
10
|
-
---
|
|
8
|
+
Honeytree grows a pixel-art forest in your terminal as you code with Claude Code. Then it lets you plant real ones.
|
|
11
9
|
|
|
12
|
-
## Quick
|
|
10
|
+
## Quick start
|
|
13
11
|
|
|
14
12
|
```bash
|
|
15
13
|
npm install -g honeytree
|
|
16
14
|
honeytree init
|
|
15
|
+
honeytree login
|
|
17
16
|
honeytree
|
|
18
17
|
```
|
|
19
18
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
1. **Install** the CLI globally
|
|
23
|
-
2. **Init** creates your forest file and registers a Claude Code hook
|
|
24
|
-
3. **Run the viewer** in a separate terminal to watch your forest grow
|
|
25
|
-
|
|
26
|
-
After setup, trees are planted automatically after every Claude Code response. No manual steps needed.
|
|
27
|
-
|
|
28
|
-
---
|
|
29
|
-
|
|
30
|
-
## How It Works
|
|
31
|
-
|
|
32
|
-
When you run `honeytree init`, it does two things:
|
|
33
|
-
|
|
34
|
-
- Creates `~/.honeydew/forest.json` to store your forest state
|
|
35
|
-
- Adds a `Stop` hook to `~/.claude/settings.json` that runs after every Claude Code response
|
|
36
|
-
|
|
37
|
-
From then on, every time Claude Code responds to a prompt, a new tree is planted in your forest automatically. Open the viewer in a second terminal to watch them grow in real time.
|
|
38
|
-
|
|
39
|
-
---
|
|
40
|
-
|
|
41
|
-
## Streaks
|
|
42
|
-
|
|
43
|
-
Honeytree tracks your coding streak — consecutive days where you use Claude Code.
|
|
44
|
-
|
|
45
|
-
- **Active streak**: The viewer and badge show your current streak count (e.g. `7-day streak`)
|
|
46
|
-
- **Broken streak**: Miss a day and your forest starts **wilting** — trees desaturate toward brown, and fog rolls in across the scene
|
|
47
|
-
- **Recovery**: Your next prompt resets the streak to 1 and clears the wilting immediately
|
|
48
|
-
|
|
49
|
-
The longer you go without coding, the worse it gets:
|
|
50
|
-
|
|
51
|
-
| Days idle | Effect |
|
|
52
|
-
|----------:|--------|
|
|
53
|
-
| 1 | Light desaturation, sparse fog |
|
|
54
|
-
| 2 | Noticeable browning, moderate fog |
|
|
55
|
-
| 3 | Heavy browning, dense fog |
|
|
56
|
-
| 4+ | Near-dead forest, thick fog |
|
|
57
|
-
|
|
58
|
-
Plant a tree to bring it all back to life.
|
|
59
|
-
|
|
60
|
-
---
|
|
61
|
-
|
|
62
|
-
## Badge
|
|
63
|
-
|
|
64
|
-
Generate a badge for your GitHub README that shows your forest stats and links back to [Honeytree](https://github.com/Varun2009178/honeytree):
|
|
65
|
-
|
|
66
|
-
```bash
|
|
67
|
-
honeytree badge
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
This creates a `honeytree-badge.svg` file in your current directory and prints the markdown to embed it:
|
|
19
|
+
`honeytree init` registers a Claude Code hook that plants a tree after every prompt. `honeytree login` links your terminal to your account so your forest syncs to the cloud. Open a second terminal pane, run `honeytree`, and watch your forest grow in real time.
|
|
71
20
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
The badge displays your tree count and streak status. It links to the [Honeytree repo](https://github.com/Varun2009178/honeytree) so anyone who sees it can install it themselves.
|
|
21
|
+
**Live growth:** keep `honeytree` open in a second pane while you use Claude Code — the
|
|
22
|
+
current turn's tree grows in real time as the response streams, and bigger turns grow
|
|
23
|
+
taller trees. One prompt still plants one tree.
|
|
77
24
|
|
|
78
|
-
|
|
79
|
-
|-------|-------------|---------|
|
|
80
|
-
| Active streak | Green | `42 trees · 7d streak` |
|
|
81
|
-
| Wilting | Orange-red | `42 trees · wilting` |
|
|
82
|
-
| No streak data | Grey | `42 trees` |
|
|
25
|
+
## Tree varieties
|
|
83
26
|
|
|
84
|
-
|
|
27
|
+
New trees are drawn from the varieties you've unlocked. Everyone starts with the
|
|
28
|
+
standard species (birch, willow); planting real trees unlocks more:
|
|
85
29
|
|
|
86
|
-
|
|
30
|
+
| Variety | Real trees | Look |
|
|
31
|
+
|---------|-----------|------|
|
|
32
|
+
| Cherry Blossom | 1 | Pink blossom canopy |
|
|
33
|
+
| Pine | 5 | Tall evergreen |
|
|
34
|
+
| Oak | 10 | Broad rounded canopy |
|
|
35
|
+
| Ancient | 25 | Rare tall golden tree |
|
|
36
|
+
| Mythic | 50 | Glowing purple tree |
|
|
87
37
|
|
|
88
|
-
|
|
38
|
+
The first time a new variety is unlocked, the viewer opens with a full-screen
|
|
39
|
+
celebration screen. Check progress anytime with `honeytree rewards`.
|
|
89
40
|
|
|
90
|
-
|
|
41
|
+
## Plant real trees
|
|
91
42
|
|
|
92
43
|
```bash
|
|
93
|
-
honeytree
|
|
44
|
+
honeytree plant
|
|
94
45
|
```
|
|
95
46
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
- Your Honeytree badge (links to the [Honeytree repo](https://github.com/Varun2009178/honeytree))
|
|
99
|
-
- Stats: tree count, streak, biome
|
|
100
|
-
- A plain-text rendering of your forest (tree silhouettes, stars, ground)
|
|
101
|
-
- Total prompts and forest age
|
|
102
|
-
|
|
103
|
-
Commit `FOREST.md` to your repo root so your team can see the forest. When teammates see it, they can install Honeytree themselves — one install spreads to the whole team.
|
|
104
|
-
|
|
105
|
-
Run `honeytree badge` first to generate the SVG, then `honeytree md` to generate the markdown that embeds it.
|
|
106
|
-
|
|
107
|
-
---
|
|
108
|
-
|
|
109
|
-
## Biomes
|
|
110
|
-
|
|
111
|
-
Your forest evolves visually as it grows — the sky, ground, and atmosphere all change:
|
|
112
|
-
|
|
113
|
-
| Trees | Biome | What changes |
|
|
114
|
-
|------:|-------|-------------|
|
|
115
|
-
| 0–9 | Clearing | Sparse stars, light ground |
|
|
116
|
-
| 10–24 | Grove | More stars, richer ground |
|
|
117
|
-
| 25–49 | Woodland | Dense canopy, varied starlight |
|
|
118
|
-
| 50–99 | Old Growth | Deep greens, warm starlight |
|
|
119
|
-
| 100+ | Ancient Forest | Richest palette, brightest sky |
|
|
120
|
-
|
|
121
|
-
Trees are never deleted. The forest only grows.
|
|
122
|
-
|
|
123
|
-
---
|
|
124
|
-
|
|
125
|
-
## Tree Species
|
|
126
|
-
|
|
127
|
-
Five species are randomly assigned when a tree is planted:
|
|
47
|
+
`honeytree plant` shows how many real trees you've unlocked (every 50 virtual trees = 1 real tree), opens a $1 checkout via the Good API, then prints your receipt and any newly-unlocked varieties right in the terminal. A keepsake receipt also lands in your inbox.
|
|
128
48
|
|
|
129
|
-
|
|
130
|
-
|---------|------|
|
|
131
|
-
| Oak | Wide, rounded canopy |
|
|
132
|
-
| Pine | Tall, triangular shape |
|
|
133
|
-
| Birch | Light trunk, bright leaves |
|
|
134
|
-
| Willow | Drooping canopy |
|
|
135
|
-
| Cherry | Pink blossoms |
|
|
49
|
+
## Your public profile
|
|
136
50
|
|
|
137
|
-
|
|
51
|
+
Every account gets a public profile at `tryhoney.xyz/<username>` — your forest, totals,
|
|
52
|
+
CO₂ impact, and unlocked varieties, ready to share.
|
|
138
53
|
|
|
139
54
|
---
|
|
140
55
|
|
|
141
|
-
## CLI
|
|
56
|
+
## CLI reference
|
|
142
57
|
|
|
143
|
-
| Command |
|
|
58
|
+
| Command | What it does |
|
|
144
59
|
|---------|-------------|
|
|
145
|
-
| `honeytree
|
|
146
|
-
| `honeytree` |
|
|
147
|
-
| `honeytree plant` | Plant
|
|
148
|
-
| `honeytree
|
|
149
|
-
| `honeytree
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
The viewer adapts to your terminal width — expand your terminal and new trees will spread across the full width.
|
|
156
|
-
|
|
157
|
-
Press `Ctrl+C` to exit. The viewer shows a summary of your forest when you close it.
|
|
158
|
-
|
|
159
|
-
### Reading the Stats Bar
|
|
160
|
-
|
|
161
|
-
Below your forest you'll see a stats bar like this:
|
|
162
|
-
|
|
163
|
-
```
|
|
164
|
-
honeytree · 42 trees · 7-day streak · ████████░░░░ next: oak [woodland]
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
Here's what each part means:
|
|
168
|
-
|
|
169
|
-
| Segment | What it tells you |
|
|
170
|
-
|---------|-------------------|
|
|
171
|
-
| `42 trees` | Total trees in your forest — one planted per prompt, never deleted |
|
|
172
|
-
| `7-day streak` | Consecutive days you've used Claude Code. Resets to 1 if you skip a day |
|
|
173
|
-
| `wilting (2d idle)` | Appears instead of streak when you've been inactive — your forest is dying |
|
|
174
|
-
| `████████░░░░` | Progress bar toward the next milestone (10, 25, 50, 100, 250, 500, 1000 trees) |
|
|
175
|
-
| `next: oak` | The species of the next tree that will be planted |
|
|
176
|
-
| `[woodland]` | Your current biome — evolves as your tree count grows |
|
|
60
|
+
| `honeytree` | Open the forest viewer |
|
|
61
|
+
| `honeytree init` | Register Claude Code hook |
|
|
62
|
+
| `honeytree plant` | Plant your unlocked real trees |
|
|
63
|
+
| `honeytree login` | Link terminal to your account |
|
|
64
|
+
| `honeytree logout` | Remove stored credentials |
|
|
65
|
+
| `honeytree sync` | Push forest to cloud |
|
|
66
|
+
| `honeytree rewards` | Show variety unlocks and progress |
|
|
67
|
+
| `honeytree status` | Check login status |
|
|
68
|
+
| `honeytree badge` | Generate `honeytree-badge.svg` |
|
|
177
69
|
|
|
178
70
|
---
|
|
179
71
|
|
|
180
72
|
## Requirements
|
|
181
73
|
|
|
182
74
|
- Node.js 18+
|
|
183
|
-
-
|
|
75
|
+
- A terminal with true color support (most modern terminals)
|
|
184
76
|
|
|
185
77
|
## Links
|
|
186
78
|
|
package/bin/honeydew.js
CHANGED
|
@@ -5,20 +5,84 @@ const command = process.argv[2];
|
|
|
5
5
|
if (command === "init") {
|
|
6
6
|
const { init } = await import("../src/init.js");
|
|
7
7
|
await init();
|
|
8
|
+
} else if (command === "__session") {
|
|
9
|
+
// Hidden: UserPromptSubmit hook — marks the start of a turn (token baseline + chosen tree).
|
|
10
|
+
try {
|
|
11
|
+
const { readStdin } = await import("../src/stdin.js");
|
|
12
|
+
const { startTurn } = await import("../src/turn.js");
|
|
13
|
+
const payload = JSON.parse((await readStdin()) || "{}");
|
|
14
|
+
startTurn(payload);
|
|
15
|
+
} catch {}
|
|
16
|
+
} else if (command === "__tick") {
|
|
17
|
+
// Hidden: Stop hook — finalizes this turn's token-sized tree (random fallback).
|
|
18
|
+
const { tick } = await import("../src/plant.js");
|
|
19
|
+
let shape = null;
|
|
20
|
+
try {
|
|
21
|
+
const { readStdin } = await import("../src/stdin.js");
|
|
22
|
+
const { computeTickShape } = await import("../src/turn.js");
|
|
23
|
+
const payload = JSON.parse((await readStdin()) || "{}");
|
|
24
|
+
shape = computeTickShape(payload);
|
|
25
|
+
} catch {}
|
|
26
|
+
await tick(shape);
|
|
8
27
|
} else if (command === "plant") {
|
|
9
|
-
const { plant } = await import("../src/plant.js");
|
|
28
|
+
const { plant } = await import("../src/plant-real.js");
|
|
10
29
|
await plant();
|
|
11
30
|
} else if (command === "badge") {
|
|
12
31
|
const { badge } = await import("../src/badge.js");
|
|
13
32
|
await badge();
|
|
14
|
-
} else if (command === "md") {
|
|
15
|
-
const { generateForestMd } = await import("../src/markdown.js");
|
|
16
|
-
await generateForestMd();
|
|
17
33
|
} else if (!command) {
|
|
18
|
-
const { viewer } = await import("../src/
|
|
34
|
+
const { viewer } = await import("../src/viewer2d.js");
|
|
19
35
|
await viewer();
|
|
36
|
+
} else if (command === "login") {
|
|
37
|
+
const { loginWithDevice } = await import("../src/auth.js");
|
|
38
|
+
const success = await loginWithDevice();
|
|
39
|
+
if (success) {
|
|
40
|
+
const { syncNow } = await import("../src/sync.js");
|
|
41
|
+
console.log(" Syncing your forest...");
|
|
42
|
+
await syncNow();
|
|
43
|
+
console.log(" Forest synced to the cloud.");
|
|
44
|
+
}
|
|
45
|
+
} else if (command === "logout") {
|
|
46
|
+
const { clearAuth } = await import("../src/auth.js");
|
|
47
|
+
clearAuth();
|
|
48
|
+
console.log("Logged out.");
|
|
49
|
+
} else if (command === "sync") {
|
|
50
|
+
const { isLoggedIn } = await import("../src/auth.js");
|
|
51
|
+
if (!isLoggedIn()) {
|
|
52
|
+
console.log("Not logged in. Run: honeytree login");
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
const { syncNow } = await import("../src/sync.js");
|
|
56
|
+
const { syncRewards } = await import("../src/rewards.js");
|
|
57
|
+
console.log(" Syncing forest...");
|
|
58
|
+
await syncNow();
|
|
59
|
+
const rewards = await syncRewards();
|
|
60
|
+
if (rewards && rewards.badges.length > 0) {
|
|
61
|
+
console.log(` Badges: ${rewards.badges.map(b => b.label).join(", ")}`);
|
|
62
|
+
if (rewards.cherry) console.log(" Cherry blossom trees unlocked!");
|
|
63
|
+
}
|
|
64
|
+
console.log(" Done.");
|
|
65
|
+
} else if (command === "rewards") {
|
|
66
|
+
const { isLoggedIn } = await import("../src/auth.js");
|
|
67
|
+
const { syncRewards, printRewardsStatus } = await import("../src/rewards.js");
|
|
68
|
+
const { readForest } = await import("../src/state.js");
|
|
69
|
+
if (isLoggedIn()) {
|
|
70
|
+
console.log(" Fetching rewards...");
|
|
71
|
+
await syncRewards();
|
|
72
|
+
}
|
|
73
|
+
const forest = readForest();
|
|
74
|
+
const realTrees = 0; // local doesn't know real trees; printRewardsStatus uses cached data
|
|
75
|
+
printRewardsStatus(realTrees);
|
|
76
|
+
} else if (command === "status") {
|
|
77
|
+
const { getAuth } = await import("../src/auth.js");
|
|
78
|
+
const auth = getAuth();
|
|
79
|
+
if (auth && auth.username) {
|
|
80
|
+
console.log(`Logged in as ${auth.username}`);
|
|
81
|
+
} else {
|
|
82
|
+
console.log("Not logged in. Run: honeytree login");
|
|
83
|
+
}
|
|
20
84
|
} else {
|
|
21
85
|
console.error(`Unknown command: ${command}`);
|
|
22
|
-
console.error("Usage: honeytree [init|plant|badge|
|
|
86
|
+
console.error("Usage: honeytree [init|login|plant|badge|logout|sync|status|rewards]");
|
|
23
87
|
process.exit(1);
|
|
24
88
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "honeytree",
|
|
3
|
-
"version": "1.1
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.2.1",
|
|
4
|
+
"description": "code with claude, and watch your forest grow! ",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"honeytree": "./bin/honeydew.js"
|
|
@@ -11,16 +11,17 @@
|
|
|
11
11
|
"src"
|
|
12
12
|
],
|
|
13
13
|
"scripts": {
|
|
14
|
-
"test": "node --test test/*.test.js"
|
|
14
|
+
"test": "FORCE_COLOR=1 node --test test/*.test.js"
|
|
15
15
|
},
|
|
16
16
|
"keywords": [
|
|
17
17
|
"cli",
|
|
18
18
|
"terminal",
|
|
19
19
|
"forest",
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
20
|
+
"3d",
|
|
21
|
+
"codebase",
|
|
22
|
+
"visualization",
|
|
23
|
+
"point-cloud",
|
|
24
|
+
"ascii-art"
|
|
24
25
|
],
|
|
25
26
|
"repository": {
|
|
26
27
|
"type": "git",
|
|
@@ -34,7 +35,9 @@
|
|
|
34
35
|
"license": "MIT",
|
|
35
36
|
"dependencies": {
|
|
36
37
|
"chalk": "^5.4.1",
|
|
37
|
-
"honeytree": "^1.
|
|
38
|
+
"honeytree": "^1.2.0",
|
|
39
|
+
"ink": "^7.0.4",
|
|
40
|
+
"react": "^19.2.6"
|
|
38
41
|
},
|
|
39
42
|
"engines": {
|
|
40
43
|
"node": ">=18"
|