@litfamily/litclaude 1.0.22 โ 1.0.24
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/CHANGELOG.md +14 -0
- package/README.md +8 -8
- package/README_ko-KR.md +8 -8
- package/docs/assets/readme/badge-version.svg +1 -1
- package/docs/hooks.md +64 -25
- package/package.json +1 -1
- package/plugins/litclaude/.claude-plugin/plugin.json +3 -3
- package/plugins/litclaude/bin/litclaude-hud.js +2 -5
- package/plugins/litclaude/bin/litclaude-mcp.js +1 -1
- package/plugins/litclaude/hooks/lit-band-client.mjs +1 -1
- package/plugins/litclaude/hooks/lit-mod.mjs +83 -10
- package/plugins/litclaude/lib/canonical-skill-resources.mjs +4 -4
- package/plugins/litclaude/lib/hud-ignition.mjs +7 -37
- package/plugins/litclaude/lib/mod/frame.mjs +270 -194
- package/plugins/litclaude/lib/mod/layout.mjs +0 -23
- package/plugins/litclaude/lib/mod/render.mjs +4 -8
- package/plugins/litclaude/lib/mod/settings.mjs +52 -4
- package/plugins/litclaude/lib/mod/skills.mjs +81 -0
- package/plugins/litclaude/lib/mod/state.mjs +38 -1
- package/plugins/litclaude/lib/mod/timeline.mjs +30 -2
- package/plugins/litclaude/lib/mod/view.mjs +62 -10
- package/plugins/litclaude/lib/office-runtime-lock/package-lock.json +167 -119
- package/plugins/litclaude/lib/office-runtime-lock/package.json +1 -1
- package/plugins/litclaude/skills/readme-studio/templates/hyperframes-cover/package-lock.json +169 -121
- package/plugins/litclaude/skills/readme-studio/templates/remotion-cover/package-lock.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.0.24 - 2026-10-12
|
|
4
|
+
|
|
5
|
+
- The LIT card no longer drops to idle while background work is still running. When the main turn ends after starting background subagents or a workflow, the card stays at work and counts the running agents until the last one finishes, and it never reads `DONE` while an agent is still busy. A workflow's agents now count too, and a subagent that finishes in the middle of a turn no longer dims the chips of the request that is still running. An agent that never reports back stops counting after 30 quiet minutes, so it cannot hold the card at work.
|
|
6
|
+
- The README shows the LIT card as it really appears: resting before anything runs, at work with the skill's chip lit, and after the turn, when the chip dims into the recent list.
|
|
7
|
+
- The README walks through automatic handoff with terminal pictures: turning it on with `lit-handoff auto on 65`, checking and turning it off, the reminder to run `/compact`, and the two shell variables that switch it on before Claude Code starts.
|
|
8
|
+
- The install section has a prompt you can paste into a coding agent so it installs LitClaude for you. The agent shows what would change and waits for your yes, runs the doctor, and reminds you to restart Claude Code.
|
|
9
|
+
- The office runtime now pins sharp 0.35.5, and the README Studio cover templates use sharp 0.35.5 and source-map-js 1.2.2.
|
|
10
|
+
|
|
11
|
+
## 1.0.23 - 2026-10-12
|
|
12
|
+
|
|
13
|
+
- The LIT card above the prompt now stays on screen for the whole session, so you can still see the status after the work ends. It is a small four-row card in the colours of your status line. The top edge names the workflow and the current phase. Below it are the plan, work and review steps with the progress of the plan or goal. Every LitClaude skill that runs gets its own chip, several at once. A chip is bright while its request is running and dims into a recent list when the turn ends. At the bottom are the context use, the five-hour usage window and the Git branch. The card fits narrow terminals by leaving out the least important parts and never wraps. The `band` setting now defaults to `always`; `auto` brings back the old behaviour, and `off` hides the card.
|
|
14
|
+
- The status line no longer shows the `๐ฅ LIT IGNITED ยท <workflow> ๐ฅ` mark. It took up so much room that the model, context and usage figures were cut off, and the card now shows which workflow is active.
|
|
15
|
+
- Project rules now fit in the skill context when LitClaude is installed under a long folder path. Before, a long install path could cut off the first line of a rule or leave the rules out entirely.
|
|
16
|
+
|
|
3
17
|
## 1.0.22 - 2026-10-11
|
|
4
18
|
|
|
5
19
|
- The README is shorter for first-time readers. It says what LitClaude does, how to install it and what to type first, and the detailed material now lives in docs pages (guide, skills, Jev, development) in English and Korean. The GitHub page also plays a short film of a real session.
|
package/README.md
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
<p align="center"><picture><source media="(prefers-reduced-motion: reduce)" srcset="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.
|
|
1
|
+
<p align="center"><picture><source media="(prefers-reduced-motion: reduce)" srcset="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.24/docs/assets/cover-motion-still.webp" /><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.24/docs/assets/cover-motion.webp" width="100%" alt="LitFamily motion cover: five armored robots power on one by one, the LitClaude robot wakes with glowing eyes and a lit frame, then LITFAMILY and KEEP THE WORK LIT. light up." /></picture></p>
|
|
2
2
|
|
|
3
3
|
<h1 align="center">LitClaude</h1>
|
|
4
4
|
<p align="center"><strong>Keep the work lit.</strong></p>
|
|
5
5
|
<p align="center">A Claude Code plugin that helps every session plan the work, build it, check it, and leave a note the next session can pick up.</p>
|
|
6
6
|
<p align="center">
|
|
7
|
-
<img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.
|
|
8
|
-
<a href="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.
|
|
7
|
+
<img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.24/docs/assets/readme/badge-version.svg" alt="1.0.24" />
|
|
8
|
+
<a href="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.24/LICENSE"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.24/docs/assets/readme/badge-license.svg" alt="MIT license" /></a>
|
|
9
9
|
</p>
|
|
10
10
|
<p align="center">
|
|
11
|
-
<a href="https://github.com/wjgoarxiv/litclaude#readme">Full guide and skills gallery on GitHub</a> ยท <a href="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.
|
|
11
|
+
<a href="https://github.com/wjgoarxiv/litclaude#readme">Full guide and skills gallery on GitHub</a> ยท <a href="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.24/README_ko-KR.md">ํ๊ตญ์ด</a>
|
|
12
12
|
</p>
|
|
13
13
|
|
|
14
14
|
Add `lit` to a Claude Code prompt and Claude pins the goal, writes a failing test first,
|
|
@@ -73,7 +73,7 @@ the `/plugin` menu.
|
|
|
73
73
|
## More
|
|
74
74
|
|
|
75
75
|
- [Full guide and skills gallery on GitHub](https://github.com/wjgoarxiv/litclaude#readme)
|
|
76
|
-
- [Privacy and network behavior](https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.
|
|
77
|
-
- [Migration and ownership conflicts](https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.
|
|
78
|
-
- [Release history](https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.
|
|
79
|
-
- [MIT license](https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.
|
|
76
|
+
- [Privacy and network behavior](https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.24/docs/privacy.md)
|
|
77
|
+
- [Migration and ownership conflicts](https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.24/docs/migration.md)
|
|
78
|
+
- [Release history](https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.24/CHANGELOG.md)
|
|
79
|
+
- [MIT license](https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.24/LICENSE)
|
package/README_ko-KR.md
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
<p align="center"><picture><source media="(prefers-reduced-motion: reduce)" srcset="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.
|
|
1
|
+
<p align="center"><picture><source media="(prefers-reduced-motion: reduce)" srcset="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.24/docs/assets/cover-motion-still.webp" /><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.24/docs/assets/cover-motion.webp" width="100%" alt="LitFamily ๋ชจ์
์ปค๋ฒ: ๋ค์ฏ ๋ก๋ด ํจ๋์ด ์ฐจ๋ก๋ก ์ผ์ง๊ณ , LitClaude ๋ก๋ด์ ๋๊ณผ ํ
๋๋ฆฌ๊ฐ ๋น๋ ๋ค LITFAMILY์ KEEP THE WORK LIT. ๋ฌธ๊ตฌ๊ฐ ๋ฐ์์ง๋ ์์" /></picture></p>
|
|
2
2
|
|
|
3
3
|
<h1 align="center">LitClaude</h1>
|
|
4
4
|
<p align="center"><strong>Keep the work lit.</strong></p>
|
|
5
5
|
<p align="center">Claude Code์์ ์ธ์
๋ง๋ค ๊ณํํ๊ณ , ๋ง๋ค๊ณ , ํ์ธํ ๋ค ๋ค์ ์ธ์
์ด ์ด์ด๋ฐ์ ๊ธฐ๋ก์ ๋จ๊ธฐ๊ฒ ๋๋ ํ๋ฌ๊ทธ์ธ์
๋๋ค.</p>
|
|
6
6
|
<p align="center">
|
|
7
|
-
<img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.
|
|
8
|
-
<a href="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.
|
|
7
|
+
<img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.24/docs/assets/readme/badge-version.svg" alt="1.0.24" />
|
|
8
|
+
<a href="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.24/LICENSE"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.24/docs/assets/readme/badge-license.svg" alt="MIT license" /></a>
|
|
9
9
|
</p>
|
|
10
10
|
<p align="center">
|
|
11
|
-
<a href="https://github.com/wjgoarxiv/litclaude/blob/main/README_ko-KR.md">์ ์ฒด ์๋ด์ ์คํฌ ๊ฐค๋ฌ๋ฆฌ๋ GitHub์์</a> ยท <a href="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.
|
|
11
|
+
<a href="https://github.com/wjgoarxiv/litclaude/blob/main/README_ko-KR.md">์ ์ฒด ์๋ด์ ์คํฌ ๊ฐค๋ฌ๋ฆฌ๋ GitHub์์</a> ยท <a href="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.24/README.md">English</a>
|
|
12
12
|
</p>
|
|
13
13
|
|
|
14
14
|
Claude Code ํ๋กฌํํธ์ `lit`์ ๋ถ์ด๋ฉด Claude๊ฐ ๋ชฉํ๋ฅผ ๊ณ ์ ํ๊ณ , ์คํจํ๋ ํ
์คํธ๋ฅผ ๋จผ์ ์ฐ๊ณ ,
|
|
@@ -71,7 +71,7 @@ LitClaude๋ ํ๋ก์ ํธ ์ํ๋ฅผ `.litclaude/`์ ๋๊ณ , ๊ทธ ์์ `.gitign
|
|
|
71
71
|
## ๋ ๋ณด๊ธฐ
|
|
72
72
|
|
|
73
73
|
- [์ ์ฒด ์๋ด์ ์คํฌ ๊ฐค๋ฌ๋ฆฌ (GitHub)](https://github.com/wjgoarxiv/litclaude/blob/main/README_ko-KR.md)
|
|
74
|
-
- [๊ฐ์ธ์ ๋ณด์ ๋คํธ์ํฌ ๋์](https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.
|
|
75
|
-
- [์ด์ ๊ณผ ์์ ๊ถ ์ถฉ๋](https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.
|
|
76
|
-
- [๋ณ๊ฒฝ ์ด๋ ฅ](https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.
|
|
77
|
-
- [MIT ๋ผ์ด์ ์ค](https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.
|
|
74
|
+
- [๊ฐ์ธ์ ๋ณด์ ๋คํธ์ํฌ ๋์](https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.24/docs/privacy.md)
|
|
75
|
+
- [์ด์ ๊ณผ ์์ ๊ถ ์ถฉ๋](https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.24/docs/migration.md)
|
|
76
|
+
- [๋ณ๊ฒฝ ์ด๋ ฅ](https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.24/CHANGELOG.md)
|
|
77
|
+
- [MIT ๋ผ์ด์ ์ค](https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.24/LICENSE)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="146" height="20" role="img" aria-label="release: 1.0.
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="146" height="20" role="img" aria-label="release: 1.0.24"><title>release: 1.0.24</title><g shape-rendering="crispEdges"><rect width="49" height="20" fill="#080d14"/><rect x="49" width="97" height="20" fill="#ff6337"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text x="255" y="140" textLength="390" transform="scale(.1)">release</text><text x="965" y="140" textLength="870" transform="scale(.1)" fill="#080D14">1.0.24</text></g></svg>
|
package/docs/hooks.md
CHANGED
|
@@ -346,36 +346,73 @@ itself. LitClaude's is `plugins/litclaude/hooks/lit-mod.mjs`, named under `modul
|
|
|
346
346
|
`hooks/hooks.json` next to the settings hooks above. It installs with the plugin and needs no
|
|
347
347
|
setup. The status line stays as it is; the band adds a live layer above the prompt.
|
|
348
348
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
349
|
+
From the first prompt to the end of the session a LIT card sits above the prompt. It keeps the
|
|
350
|
+
same four rows whether LitClaude is working or idle, and takes the status line's accent
|
|
351
|
+
(`LITCLAUDE_HUD_ACCENT`, read from the installed status line command), so the card and the
|
|
352
|
+
status line read as one family:
|
|
353
|
+
|
|
354
|
+
```
|
|
355
|
+
โญโ [๐ฅ LIT] ยท lit-loop โโโโโโโโโโโโโโโโโโโโโโโโโโโ WORK โ โโฎ
|
|
356
|
+
โ โ PLAN โโ [WORK] โโ โ REVIEW goal โโโโโ 2/5 โ
|
|
357
|
+
โ skills [โก lit-plan] [โก litresearch] [โฏ lit-docx] โ
|
|
358
|
+
โฐโ ctx 42% โฐโฐโฑโฑโฑ ยท 5h 31% ยท git main โโโโโโโโโโโโโโโโโโโโโโโฏ
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
The brackets stand for the ends of filled pills: rounded caps from the icon font with `nerd`
|
|
362
|
+
glyphs, one cell of the pill's colour with `basic`. The brand is a pink pill, the active phase
|
|
363
|
+
and the skills of this request are pills on the accent with dark text, and skills from earlier
|
|
364
|
+
requests are muted grey pills.
|
|
365
|
+
|
|
366
|
+
- The top edge names the discipline the prompt hook ignited (the last one, dimmed, while the
|
|
367
|
+
session is idle; `ready` before any) and, on the right, the current phase: `WORK โ`, `idle`,
|
|
368
|
+
or `DONE โ` during the finish. While a subagent is still running the card stays at work
|
|
369
|
+
(`LIVE โ` when no phase is active) and never reads `DONE`, even after the main turn ended.
|
|
370
|
+
- The phase row lights `PLAN โโ WORK โโ REVIEW` from the start-work plan, the litgoal goal and
|
|
371
|
+
the discipline (the active phase as a pill, done phases `โ`, the rest `โ`), and on its right shows a pink-to-cyan progress bar with the checked tasks or
|
|
372
|
+
passed criteria (`goal โ 5/5` once a goal is met), the number of live subagents (`โ 2 lanes`), the autoloop
|
|
373
|
+
count with the time left in its 30-minute budget, and `ctx 76% โ 80%` when the context is
|
|
374
|
+
within five points of the auto-handoff percent.
|
|
375
|
+
- The chips row shows each LitFamily skill that fired as a pill: a Skill tool call naming a LitClaude
|
|
376
|
+
skill, a typed `/litclaude:<name>`, or bare `lit` routing seen through the ignition record.
|
|
377
|
+
A skill fired in the current request is bright, with a short light passing over its name as
|
|
378
|
+
it arrives; when the turn completes it dims into the `recent` list, and a new firing brightens
|
|
379
|
+
it again. Chips follow a dim `skills` label; those that do not fit collapse into a muted `+N`. Skills of other plugins never get a chip.
|
|
380
|
+
With no chip yet, the row shows the next task while work runs, or how to start (`lit <task>`)
|
|
381
|
+
while idle.
|
|
382
|
+
- The bottom edge carries the live figures from the status line: context fill, the five-hour
|
|
383
|
+
rate window and the Git branch (read from `HEAD`, across a linked worktree).
|
|
384
|
+
- A notice takes the chips row for a few seconds, with a toast, when a gate fires: lit-plan not
|
|
385
|
+
saved, interface probe pending or failed, motion gate, context near the auto-handoff percent,
|
|
386
|
+
auto-handoff fired. The completion moment takes it when the last task is checked, the work
|
|
387
|
+
completes or the goal is met: a light passes over the brand, embers scatter, and `COMPLETE`
|
|
388
|
+
shows for about a second.
|
|
389
|
+
- Amber or red when something needs attention: a lane quiet for more than 10 minutes turns the
|
|
390
|
+
border amber and puts `โ <lane> quiet for 12m` on the bottom edge; a failed interface probe
|
|
391
|
+
turns it red.
|
|
392
|
+
|
|
393
|
+
Subagents and teammates come from Claude Code's agent list. A workflow script's agents never
|
|
394
|
+
appear there, so the mod also records every agent at `agent.spawn` and counts it until that
|
|
395
|
+
agent's own `turn.complete` arrives. A subagent's turn ending does not end the main turn: the
|
|
396
|
+
chips of the current request stay bright until the main turn completes. An agent the list shows
|
|
397
|
+
as ended stops counting at once, and one quiet for 30 minutes (no tool call, no status change)
|
|
398
|
+
stops counting too, so a crashed or lost agent cannot hold the card at work.
|
|
399
|
+
|
|
400
|
+
The card is the terminal's width up to 80 columns and every row is fitted to it, with Hangul and
|
|
401
|
+
emoji counted as two cells. Nothing wraps: on a narrow terminal the Git branch goes first, then
|
|
402
|
+
the rate window, the lanes, the autoloop count and the long phase labels (`P โ W โ R`).
|
|
366
403
|
|
|
367
404
|
The spinner gains ` ยท <discipline> ยท n/m` after its ellipsis. `/lit-evidence` opens a pane with
|
|
368
405
|
three tabs (keys `1`, `2`, `3`): the goal's criteria with their last evidence, blockers and the
|
|
369
|
-
newest litgoal ledger entries; the lanes; and the gates.
|
|
370
|
-
drawn at all.
|
|
406
|
+
newest litgoal ledger entries; the lanes; and the gates.
|
|
371
407
|
|
|
372
408
|
Motion: entrances pop in 60 ms apart with a slight overshoot (160 ms each), fills and colour
|
|
373
409
|
changes ease in and out (300 ms and 140 ms), notices slide in over 220 ms and leave over 150 ms,
|
|
374
|
-
|
|
410
|
+
a chip's arrival light runs 400 ms (a plain fade under `subtle`, nothing under `off`), and the
|
|
411
|
+
finish lasts at most 1.2 s. The band's `Client` element animates on Claude Code's frame
|
|
375
412
|
clock only while something moves and stops its timer as soon as everything settles. In Claude
|
|
376
413
|
Code 2.1.292 a terminal row whose only change is a non-ASCII glyph is not repainted, so every
|
|
377
414
|
moving part changes ASCII text or colour: bar cells are coloured spaces, embers are ASCII sparks,
|
|
378
|
-
and a glyph swaps only together with its words.
|
|
415
|
+
a chip's light moves over its ASCII name, and a glyph swaps only together with its words.
|
|
379
416
|
|
|
380
417
|
Options, in `/config` under LitClaude (stored in `pluginConfigs`):
|
|
381
418
|
|
|
@@ -383,14 +420,15 @@ Options, in `/config` under LitClaude (stored in `pluginConfigs`):
|
|
|
383
420
|
| --- | --- | --- |
|
|
384
421
|
| `motion` | `full`, `subtle` (no overshoot, shimmer or embers, shorter), `off` (final frames only) | `full` |
|
|
385
422
|
| `glyphs` | `auto` (Nerd glyphs when the icon font is installed), `nerd`, or `basic` | `auto` |
|
|
386
|
-
| `band` | `auto` (only while work is active), `
|
|
423
|
+
| `band` | `always` (the whole session, idle included), `auto` (only while work is active or a skill of this request is lit), `off` | `always` |
|
|
387
424
|
|
|
388
425
|
Unknown values fall back to the default. The fields are plain strings with no `options` list on
|
|
389
426
|
purpose: Claude Code 2.1.270 and older refuse to load a plugin whose `userConfig` has one, and
|
|
390
427
|
that would take every LitClaude hook down with it. Nerd glyphs reach only the terminal; the
|
|
391
428
|
desktop app and the other surfaces always get the basic set.
|
|
392
429
|
|
|
393
|
-
The rounded pill caps
|
|
430
|
+
The icons on `nerd` (the rounded pill caps U+E0B6 and U+E0B4, the chip bolt and the branch mark)
|
|
431
|
+
come from a Nerd Font. `litclaude-ai install
|
|
394
432
|
--icon-font`, or a Yes to the install question (default No), adds the symbols-only Nerd Font,
|
|
395
433
|
Symbols Nerd Font Mono (MIT), to the per-user font folder (`~/Library/Fonts` on macOS,
|
|
396
434
|
`~/.local/share/fonts` on Linux, then `fc-cache -f` if present; on Windows it prints how to
|
|
@@ -403,8 +441,9 @@ records the two files, `uninstall` removes only those (and only while unchanged)
|
|
|
403
441
|
prints `ICON_FONT:`. With `glyphs` on `auto`, the band checks those font folders by stat at session
|
|
404
442
|
start and says what it decided on the `/lit-evidence` gates tab.
|
|
405
443
|
|
|
406
|
-
The mod is read-only. It reads LitClaude's own state
|
|
407
|
-
the
|
|
444
|
+
The mod is read-only. It reads LitClaude's own state, the Git `HEAD` of the working directory and
|
|
445
|
+
the merged settings (for the status line's accent) and nothing else: the ignition record in the
|
|
446
|
+
per-user temp folder, `.litclaude/boulder.json` (found the way the hooks find it, across a
|
|
408
447
|
linked worktree), and under the outermost Git root's `.litclaude/` the litgoal goal, autoloop
|
|
409
448
|
counter and ledger, the lit-plan, interface-probe and motion turn records, and the auto-handoff
|
|
410
449
|
settings and session record. Each file must be a regular file under its size cap that resolves
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@litfamily/litclaude",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.24",
|
|
4
4
|
"description": "Claude Code plugin: add lit to a prompt and Claude plans, tests, checks and reviews the work, then leaves a handoff for the next session.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "litclaude",
|
|
3
3
|
"description": "Claude Code-native workflow plugin with a bounded-authority start-work lifecycle.",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.24",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "LitClaude contributors"
|
|
7
7
|
},
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
"band": {
|
|
31
31
|
"type": "string",
|
|
32
32
|
"title": "LIT band",
|
|
33
|
-
"description": "When the
|
|
34
|
-
"default": "
|
|
33
|
+
"description": "When the LIT card shows above the prompt: always (the whole session, idle included), auto (only while LitClaude work is active or a skill of this request is lit) or off.",
|
|
34
|
+
"default": "always"
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
}
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
toneText,
|
|
15
15
|
} from "../lib/hud-accent-palette.mjs";
|
|
16
16
|
import { latestUsageTokensCached } from "../lib/cache-measurement.mjs";
|
|
17
|
-
import { ignitionStatePath
|
|
17
|
+
import { ignitionStatePath } from "../lib/hud-ignition.mjs";
|
|
18
18
|
import { jevHudState } from "../lib/jev-skill-hint.mjs";
|
|
19
19
|
import { resolveProjectStateRoot } from "../lib/project-state-root.mjs";
|
|
20
20
|
import { recordContextUsage, resolveAutoHandoff } from "../lib/auto-handoff.mjs";
|
|
@@ -344,13 +344,10 @@ const main = async () => {
|
|
|
344
344
|
const contextText = contextPct === null
|
|
345
345
|
? `${text("ctx")} ${text(`?/${windowText}`)}`
|
|
346
346
|
: `${text("ctx")} ${accent("[")}${makeContextBar(contextPct)}${accent("]")} ${text(`${contextPct}%/${windowText}`)}`;
|
|
347
|
-
const ignition = renderIgnitionSegment(readIgnitionState(status.session_id), {
|
|
348
|
-
depth: plainOutput ? "plain" : colorDepth,
|
|
349
|
-
});
|
|
350
347
|
const effort = effortLabel(status);
|
|
351
348
|
const jev = jevBadge(status);
|
|
352
349
|
const autoHandoff = autoHandoffSegment(status, knownContextPct);
|
|
353
|
-
const line = `${prefix}
|
|
350
|
+
const line = `${prefix} ${accent("|")} ${text(model)}${effort ? ` ${text(effort)}` : ""}${jev ? ` ${jev}` : ""} ${accent(sep)} ${contextText}${autoHandoff ? ` ${accent(sep)} ${autoHandoff}` : ""}${usageText}${git ? ` ${accent(sep)} ${text("git")} ${text(git)}` : ""}`;
|
|
354
351
|
process.stdout.write(`${line}\n`);
|
|
355
352
|
|
|
356
353
|
const lastMessage = latestUserMessage(status.transcript_path);
|
|
@@ -39,6 +39,6 @@ export default function LitBand(props, surface) {
|
|
|
39
39
|
if (surface.state?.live !== holder) surface.setState({ live: holder, now: holder.now });
|
|
40
40
|
|
|
41
41
|
if (!model.visible && !timelineBusy(holder.timeline, holder.now, profile)) return empty();
|
|
42
|
-
const frame = composeBand(model, sampleTimeline(holder.timeline, holder.now, profile), { columns: props.columns, glyphs: props.glyphs });
|
|
42
|
+
const frame = composeBand(model, sampleTimeline(holder.timeline, holder.now, profile), { columns: props.columns, glyphs: props.glyphs, accent: props.accent });
|
|
43
43
|
return renderBand(surface.elements, frame);
|
|
44
44
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
// LitClaude's Claude Code mod (hooks/hooks.json `modules`). It draws the LIT
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
1
|
+
// LitClaude's Claude Code mod (hooks/hooks.json `modules`). It draws the LIT card above the prompt
|
|
2
|
+
// for the whole session (the `band` setting can limit it to active work or turn it off), lights a
|
|
3
|
+
// chip for each LitFamily skill that fires, adds the discipline and progress to the spinner, raises
|
|
4
|
+
// gate notices, and serves /lit-evidence. It is read-only: it reads LitClaude's own state files and
|
|
5
|
+
// the Git HEAD through lib/mod/state.mjs, the settings for the status line's accent, and the host's
|
|
6
|
+
// live figures, and never writes, spawns, fetches or calls a model.
|
|
5
7
|
// Claude Code releases before mods ignore the `modules` key and keep running the settings hooks.
|
|
6
8
|
//
|
|
7
9
|
// The mods loader only follows `$` into functions declared at the top of this file, so each helper
|
|
@@ -10,8 +12,9 @@
|
|
|
10
12
|
import { composeBand, composeEvidence } from "../lib/mod/frame.mjs";
|
|
11
13
|
import { TIMINGS } from "../lib/mod/motion.mjs";
|
|
12
14
|
import { renderBand, renderRows } from "../lib/mod/render.mjs";
|
|
13
|
-
import { normalizeModSettings, resolveGlyphs } from "../lib/mod/settings.mjs";
|
|
14
|
-
import {
|
|
15
|
+
import { accentFromSettings, normalizeModSettings, resolveGlyphs } from "../lib/mod/settings.mjs";
|
|
16
|
+
import { chipStates, litSkillId, noteSkill } from "../lib/mod/skills.mjs";
|
|
17
|
+
import { detectIconFont, readGitBranch, readLedgerTail, readLitSnapshot } from "../lib/mod/state.mjs";
|
|
15
18
|
import { settledSample } from "../lib/mod/timeline.mjs";
|
|
16
19
|
import {
|
|
17
20
|
EMPTY_ACTIVITY,
|
|
@@ -19,7 +22,11 @@ import {
|
|
|
19
22
|
buildEvidenceModel,
|
|
20
23
|
detectCompletion,
|
|
21
24
|
diffNotices,
|
|
25
|
+
mergeSpawned,
|
|
22
26
|
noteAgentActivity,
|
|
27
|
+
noteSpawn,
|
|
28
|
+
noteSpawnActivity,
|
|
29
|
+
noteSpawnEnded,
|
|
23
30
|
spinnerSuffix,
|
|
24
31
|
trackAgents,
|
|
25
32
|
} from "../lib/mod/view.mjs";
|
|
@@ -41,6 +48,7 @@ const createLive = (options) => ({
|
|
|
41
48
|
snapshot: null,
|
|
42
49
|
model: null,
|
|
43
50
|
agents: [],
|
|
51
|
+
spawned: {},
|
|
44
52
|
usage: null,
|
|
45
53
|
activity: EMPTY_ACTIVITY,
|
|
46
54
|
statusById: {},
|
|
@@ -55,6 +63,12 @@ const createLive = (options) => ({
|
|
|
55
63
|
evidenceTab: "goal",
|
|
56
64
|
ledger: [],
|
|
57
65
|
celebrated: new Set(),
|
|
66
|
+
accent: undefined,
|
|
67
|
+
git: null,
|
|
68
|
+
fired: [],
|
|
69
|
+
settledAt: 0,
|
|
70
|
+
ignitionAt: undefined,
|
|
71
|
+
lastDiscipline: null,
|
|
58
72
|
});
|
|
59
73
|
|
|
60
74
|
const stateIo = ($) => ({
|
|
@@ -77,6 +91,9 @@ async function rebuild($, live) {
|
|
|
77
91
|
isWorking: live.isWorking,
|
|
78
92
|
notice: live.notice,
|
|
79
93
|
completion: live.completion,
|
|
94
|
+
skills: chipStates(live.fired, live.settledAt),
|
|
95
|
+
lastDiscipline: live.lastDiscipline,
|
|
96
|
+
git: live.git,
|
|
80
97
|
});
|
|
81
98
|
live.model = next;
|
|
82
99
|
if (previous?.visible && !next.visible && !live.exiting) {
|
|
@@ -112,20 +129,42 @@ function celebrate($, live, finish) {
|
|
|
112
129
|
});
|
|
113
130
|
}
|
|
114
131
|
|
|
132
|
+
// A firing of a skill or command by name; anything that is not LitClaude's is ignored.
|
|
133
|
+
async function noteFiring($, live, name) {
|
|
134
|
+
const id = litSkillId(name);
|
|
135
|
+
if (!id) return;
|
|
136
|
+
live.fired = noteSkill(live.fired, id, await $.clock.now());
|
|
137
|
+
live.lastDiscipline = id;
|
|
138
|
+
await rebuild($, live);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// The prompt hook rewrites the ignition record on every prompt; a new record naming a discipline is
|
|
142
|
+
// a bare `lit` (or slash) routing, and lights that skill's chip at the time the hook wrote it.
|
|
143
|
+
function noteIgnition(live, ignition, now) {
|
|
144
|
+
if (!ignition || ignition.at === live.ignitionAt) return;
|
|
145
|
+
live.ignitionAt = ignition.at;
|
|
146
|
+
live.lastDiscipline = ignition.discipline;
|
|
147
|
+
const id = litSkillId(ignition.discipline);
|
|
148
|
+
if (id) live.fired = noteSkill(live.fired, id, ignition.at ?? now);
|
|
149
|
+
}
|
|
150
|
+
|
|
115
151
|
async function refresh($, live) {
|
|
116
152
|
if (live.refreshing) return;
|
|
117
153
|
live.refreshing = true;
|
|
118
154
|
try {
|
|
119
155
|
const [cwd, sessionId] = await Promise.all([$.session.cwd(), $.session.id()]);
|
|
120
156
|
const fresh = await readLitSnapshot(stateIo($), { cwd, sessionId, env: live.env });
|
|
121
|
-
live.
|
|
157
|
+
live.git = await readGitBranch(stateIo($), cwd).catch(() => live.git);
|
|
158
|
+
const listed = await $.agent.list().catch(() => []);
|
|
122
159
|
live.usage = await $.session.usage().catch(() => live.usage);
|
|
123
160
|
const now = await $.clock.now();
|
|
161
|
+
({ agents: live.agents, spawned: live.spawned } = mergeSpawned(listed, live.spawned, now));
|
|
124
162
|
live.activity = trackAgents(live.activity, live.agents, live.statusById, now);
|
|
125
163
|
live.statusById = Object.fromEntries(live.agents.map((agent) => [agent.id, agent.status]));
|
|
126
164
|
const before = live.snapshot;
|
|
127
165
|
const previousModel = live.model;
|
|
128
166
|
live.snapshot = fresh;
|
|
167
|
+
noteIgnition(live, fresh.ignition, now);
|
|
129
168
|
const finish = detectCompletion(before, fresh);
|
|
130
169
|
if (finish) celebrate($, live, finish);
|
|
131
170
|
const next = await rebuild($, live);
|
|
@@ -167,6 +206,8 @@ export const register = (on, options) => {
|
|
|
167
206
|
XDG_DATA_HOME: await $.env.get("XDG_DATA_HOME"),
|
|
168
207
|
LOCALAPPDATA: await $.env.get("LOCALAPPDATA"),
|
|
169
208
|
});
|
|
209
|
+
live.settledAt = await $.clock.now();
|
|
210
|
+
live.accent = accentFromSettings(await $.settings.read().catch(() => null), await $.env.get("LITCLAUDE_HUD_ACCENT"));
|
|
170
211
|
await $.command.register({ name: PANE, description: "Show LitClaude goal criteria, evidence, lanes and gates in a pane" });
|
|
171
212
|
await refresh($, live);
|
|
172
213
|
$.clock.every(POLL_MS, () => {
|
|
@@ -182,7 +223,15 @@ export const register = (on, options) => {
|
|
|
182
223
|
});
|
|
183
224
|
|
|
184
225
|
on("turn.complete", async ($, e, next) => {
|
|
226
|
+
// A subagent's or teammate's turn ends its run, not the main turn the card follows.
|
|
227
|
+
if (typeof e.agentId === "string") {
|
|
228
|
+
live.spawned = noteSpawnEnded(live.spawned, e.agentId);
|
|
229
|
+
refreshSoon($, live);
|
|
230
|
+
return next(e);
|
|
231
|
+
}
|
|
185
232
|
live.isWorking = false;
|
|
233
|
+
// The request is over: its chips dim to the recent list until a skill fires again.
|
|
234
|
+
live.settledAt = await $.clock.now();
|
|
186
235
|
refreshSoon($, live);
|
|
187
236
|
return next(e);
|
|
188
237
|
});
|
|
@@ -194,12 +243,36 @@ export const register = (on, options) => {
|
|
|
194
243
|
});
|
|
195
244
|
|
|
196
245
|
on("tool.call", async ($, e, next) => {
|
|
246
|
+
if (e.tool === "Skill") await noteFiring($, live, e.skill);
|
|
247
|
+
if (typeof e.agentId === "string") live.spawned = noteSpawnActivity(live.spawned, e.agentId, await $.clock.now());
|
|
197
248
|
const result = await next(e);
|
|
198
|
-
if (typeof e.agentId === "string")
|
|
249
|
+
if (typeof e.agentId === "string") {
|
|
250
|
+
const now = await $.clock.now();
|
|
251
|
+
live.activity = noteAgentActivity(live.activity, e.agentId, now);
|
|
252
|
+
live.spawned = noteSpawnActivity(live.spawned, e.agentId, now);
|
|
253
|
+
}
|
|
199
254
|
refreshSoon($, live);
|
|
200
255
|
return result;
|
|
201
256
|
}).catch(($, e, next) => next(e));
|
|
202
257
|
|
|
258
|
+
// Every subagent, teammate and workflow agent starts here. A workflow's never shows in
|
|
259
|
+
// `$.agent.list()`, so the card keeps its own record until the agent's turn.complete.
|
|
260
|
+
on("agent.spawn", async ($, e, next) => {
|
|
261
|
+
const result = await next(e);
|
|
262
|
+
if (typeof result?.agentId === "string") {
|
|
263
|
+
live.spawned = noteSpawn(live.spawned, { id: result.agentId, description: e.description, type: e.subagentType, at: await $.clock.now() });
|
|
264
|
+
refreshSoon($, live);
|
|
265
|
+
}
|
|
266
|
+
return result;
|
|
267
|
+
}).catch(($, e, next) => next(e));
|
|
268
|
+
|
|
269
|
+
// A typed `/litclaude:<name>` and the Skill tool both expand the skill's prompt here; the text
|
|
270
|
+
// passes through untouched.
|
|
271
|
+
on("skill.prompt", async ($, e, next) => {
|
|
272
|
+
await noteFiring($, live, e.skill);
|
|
273
|
+
return next(e);
|
|
274
|
+
}).catch(($, e, next) => next(e));
|
|
275
|
+
|
|
203
276
|
on("ui.fault", async ($, e, next) => {
|
|
204
277
|
if (e.component === "AbovePrompt") live.clientFailed = true;
|
|
205
278
|
return next(e);
|
|
@@ -214,9 +287,9 @@ export const register = (on, options) => {
|
|
|
214
287
|
const columns = Math.max(20, e.props.bodyColumns ?? e.viewport?.columns ?? 80);
|
|
215
288
|
let drawn = null;
|
|
216
289
|
if (elements.Client && !live.clientFailed) {
|
|
217
|
-
drawn = elements.Client({ key: "lit-band", module: "./lit-band-client.mjs", props: { model, columns, glyphs, motion: settings.motion } });
|
|
290
|
+
drawn = elements.Client({ key: "lit-band", module: "./lit-band-client.mjs", props: { model, columns, glyphs, motion: settings.motion, accent: live.accent } });
|
|
218
291
|
} else if (model.visible) {
|
|
219
|
-
drawn = renderBand(elements, composeBand(model, settledSample(model), { columns, glyphs }));
|
|
292
|
+
drawn = renderBand(elements, composeBand(model, settledSample(model), { columns, glyphs, accent: live.accent }));
|
|
220
293
|
}
|
|
221
294
|
const below = await next(e);
|
|
222
295
|
if (!drawn) return below;
|
|
@@ -11,8 +11,8 @@ export const canonicalSkillResourceManifest = Object.freeze(
|
|
|
11
11
|
["lib/durable-plan.mjs", "33fc7c2ba6305602c73650c8f29e6141e93b8ac32a444f772807e11bf8c22e44"],
|
|
12
12
|
["lib/immutable-expected-file-map.mjs", "4061486bc8eda8a53e56b7b346a1e400e7c858c0a682c83362fea460b46dfd4b"],
|
|
13
13
|
["lib/lit-mark.mjs", "cb57921a3da0ff983c74e9426dcd3b2379db090198743139e379a059c128021e"],
|
|
14
|
-
["lib/office-runtime-lock/package-lock.json", "
|
|
15
|
-
["lib/office-runtime-lock/package.json", "
|
|
14
|
+
["lib/office-runtime-lock/package-lock.json", "16d19b420b410035e9ca6886133368444a2b438121919857b3e8915be280c6a6"],
|
|
15
|
+
["lib/office-runtime-lock/package.json", "5e4b0c7ee7bd5ff88c888f7f46152c605caf128cc4e7bfd16423571210925394"],
|
|
16
16
|
["lib/office-runtime-lock/requirements.lock", "7c63ce0de1ae9a912d1e546e9c01dd99a705d4a50435f36040d351cc3e6e6014"],
|
|
17
17
|
["lib/office-runtime.mjs", "24d108a4ae7aa98dd0d6f2fa66686d7c9f020ecf42fe641241be2869075bbea3"],
|
|
18
18
|
["lib/office_data.py", "0f4c2449622b6d59630e60508594d181279052c41918df4370e11a68df1ee239"],
|
|
@@ -848,11 +848,11 @@ export const canonicalSkillResourceManifest = Object.freeze(
|
|
|
848
848
|
["skills/readme-studio/templates/cover-source.json", "182051737e4cda9002360316bb2c01b500ecc20c27953a2d332d908f044f5cd7"],
|
|
849
849
|
["skills/readme-studio/templates/hyperframes-cover/index.html", "edaee52e01cc7d90524b43e3da80b4bc6514fef1d17b4317cbf15ed5e36a5c67"],
|
|
850
850
|
["skills/readme-studio/templates/hyperframes-cover/index.motion.json", "bef879ce5abe7810d73cc733ab635884ec807eccd7bc5e1c9bc9900049187249"],
|
|
851
|
-
["skills/readme-studio/templates/hyperframes-cover/package-lock.json", "
|
|
851
|
+
["skills/readme-studio/templates/hyperframes-cover/package-lock.json", "5adacd09e4608c8c3917ca0245052e4d3abae3a566ebe07a2fdad593c67cb91c"],
|
|
852
852
|
["skills/readme-studio/templates/hyperframes-cover/package.json", "0993c6f04892f5a318cc99030de653b7c68d3ea6789c69b30b6a2ae80e4120f0"],
|
|
853
853
|
["skills/readme-studio/templates/readme-cover-section.md", "1dc4c536f65d3437f12e09a76170a8dc76557225587c7453631a06604a21573d"],
|
|
854
854
|
["skills/readme-studio/templates/readme-facts.json", "fb95b8aece0e8591726d3a36e25cc66712b0c6e57835c848db0f07b745e73205"],
|
|
855
|
-
["skills/readme-studio/templates/remotion-cover/package-lock.json", "
|
|
855
|
+
["skills/readme-studio/templates/remotion-cover/package-lock.json", "422af74482c6c36e5bfaa86c2fe6a78e7ff54d27d3119f9c462685333a449857"],
|
|
856
856
|
["skills/readme-studio/templates/remotion-cover/package.json", "7921a415cf96343b46c9a2a3bea9160ecc807710fb6a34ba227704eff7d83887"],
|
|
857
857
|
["skills/readme-studio/templates/remotion-cover/src/index.tsx", "81cf3edd996a98ddca46465d4bc84ca0203ecd3bdce1736bf1dc3d9f2bc15af9"],
|
|
858
858
|
["skills/readme-studio/templates/typography/package-lock.json", "1d6dc1ae0d06d0a3a5e1b2b45bea1d40be7497f1f2fb856eefd33cc3649af5bd"],
|
|
@@ -1,18 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { mkdirSync, renameSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { tmpdir } from "node:os";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
|
|
5
|
-
// Per-session ignition record: the prompt hook writes it on every UserPromptSubmit and the
|
|
6
|
-
//
|
|
7
|
-
// the current turn instead of anything the model chooses to
|
|
8
|
-
// durable, so the record lives in the per-user temp directory:
|
|
9
|
-
// root (activation must stay side-effect-free there) and not in the
|
|
10
|
-
|
|
11
|
-
const IGNITION_PALETTE = Object.freeze({
|
|
12
|
-
truecolor: "\x1b[38;2;255;99;55m",
|
|
13
|
-
"256": "\x1b[38;5;203m",
|
|
14
|
-
"16": "\x1b[91m",
|
|
15
|
-
});
|
|
5
|
+
// Per-session ignition record: the prompt hook writes it on every UserPromptSubmit and the LIT
|
|
6
|
+
// card (hooks/lit-mod.mjs, through lib/mod/state.mjs) reads it back, so the card reflects the
|
|
7
|
+
// discipline actually selected for the current turn instead of anything the model chooses to
|
|
8
|
+
// draw. Mode is per turn and never durable, so the record lives in the per-user temp directory:
|
|
9
|
+
// not in the repository state root (activation must stay side-effect-free there) and not in the
|
|
10
|
+
// home directory.
|
|
16
11
|
|
|
17
12
|
export const ignitionStateRoot = (env = process.env) => {
|
|
18
13
|
const override = env.LITCLAUDE_HUD_STATE_ROOT?.trim();
|
|
@@ -47,28 +42,3 @@ export function writeIgnitionState({ sessionId, discipline }, env = process.env,
|
|
|
47
42
|
renameSync(staging, target);
|
|
48
43
|
return record;
|
|
49
44
|
}
|
|
50
|
-
|
|
51
|
-
export function readIgnitionState(sessionId, env = process.env) {
|
|
52
|
-
const target = ignitionStatePath(sessionId, env);
|
|
53
|
-
if (!existsSync(target)) return null;
|
|
54
|
-
try {
|
|
55
|
-
const parsed = JSON.parse(readFileSync(target, "utf8"));
|
|
56
|
-
if (!parsed || typeof parsed !== "object") return null;
|
|
57
|
-
return {
|
|
58
|
-
sessionId: typeof parsed.sessionId === "string" ? parsed.sessionId : null,
|
|
59
|
-
discipline: typeof parsed.discipline === "string" && parsed.discipline ? parsed.discipline : null,
|
|
60
|
-
at: typeof parsed.at === "string" ? parsed.at : null,
|
|
61
|
-
};
|
|
62
|
-
} catch {
|
|
63
|
-
return null;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export function renderIgnitionSegment(state, { depth = "plain" } = {}) {
|
|
68
|
-
const discipline = state?.discipline ?? null;
|
|
69
|
-
if (!discipline) return "";
|
|
70
|
-
const label = ignitionMark(discipline);
|
|
71
|
-
if (depth === "plain") return label;
|
|
72
|
-
const paint = IGNITION_PALETTE[depth] ?? IGNITION_PALETTE["256"];
|
|
73
|
-
return `\x1b[1m${paint}${label}\x1b[0m`;
|
|
74
|
-
}
|