@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.
Files changed (111) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +145 -0
  3. package/bin/cc-candybar +6 -0
  4. package/dist/index.mjs +185 -0
  5. package/package.json +99 -0
  6. package/plugin/.claude-plugin/plugin.json +11 -0
  7. package/plugin/bin/preview.sh +305 -0
  8. package/plugin/commands/candybar.md +403 -0
  9. package/plugin/templates/config-essential.json +36 -0
  10. package/plugin/templates/config-full.json +55 -0
  11. package/plugin/templates/config-standard.json +39 -0
  12. package/plugin/templates/config-tui-compact.json +48 -0
  13. package/plugin/templates/config-tui-full.json +89 -0
  14. package/plugin/templates/config-tui-standard.json +56 -0
  15. package/plugin/templates/config-tui.json +18 -0
  16. package/plugin/templates/nerd-fonts-sample.txt +5 -0
  17. package/schema/cc-candybar.schema.json +1379 -0
  18. package/src/click/wire.ts +113 -0
  19. package/src/config/action.ts +91 -0
  20. package/src/config/cli.ts +170 -0
  21. package/src/config/default-dsl-config.ts +661 -0
  22. package/src/config/dsl-loader.ts +265 -0
  23. package/src/config/dsl-types.ts +425 -0
  24. package/src/config/loader/actions.ts +530 -0
  25. package/src/config/loader/cache.ts +206 -0
  26. package/src/config/loader/cross-ref.ts +326 -0
  27. package/src/config/loader/cycles.ts +148 -0
  28. package/src/config/loader/diagnostics.ts +99 -0
  29. package/src/config/loader/discovery.ts +182 -0
  30. package/src/config/loader/emit-schema.ts +63 -0
  31. package/src/config/loader/globals.ts +42 -0
  32. package/src/config/loader/helpers.ts +48 -0
  33. package/src/config/loader/layout.ts +688 -0
  34. package/src/config/loader/merge.ts +40 -0
  35. package/src/config/loader/refs.ts +96 -0
  36. package/src/config/loader/segments.ts +120 -0
  37. package/src/config/loader/validate-core.ts +674 -0
  38. package/src/config/loader/variables.ts +260 -0
  39. package/src/daemon/acquire.ts +411 -0
  40. package/src/daemon/cache/git.ts +553 -0
  41. package/src/daemon/cache/render.ts +449 -0
  42. package/src/daemon/cache/session-usage-store.ts +446 -0
  43. package/src/daemon/cache/watchers.ts +245 -0
  44. package/src/daemon/client-debug.ts +120 -0
  45. package/src/daemon/client-stats.ts +129 -0
  46. package/src/daemon/client-transport.ts +273 -0
  47. package/src/daemon/client.ts +75 -0
  48. package/src/daemon/debug-types.ts +91 -0
  49. package/src/daemon/debug.ts +264 -0
  50. package/src/daemon/limits.ts +154 -0
  51. package/src/daemon/log.ts +69 -0
  52. package/src/daemon/parent-watchdog.ts +80 -0
  53. package/src/daemon/paths.ts +127 -0
  54. package/src/daemon/protocol.ts +235 -0
  55. package/src/daemon/render-payload.ts +611 -0
  56. package/src/daemon/server.ts +1103 -0
  57. package/src/daemon/session-state-file.ts +108 -0
  58. package/src/daemon/session-state.ts +237 -0
  59. package/src/daemon/stats.ts +229 -0
  60. package/src/daemon/verbs/index.ts +458 -0
  61. package/src/daemon/verbs/state-validators.ts +708 -0
  62. package/src/demo/dsl.ts +117 -0
  63. package/src/demo/mock-data.ts +67 -0
  64. package/src/demo/statusline.json5 +92 -0
  65. package/src/dsl/node-registry.ts +281 -0
  66. package/src/dsl/render.ts +558 -0
  67. package/src/index.ts +206 -0
  68. package/src/install/index.ts +410 -0
  69. package/src/proc/launch.ts +451 -0
  70. package/src/proc/stats-handle.ts +13 -0
  71. package/src/render/action.ts +458 -0
  72. package/src/render/diagnostic-style.ts +23 -0
  73. package/src/render/diagnostic-text.ts +77 -0
  74. package/src/render/error-glyph.ts +53 -0
  75. package/src/render/outcome-plan.ts +45 -0
  76. package/src/render/picker.ts +231 -0
  77. package/src/render/split-lines.ts +51 -0
  78. package/src/render/strip.ts +103 -0
  79. package/src/segments/cache.ts +131 -0
  80. package/src/segments/context.ts +190 -0
  81. package/src/segments/git.ts +561 -0
  82. package/src/segments/metrics.ts +101 -0
  83. package/src/segments/pricing.ts +452 -0
  84. package/src/segments/session.ts +188 -0
  85. package/src/segments/tmux.ts +74 -0
  86. package/src/template-engine/cells.ts +90 -0
  87. package/src/template-engine/colors.ts +102 -0
  88. package/src/template-engine/engine.ts +108 -0
  89. package/src/template-engine/funcs.ts +216 -0
  90. package/src/template-engine/index.ts +11 -0
  91. package/src/template-engine/layout.ts +112 -0
  92. package/src/template-engine/scope.ts +62 -0
  93. package/src/themes/index.ts +19 -0
  94. package/src/themes/palette-resolvers.ts +86 -0
  95. package/src/themes/policy.ts +79 -0
  96. package/src/themes/session-random.ts +88 -0
  97. package/src/utils/cache.ts +206 -0
  98. package/src/utils/claude.ts +616 -0
  99. package/src/utils/color-support.ts +118 -0
  100. package/src/utils/formatters.ts +77 -0
  101. package/src/utils/logger.ts +5 -0
  102. package/src/utils/outcome.ts +33 -0
  103. package/src/utils/schema-validator.ts +126 -0
  104. package/src/utils/single-flight.ts +57 -0
  105. package/src/utils/terminal-width.ts +43 -0
  106. package/src/utils/terminal.ts +11 -0
  107. package/src/utils/transcript-fs.ts +162 -0
  108. package/src/var-system/index.ts +24 -0
  109. package/src/var-system/sources.ts +1038 -0
  110. package/src/var-system/store.ts +223 -0
  111. 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
+ ![License:MIT](https://img.shields.io/static/v1?label=License&message=MIT&color=blue&style=flat-square)
8
+ [![npm version](https://img.shields.io/npm/v/@promptctl/cc-candybar?style=flat-square)](https://www.npmjs.com/package/@promptctl/cc-candybar)
9
+ [![Dependencies](https://img.shields.io/badge/dependencies-zero-brightgreen)](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)
@@ -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