@promptctl/cc-candybar 1.0.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 +145 -0
- package/bin/cc-candybar +6 -0
- package/dist/index.mjs +185 -0
- package/package.json +99 -0
- package/plugin/.claude-plugin/plugin.json +11 -0
- package/plugin/bin/preview.sh +305 -0
- package/plugin/commands/candybar.md +403 -0
- package/plugin/templates/config-essential.json +36 -0
- package/plugin/templates/config-full.json +55 -0
- package/plugin/templates/config-standard.json +39 -0
- package/plugin/templates/config-tui-compact.json +48 -0
- package/plugin/templates/config-tui-full.json +89 -0
- package/plugin/templates/config-tui-standard.json +56 -0
- package/plugin/templates/config-tui.json +18 -0
- package/plugin/templates/nerd-fonts-sample.txt +5 -0
- package/schema/cc-candybar.schema.json +1379 -0
- package/src/click/wire.ts +113 -0
- package/src/config/action.ts +91 -0
- package/src/config/cli.ts +170 -0
- package/src/config/default-dsl-config.ts +661 -0
- package/src/config/dsl-loader.ts +265 -0
- package/src/config/dsl-types.ts +425 -0
- package/src/config/loader/actions.ts +530 -0
- package/src/config/loader/cache.ts +206 -0
- package/src/config/loader/cross-ref.ts +326 -0
- package/src/config/loader/cycles.ts +148 -0
- package/src/config/loader/diagnostics.ts +99 -0
- package/src/config/loader/discovery.ts +182 -0
- package/src/config/loader/emit-schema.ts +63 -0
- package/src/config/loader/globals.ts +42 -0
- package/src/config/loader/helpers.ts +48 -0
- package/src/config/loader/layout.ts +688 -0
- package/src/config/loader/merge.ts +40 -0
- package/src/config/loader/refs.ts +96 -0
- package/src/config/loader/segments.ts +120 -0
- package/src/config/loader/validate-core.ts +674 -0
- package/src/config/loader/variables.ts +260 -0
- package/src/daemon/acquire.ts +411 -0
- package/src/daemon/cache/git.ts +553 -0
- package/src/daemon/cache/render.ts +449 -0
- package/src/daemon/cache/session-usage-store.ts +446 -0
- package/src/daemon/cache/watchers.ts +245 -0
- package/src/daemon/client-debug.ts +120 -0
- package/src/daemon/client-stats.ts +129 -0
- package/src/daemon/client-transport.ts +273 -0
- package/src/daemon/client.ts +75 -0
- package/src/daemon/debug-types.ts +91 -0
- package/src/daemon/debug.ts +264 -0
- package/src/daemon/limits.ts +154 -0
- package/src/daemon/log.ts +69 -0
- package/src/daemon/parent-watchdog.ts +80 -0
- package/src/daemon/paths.ts +127 -0
- package/src/daemon/protocol.ts +235 -0
- package/src/daemon/render-payload.ts +611 -0
- package/src/daemon/server.ts +1103 -0
- package/src/daemon/session-state-file.ts +108 -0
- package/src/daemon/session-state.ts +237 -0
- package/src/daemon/stats.ts +229 -0
- package/src/daemon/verbs/index.ts +458 -0
- package/src/daemon/verbs/state-validators.ts +708 -0
- package/src/demo/dsl.ts +117 -0
- package/src/demo/mock-data.ts +67 -0
- package/src/demo/statusline.json5 +92 -0
- package/src/dsl/node-registry.ts +281 -0
- package/src/dsl/render.ts +558 -0
- package/src/index.ts +206 -0
- package/src/install/index.ts +410 -0
- package/src/proc/launch.ts +451 -0
- package/src/proc/stats-handle.ts +13 -0
- package/src/render/action.ts +458 -0
- package/src/render/diagnostic-style.ts +23 -0
- package/src/render/diagnostic-text.ts +77 -0
- package/src/render/error-glyph.ts +53 -0
- package/src/render/outcome-plan.ts +45 -0
- package/src/render/picker.ts +231 -0
- package/src/render/split-lines.ts +51 -0
- package/src/render/strip.ts +103 -0
- package/src/segments/cache.ts +131 -0
- package/src/segments/context.ts +190 -0
- package/src/segments/git.ts +561 -0
- package/src/segments/metrics.ts +101 -0
- package/src/segments/pricing.ts +452 -0
- package/src/segments/session.ts +188 -0
- package/src/segments/tmux.ts +74 -0
- package/src/template-engine/cells.ts +90 -0
- package/src/template-engine/colors.ts +102 -0
- package/src/template-engine/engine.ts +108 -0
- package/src/template-engine/funcs.ts +216 -0
- package/src/template-engine/index.ts +11 -0
- package/src/template-engine/layout.ts +112 -0
- package/src/template-engine/scope.ts +62 -0
- package/src/themes/index.ts +19 -0
- package/src/themes/palette-resolvers.ts +86 -0
- package/src/themes/policy.ts +79 -0
- package/src/themes/session-random.ts +88 -0
- package/src/utils/cache.ts +206 -0
- package/src/utils/claude.ts +616 -0
- package/src/utils/color-support.ts +118 -0
- package/src/utils/formatters.ts +77 -0
- package/src/utils/logger.ts +5 -0
- package/src/utils/outcome.ts +33 -0
- package/src/utils/schema-validator.ts +126 -0
- package/src/utils/single-flight.ts +57 -0
- package/src/utils/terminal-width.ts +43 -0
- package/src/utils/terminal.ts +11 -0
- package/src/utils/transcript-fs.ts +162 -0
- package/src/var-system/index.ts +24 -0
- package/src/var-system/sources.ts +1038 -0
- package/src/var-system/store.ts +223 -0
- package/src/var-system/types.ts +57 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Owloops
|
|
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,145 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# CCCandybar
|
|
4
|
+
|
|
5
|
+
**Powerline statusline for Claude Code — daemon-backed, config-driven, zero-config-file required.**
|
|
6
|
+
|
|
7
|
+

|
|
8
|
+
[](https://www.npmjs.com/package/@promptctl/cc-candybar)
|
|
9
|
+
[](https://www.npmjs.com/package/@promptctl/cc-candybar)
|
|
10
|
+
|
|
11
|
+
<img src="images/demo-tui.gif" alt="CCCandybar TUI Mode Demo" width="600"/>
|
|
12
|
+
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
## What it is
|
|
16
|
+
|
|
17
|
+
CCCandybar is a statusline renderer for [Claude Code](https://docs.anthropic.com/en/docs/claude-code). It shows session cost, context usage, git status, model info, rate-limit utilization, and more, configured through a JSON5 DSL with hot-reloading.
|
|
18
|
+
|
|
19
|
+
A background daemon caches git state, usage data, and per-session values across concurrent Claude Code sessions. The renderer connects to the daemon over a Unix socket, so every invocation is fast (~50ms budget) and stateful.
|
|
20
|
+
|
|
21
|
+
## Quick start (macOS)
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pnpm dlx @promptctl/cc-candybar@latest install
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
That single command:
|
|
28
|
+
|
|
29
|
+
1. Builds `~/Applications/CCCandybarURLHandler.app` and registers the `cc-candybar://` URL scheme with macOS Launch Services.
|
|
30
|
+
2. Copies the runtime into `~/Library/Application Support/CCCandybar/url-handler.mjs` (stable path independent of pnpm cache).
|
|
31
|
+
3. Writes the statusline renderer command into `~/.claude/settings.json`.
|
|
32
|
+
|
|
33
|
+
Restart Claude Code. The statusline appears with the bundled default layout (directory, git, model, session, today, context). Cmd-clicking clickable cells fires `cc-candybar://` URL verbs that the daemon dispatches.
|
|
34
|
+
|
|
35
|
+
## Customization
|
|
36
|
+
|
|
37
|
+
Drop a `.cc-candybar.json5` (or `.cc-candybar.json` — both extensions are accepted) at any of these locations (highest precedence first):
|
|
38
|
+
|
|
39
|
+
1. `$CC_CANDYBAR_CONFIG` (literal path, supports `~` expansion)
|
|
40
|
+
2. `<project>/.cc-candybar.json5` (then `.json` at the same location)
|
|
41
|
+
3. `<cwd>/.cc-candybar.json5` (then `.json`)
|
|
42
|
+
4. `$XDG_CONFIG_HOME/cc-candybar/config.json5` (then `.json`; defaults to `~/.config/cc-candybar/config.json5`)
|
|
43
|
+
|
|
44
|
+
JSON is a strict subset of JSON5, so the same parser handles both — `.json5` is the documented format (supports inline comments, trailing commas, unquoted keys), `.json` is the legacy/compat extension. When both exist at the same location, `.json5` wins and the bar shows a persistent warning so you can remove the shadowed duplicate.
|
|
45
|
+
|
|
46
|
+
The file is a **complete** replacement for the bundled default — no merge layer. Start by copying `src/demo/statusline.json5` from the repo as a minimal example, or `src/config/default-dsl-config.ts` for the full standard library.
|
|
47
|
+
|
|
48
|
+
```json5
|
|
49
|
+
// minimal example — user, directory, branch, model, session, clock
|
|
50
|
+
{
|
|
51
|
+
globals: { palette: 'textual-dark' },
|
|
52
|
+
variables: {
|
|
53
|
+
user: { kind: 'env', name: 'USER', default: 'anon' },
|
|
54
|
+
cwd: { kind: 'input', path: 'workspace.current_dir', default: '?' },
|
|
55
|
+
branch: { kind: 'shell', command: 'git branch --show-current',
|
|
56
|
+
cache: { ttl: '5s' }, default: '' },
|
|
57
|
+
clock: { kind: 'time', layout: '15:04:05', cache: { ttl: '1s' } },
|
|
58
|
+
// per-segment hue rotation (degrees), read by the renderer. A literal pins
|
|
59
|
+
// it; make it `{ kind: 'state', key: 'hue-step' }` + a stepper widget to
|
|
60
|
+
// adjust it live.
|
|
61
|
+
'hue.step': { kind: 'literal', value: 14 },
|
|
62
|
+
},
|
|
63
|
+
segments: {
|
|
64
|
+
user: { template: ' {{ .user }} ', bg: 'primary', fg: 'auto' },
|
|
65
|
+
directory: { template: ' {{ basename .cwd }} ', bg: 'surface', fg: 'foreground' },
|
|
66
|
+
branch: { template: ' {{ .branch }} ', bg: 'accent', fg: 'auto',
|
|
67
|
+
when: '{{ ne .branch "" }}' },
|
|
68
|
+
clock: { template: ' {{ .clock }} ', bg: 'primary', fg: 'auto' },
|
|
69
|
+
},
|
|
70
|
+
layout: ['user', 'directory', 'branch', 'clock'],
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Saving the file triggers a hot-reload of every active session.
|
|
75
|
+
|
|
76
|
+
## Architecture
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
┌─────────────┐ Unix socket ┌──────────────────┐
|
|
80
|
+
│ Claude Code │ ──────────────► │ cc-candybar daemon│
|
|
81
|
+
│ (hook) │ render req │ │
|
|
82
|
+
│ │ ◄────────────── │ git cache │
|
|
83
|
+
└─────────────┘ ANSI output │ usage cache │
|
|
84
|
+
│ session state │
|
|
85
|
+
│ render cache │
|
|
86
|
+
└──────────────────┘
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
- **Daemon** (`src/daemon/`) — long-lived background process. One per user. Caches git state via filesystem watchers, usage data, and per-session key/value state. Runs until it exits on an RSS backstop (default 512 MB) or the host restarts; there is no idle or age timeout.
|
|
90
|
+
- **Client** (`src/daemon/client.ts`) — each Claude Code hook invocation connects to the daemon, sends a render request, and prints the ANSI response. On failure, spawns a fresh daemon and emits empty output.
|
|
91
|
+
- **Renderer** (`src/render/`, `src/segments/`) — segments produce styled output from cached data. Themes cascade from defaults through palette resolution using OKLCH color math.
|
|
92
|
+
- **TUI grid** (`src/tui/`) — CSS Grid-inspired layout engine with breakpoints, column sizing (`auto`, `1fr`, fixed), spanning, and automatic culling of empty segments.
|
|
93
|
+
|
|
94
|
+
## Segments
|
|
95
|
+
|
|
96
|
+
| Segment | Shows | Symbol |
|
|
97
|
+
|---------|-------|--------|
|
|
98
|
+
| directory | CWD name (`full`, `fish`, `basename`) | — |
|
|
99
|
+
| git | Branch, SHA, working tree, upstream, stash, tags | `⎇` |
|
|
100
|
+
| model | Current Claude model | `✱` |
|
|
101
|
+
| session | Per-session cost/tokens/breakdown | `§` |
|
|
102
|
+
| today | Daily usage with budget monitoring | `☉` |
|
|
103
|
+
| context | Context window usage with auto-compact threshold | `◔` |
|
|
104
|
+
| block | 5-hour rate-limit utilization | `◱` |
|
|
105
|
+
| weekly | 7-day rolling rate-limit utilization | `◑` |
|
|
106
|
+
| metrics | Response time, duration, lines changed | `⧖` |
|
|
107
|
+
| version | Claude Code version | `◈` |
|
|
108
|
+
| tmux | tmux session name | — |
|
|
109
|
+
| sessionId | Session identifier (cmd-click to copy) | `⌗` |
|
|
110
|
+
| env | Arbitrary environment variable | `⚙` |
|
|
111
|
+
|
|
112
|
+
Each segment is a DSL declaration with a `template` (text + interpolation + style functions), a `bg`/`fg` palette spec, and optional `when` predicate. Templates compose freely — every formatter in the bundled function library (`formatCost`, `formatTokens`, `formatLongTimeRemaining`, `budgetStatus`, `link`, `urlEncode`, the sprig string/list/dict library, …) is available in every segment.
|
|
113
|
+
|
|
114
|
+
## Themes
|
|
115
|
+
|
|
116
|
+
The DSL config picks a base palette via `globals.palette` (e.g. `textual-dark`, `gruvbox`). Each segment may override with its own `palette:` field, and `bg`/`fg` evaluate as palette spec names (`primary`, `surface`, `panel`, `accent`, `foreground`, `auto`, `warning`, `error`, …). Color math runs through OKLCH for perceptual uniformity; the `hue.step` variable (read via the conventional `HUE_STEP_VAR` name) rotates adjacent segments by that many degrees to keep them visually distinct without authoring per-segment colors — a literal pins it, a `state` var driven by a stepper widget makes it adjustable live.
|
|
117
|
+
|
|
118
|
+
## Installation
|
|
119
|
+
|
|
120
|
+
Requires Node.js 18+, Claude Code, and Git 2.0+. For best display, install a [Nerd Font](https://www.nerdfonts.com/) so the powerline glyphs render correctly.
|
|
121
|
+
|
|
122
|
+
### Manual setup
|
|
123
|
+
|
|
124
|
+
Edit `~/.claude/settings.json` directly. Pin the version — don't use `@latest` (pnpm caches aggressively and won't pick up new releases).
|
|
125
|
+
|
|
126
|
+
```json
|
|
127
|
+
{
|
|
128
|
+
"statusLine": {
|
|
129
|
+
"type": "command",
|
|
130
|
+
"command": "pnpm dlx @promptctl/cc-candybar@0.2.3"
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Config file
|
|
136
|
+
|
|
137
|
+
Customization lives in `.cc-candybar.json5`. See the [Customization](#customization) section above for the resolution order. Saved edits hot-reload — no restart needed.
|
|
138
|
+
|
|
139
|
+
## Contributing
|
|
140
|
+
|
|
141
|
+
Contributions welcome. See [CONTRIBUTORS.md](CONTRIBUTORS.md) for people who have contributed outside of GitHub PRs.
|
|
142
|
+
|
|
143
|
+
## License
|
|
144
|
+
|
|
145
|
+
[MIT](LICENSE)
|
package/bin/cc-candybar
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
echo "cc-candybar: native binary not installed." >&2
|
|
3
|
+
echo "Postinstall did not stage a platform binary. Reinstall on darwin-arm64," >&2
|
|
4
|
+
echo "darwin-x64, linux-x64, or linux-arm64; or open an issue at" >&2
|
|
5
|
+
echo "https://github.com/promptctl/cc-candybar/issues." >&2
|
|
6
|
+
exit 1
|