Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
125 commits
Select commit Hold shift + click to select a range
17b9fe3
Add curated external welcome presets
raiseCatError Sep 28, 2026
3d67999
Add offline Linguist language colors
raiseCatError Sep 28, 2026
3bf1871
Add optional VHS demo tapes
raiseCatError Sep 28, 2026
4f6347e
Make VHS demos wait for visible states
raiseCatError Sep 28, 2026
92240b3
Add supplied-candidate picker providers and terminal handoff
raiseCatError Sep 30, 2026
21c0e83
Add native directory navigation and optional zoxide snapshot queries
raiseCatError Sep 30, 2026
8b8e197
Suggest conservative command-not-found corrections without execution
raiseCatError Sep 30, 2026
ff0fa1c
Harden completion paths, history imports and concurrent deletion privacy
raiseCatError Sep 30, 2026
2da4d02
Document v0.8 command intelligence architecture and pending terminal QA
raiseCatError Sep 30, 2026
f63182b
Add local command inspector sharing completion knowledge
raiseCatError Oct 1, 2026
83d8b07
Add keyboard and passive-hover command block actions
raiseCatError Oct 1, 2026
7919fdf
Add live command notifications and terminal focus lifecycle
raiseCatError Oct 1, 2026
573ca03
Isolate test TMPDIR and verify lifecycle cleanup before sweeping
raiseCatError Oct 1, 2026
8e61137
Keep inspector command context for quoted paths and redirects
raiseCatError Oct 1, 2026
0de4805
Document v0.8 continuation architecture and pending combined QA
raiseCatError Oct 1, 2026
b1ab55e
Await sandbox writers and clean up owned background fixture jobs
raiseCatError Oct 1, 2026
2dfbf9c
Record final continuation verification and fixture ownership limits
raiseCatError Oct 1, 2026
6e1cc7c
Merge commit '2dfbf9c12c54ada8af364bc44db87bc70f0b77c0' into feature/…
raiseCatError Oct 1, 2026
0ffa990
Integrate Linguist lookup with Chroma identity colors
raiseCatError Oct 1, 2026
a3b65fa
Merge branch 'feature/176-linguist-language-colors' into feature/177-…
raiseCatError Oct 1, 2026
aa3b5ed
Modernize optional welcome adapter presentation and maintenance notes
raiseCatError Oct 1, 2026
0cbc8e8
Merge branch 'feature/177-external-welcome-adapters' into tooling/178…
raiseCatError Oct 1, 2026
4434ce7
Use deterministic isolated launches in development tapes
raiseCatError Oct 1, 2026
56ba4bc
Add supported tool configuration review with native Starship adapter
raiseCatError Oct 1, 2026
f1d6899
Add optional tools browser and explicit installation previews
raiseCatError Oct 1, 2026
9f9ce08
Record v0.9 checkpoint and additive physical QA
raiseCatError Oct 1, 2026
78b9c41
Add consent-based mise project awareness and task discovery
raiseCatError Oct 1, 2026
0b0b2d0
Add named presets that launch new live shell sessions
raiseCatError Oct 1, 2026
389d87d
Record final v0.9 development acceptance and pending physical QA
raiseCatError Oct 1, 2026
eb9847e
Wait for frontend startup completion in cumulative preset acceptance
raiseCatError Oct 1, 2026
02cda58
Enforce preset storage byte limits before atomic replacement
raiseCatError Oct 1, 2026
d845e33
Introduce frontend terminal capabilities and bounded startup probes
raiseCatError Oct 1, 2026
a31e24e
Harden baseline rendering and add conservative color fallback
raiseCatError Oct 1, 2026
a0b4751
Isolate terminal configuration and bootstrap hints behind host adapters
raiseCatError Oct 1, 2026
4b8165d
Add capability profiles for iTerm2 Kitty and WezTerm
raiseCatError Oct 1, 2026
ae66506
Record v0.10 resource checkpoint after host profiles
raiseCatError Oct 1, 2026
4a0ba7b
Add capability-gated OSC 8 transcript presentation
raiseCatError Oct 1, 2026
4289b8b
Add deterministic CLI and TUI compatibility fixtures
raiseCatError Oct 1, 2026
ce0fdcc
Harden terminal mode replay and probe cleanup
raiseCatError Oct 1, 2026
d3e77f7
Document v0.10 development acceptance and remaining physical QA
raiseCatError Oct 1, 2026
d61607d
Bridge configured zsh completion knowledge into the owned composer
raiseCatError Oct 1, 2026
d80a165
Bound completion transport lifetime and clean hidden PTY groups
raiseCatError Oct 1, 2026
0df8cd6
Preserve the native completion query budget
raiseCatError Oct 2, 2026
dbec8aa
Improve native shell intelligence with live name metadata
raiseCatError Oct 1, 2026
00afcfd
Preserve authoritative shell names across generations and reattachment
raiseCatError Oct 2, 2026
f63f2f3
Wait for frontend ownership before compatibility assertions
raiseCatError Oct 2, 2026
be97375
Harden shell intelligence helper cleanup and completion insertion
raiseCatError Oct 2, 2026
1f09274
Retain managed shell cleanup ownership through exit and spawn failures
raiseCatError Oct 2, 2026
37244be
Throttle completion configuration reloads and isolate redraw regression
raiseCatError Oct 2, 2026
3eb4a2a
Document v0.11 cumulative acceptance and extensibility research
raiseCatError Oct 2, 2026
4a5ef78
Record final hardening evidence and completion reload limits
raiseCatError Oct 2, 2026
71472b7
feat: add composable Chroma treatments for owned surfaces
raiseCatError Oct 2, 2026
0815d90
feat: add bounded effects with shared presentation scheduling
raiseCatError Oct 2, 2026
45620a1
fix: harden presentation lifecycle and configuration preservation
raiseCatError Oct 2, 2026
cfc9c08
docs: record cumulative v0.12 acceptance and deferred physical QA
raiseCatError Oct 2, 2026
6fda729
feat: establish Linux zsh runtime and canonical CI baseline
raiseCatError Oct 2, 2026
78010a1
ci: avoid duplicate runs for stacked feature pushes
raiseCatError Oct 2, 2026
e433a8e
fix: harden zsh bootstrap paths and platform diagnostics
raiseCatError Oct 2, 2026
b34f7e3
fix: use absolute config defaults and flush fixture output
raiseCatError Oct 2, 2026
6dc303d
test: isolate Linux startup failures and preserve fixture exit status
raiseCatError Oct 2, 2026
4f74efe
ci: secure Ubuntu completion paths before zsh startup
raiseCatError Oct 2, 2026
2c280ca
fix: preserve commands submitted during slow shell bootstrap
raiseCatError Oct 2, 2026
0d086c1
test: await shell execution before detached output fixtures
raiseCatError Oct 2, 2026
48fdd15
fix: retain pre-bootstrap command state across reattach
raiseCatError Oct 2, 2026
3b0fc8a
test: verify detached retention independently of PTY chunks
raiseCatError Oct 2, 2026
e325bb3
docs: record v0.13 portability acceptance and deferred QA
raiseCatError Oct 2, 2026
b5de57b
fix: never overwrite unreadable settings and merge only changed value…
raiseCatError Oct 2, 2026
2f4b280
fix: recover preset storage lock from dead owners using pid ownership
raiseCatError Oct 2, 2026
87e3a83
fix: schedule presentation frames monotonically; make welcome test ch…
raiseCatError Oct 2, 2026
12ab1af
fix: classify notification slash commands semantically; track local m…
raiseCatError Oct 2, 2026
0792272
feat: optional Linux clipboard via wl-copy, xclip or xsel
raiseCatError Oct 2, 2026
dc398a4
fix: reconcile terminal modes when foreground ownership returns after…
raiseCatError Oct 2, 2026
2c3b705
fix: hold input and show explicit state while zsh startup is blocked …
raiseCatError Oct 2, 2026
e6bb9d0
fix: fill absent settings on partial saves; baseline hosts only recei…
raiseCatError Oct 2, 2026
ae45bbe
test: wait for the live session listing before inspecting startup fix…
raiseCatError Oct 2, 2026
6f761fe
docs: record v0.13 post-QA hardening acceptance
raiseCatError Oct 2, 2026
4f90c13
docs: explain the macOS skip count in post-QA acceptance
raiseCatError Oct 2, 2026
39923fc
fix: resolve adversarial startup and ownership blockers
raiseCatError Oct 2, 2026
38284c8
docs: record final adversarial hardening acceptance
raiseCatError Oct 2, 2026
2a4ca48
test: synchronize nested tmux startup and ownership return
raiseCatError Oct 2, 2026
a8937c6
fix: enable raw input before reattach terminal handoff
raiseCatError Oct 2, 2026
3b884a1
docs: finalize adversarial acceptance after reattach fix
raiseCatError Oct 2, 2026
71115f6
Merge pull request #290 from raiseCatError/docs/v013-adversarial-fina…
raiseCatError Oct 3, 2026
8baba22
Merge pull request #287 from raiseCatError/fix/v013-adversarial-harde…
raiseCatError Oct 3, 2026
404394b
Merge pull request #286 from raiseCatError/docs/v013-post-qa-acceptance
raiseCatError Oct 3, 2026
e97346e
Merge pull request #285 from raiseCatError/fix/v013-post-qa-hardening
raiseCatError Oct 3, 2026
edbc073
Merge pull request #283 from raiseCatError/docs/v013-cumulative-accep…
raiseCatError Oct 3, 2026
f436e81
Merge pull request #282 from raiseCatError/feature/v013-portability-h…
raiseCatError Oct 3, 2026
1edc150
Merge pull request #280 from raiseCatError/feature/v013-linux-baseline
raiseCatError Oct 3, 2026
27109b8
Merge pull request #278 from raiseCatError/docs/v012-cumulative-accep…
raiseCatError Oct 3, 2026
6eb971e
Merge pull request #277 from raiseCatError/feature/v012-presentation-…
raiseCatError Oct 3, 2026
febbf2b
Merge pull request #275 from raiseCatError/feature/v012-transient-eff…
raiseCatError Oct 3, 2026
8acece0
Merge pull request #273 from raiseCatError/feature/v012-chroma-treatm…
raiseCatError Oct 3, 2026
e10f6f1
Merge pull request #271 from raiseCatError/docs/v011-cumulative-accep…
raiseCatError Oct 3, 2026
32099ce
Merge pull request #269 from raiseCatError/feature/v011-shell-hardening
raiseCatError Oct 3, 2026
b30a263
Merge pull request #268 from raiseCatError/feature/v011-shell-intelli…
raiseCatError Oct 3, 2026
cace46d
Merge pull request #267 from raiseCatError/feature/v011-configured-co…
raiseCatError Oct 3, 2026
03c6568
Merge pull request #266 from raiseCatError/docs/v010-final-acceptance
raiseCatError Oct 3, 2026
67e05a2
Merge pull request #265 from raiseCatError/feature/v010-terminal-hard…
raiseCatError Oct 3, 2026
732edbe
Merge pull request #264 from raiseCatError/feature/v010-compatibility…
raiseCatError Oct 3, 2026
32eefc5
Merge pull request #263 from raiseCatError/feature/v010-osc8-links
raiseCatError Oct 3, 2026
b4de8dd
Merge pull request #262 from raiseCatError/feature/v010-host-profiles
raiseCatError Oct 3, 2026
a7544ad
Merge pull request #261 from raiseCatError/feature/v010-host-integration
raiseCatError Oct 3, 2026
7f87585
Merge pull request #260 from raiseCatError/feature/v010-baseline-host
raiseCatError Oct 3, 2026
cef80da
Merge pull request #259 from raiseCatError/feature/v010-host-capabili…
raiseCatError Oct 3, 2026
ada2be0
Merge pull request #258 from raiseCatError/docs/v09-final-acceptance
raiseCatError Oct 3, 2026
6952ef1
Merge pull request #257 from raiseCatError/feature/v09-session-presets
raiseCatError Oct 3, 2026
c884484
Merge pull request #256 from raiseCatError/feature/v09-mise-awareness
raiseCatError Oct 3, 2026
28f0b7a
Merge pull request #255 from raiseCatError/feature/v09-tools-browser
raiseCatError Oct 3, 2026
a1b4f7b
Merge pull request #254 from raiseCatError/feature/v09-supported-tool…
raiseCatError Oct 3, 2026
ad0399a
Merge pull request #183 from raiseCatError/tooling/178-vhs-demo-harness
raiseCatError Oct 3, 2026
c0b21eb
Merge pull request #181 from raiseCatError/feature/177-external-welco…
raiseCatError Oct 3, 2026
1d56667
Merge pull request #182 from raiseCatError/feature/176-linguist-langu…
raiseCatError Oct 3, 2026
971d273
Merge pull request #251 from raiseCatError/docs/v08-continuation-fina…
raiseCatError Oct 3, 2026
41a79aa
Merge pull request #250 from raiseCatError/test/208-fixture-writers
raiseCatError Oct 3, 2026
f62537e
Merge pull request #249 from raiseCatError/docs/v08-continuation-acce…
raiseCatError Oct 3, 2026
1708520
Merge pull request #248 from raiseCatError/fix/v08-continuation-harde…
raiseCatError Oct 3, 2026
a8bd35e
Merge pull request #247 from raiseCatError/test/208-tmpdir-hygiene
raiseCatError Oct 3, 2026
a120fcc
Merge pull request #246 from raiseCatError/feature/v08-command-notifi…
raiseCatError Oct 3, 2026
8d38e2d
Merge pull request #245 from raiseCatError/feature/v08-block-actions
raiseCatError Oct 3, 2026
072a474
Merge pull request #244 from raiseCatError/feature/v08-command-inspector
raiseCatError Oct 3, 2026
ae9b174
Merge pull request #241 from raiseCatError/docs/v08-command-intellige…
raiseCatError Oct 3, 2026
9a6ba4a
Merge pull request #240 from raiseCatError/fix/v08-intelligence-harde…
raiseCatError Oct 3, 2026
d61d144
Merge pull request #239 from raiseCatError/feature/152-safe-command-c…
raiseCatError Oct 3, 2026
941076f
Merge pull request #238 from raiseCatError/feature/147-directory-navi…
raiseCatError Oct 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 38 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ on:
push:
branches: [master, dev]
pull_request:
branches: [master, dev]
# Stacked PRs need the same gates as integration PRs.

workflow_dispatch:

permissions:
Expand All @@ -16,11 +17,13 @@ concurrency:

jobs:
verify:
name: Verify
runs-on: macos-latest
name: Verify (${{ matrix.os }}, Node ${{ matrix.node-version }})
runs-on: ${{ matrix.os }}
timeout-minutes: 10
strategy:
fail-fast: false
matrix:
os: [macos-latest, ubuntu-24.04]
node-version: [22.x, 26.x]

steps:
Expand All @@ -33,6 +36,28 @@ jobs:
node-version: ${{ matrix.node-version }}
cache: 'npm'

- name: Install Linux shell and native build prerequisites
if: runner.os == 'Linux'
run: sudo apt-get update && sudo apt-get install -y zsh build-essential python3

- name: Verify secure Linux system completion paths
if: runner.os == 'Linux'
run: |
# Hosted image completion directories can be group-writable. Global
# compinit then prompts before NMSh's isolated startup files run.
insecure="$(zsh -fc 'autoload -Uz compaudit; compaudit' 2>/dev/null || true)"
while IFS= read -r path; do
[ -z "$path" ] && continue
case "$path" in
/usr/share/zsh|/usr/share/zsh/*|/usr/local/share/zsh|/usr/local/share/zsh/*)
sudo chown root:root "$path"
sudo chmod go-w "$path"
;;
*) echo "::error::Unexpected insecure completion path: $path"; exit 1 ;;
esac
done <<< "$insecure"
zsh -fc 'autoload -Uz compaudit; compaudit'

- name: Install dependencies
run: npm ci

Expand All @@ -42,15 +67,23 @@ jobs:
- name: Typecheck
run: npm run typecheck

- name: Typecheck benchmark script
run: npx tsc --ignoreConfig --noEmit --types node --target ES2022 --module NodeNext --moduleResolution NodeNext --esModuleInterop --skipLibCheck scripts/benchmarks.ts scripts/platform-benchmarks.ts

- name: Bounded platform timing smoke
run: |
node --import=tsx scripts/platform-benchmarks.ts
NMSH_BENCH_SAMPLES=5 NMSH_BENCH_WARMUP=1 npm run bench -- completion/configured-cold completion/configured-warm composer/screen-plan transcript/wrap-present-10000

- name: Run tests
run: npm test
run: npm test -- --test-timeout=120000

- name: Verify working tree clean
run: git diff --check

- name: Process leak check
run: |
if ps -axo pid,ppid,pgid,command | grep -E '[z]sh.*nmsh-semantic|[n]msh-semantic|viewportSyntax' | grep -v grep; then
if ps -axo pid,ppid,pgid,command | grep -E '[z]sh.*nmsh-semantic|[n]msh-semantic|[c]onfigured-completion\.zsh|[c]apture\.zsh|[v]iewportSyntax' | grep -v grep; then
echo "::error::NMSh helper or test processes leaked!"
exit 1
fi
Expand Down
56 changes: 49 additions & 7 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
|---|---|
| **Current release** | [v0.7.0 — UI Foundation & Customization](https://github.com/raiseCatError/notMyShell/releases/tag/v0.7.0) |
| **Development branch** | `dev` |
| **Next direction** | Not yet defined; see the Backlog below and open issues |
| **Next direction** | [v0.8.0 — Command Intelligence & Navigation](https://github.com/raiseCatError/notMyShell/milestone/8), in development |
| **Stacked development** | [v0.9.0 — Tools, Integrations & Workflows](https://github.com/raiseCatError/notMyShell/milestone/9), development-complete, unmerged; physical QA pending |
| **Prior stacked milestone** | [v0.10.0 — Terminal Hosts & Compatibility](https://github.com/raiseCatError/notMyShell/milestone/10), development acceptance complete as an unmerged stack; [evidence and limitations](docs/testing/v010-acceptance.md), physical QA pending |
| **Current stacked milestone** | [v0.13.0 — Portability & Platform Foundations](https://github.com/raiseCatError/notMyShell/milestone/13), Linux runtime/CI and Windows feasibility; unmerged, physical QA deferred |
| **Project board** | [NMSh Development](https://github.com/users/raiseCatError/projects/1) |

GitHub issues define actionable remaining work. A merged implementation may still be open with `needs-human-test` while physical terminal checks are pending. Closed issues represent completed work, not a promise that future refinements are finished.
Expand Down Expand Up @@ -112,6 +115,50 @@ The final release candidate also included the passive-hover selection fix.
| [#172](https://github.com/raiseCatError/notMyShell/issues/172) | Semantic motion engine; shimmer migrated onto it |
| [#173](https://github.com/raiseCatError/notMyShell/issues/173) | Deterministic presentation mode |

## In development — v0.8.0 Command Intelligence & Navigation

[Milestone #8](https://github.com/raiseCatError/notMyShell/milestone/8) contains #140, #141, #142, #143, #144, #145, #147 and #152. The [architecture and implemented scope](docs/design/command-intelligence.md) describe the unmerged review stack; the [physical-QA checklist](docs/qa/v0.8.0-physical-qa.md) remains pending. Package version stays at 0.7.0 during development.

Native structured completion, command-level history, reusable optional pickers, explicit directory navigation and conservative edit-only corrections build on the released UI foundation. External completion sources remain research; #52 stays parked. #155 / #193 supply measurements without absorbing the full performance issue into this milestone.

The earlier milestone #7 now represents unscheduled Discoverability & Integrations; its unrelated scope remains separate.

The continuation's final acceptance head is [#251](https://github.com/raiseCatError/notMyShell/pull/251),
`docs/v08-continuation-final-verification` at `2dfbf9c12c54ada8af364bc44db87bc70f0b77c0`.
It includes command inspector, block actions, notifications and fixture hygiene.
These remain implemented/unmerged with cumulative physical QA pending, not reopened backlog.

## Stacked development — v0.9.0 Tools, Integrations & Workflows

[Milestone #9](https://github.com/raiseCatError/notMyShell/milestone/9) adopts #9,
#83, #153, #154, #176, #177 and #178. Research children #252 (supported config)
and #253 (mise awareness) are also included. #176/#177/#178 moved from the
unscheduled grouping; #179/#180 remain there. The stack consumes the pinned
final v0.8 head without modifying or merging it; package version remains 0.7.0.

Review order: #251 → #182 → #181 → #183 → #254 → #255 → #256 (#253)
→ #257 (#153) → final acceptance on `docs/v09-final-acceptance`.
Linguist identity, external welcome adapters, deterministic VHS tooling,
supported Starship configuration, Tools discovery/install, consent-based optional
mise awareness and new-live-session presets are implemented in the unmerged stack.
The ENOSPC checkpoint was resumed and #255 local verification passed; it is ready
for review. See the [final development record](docs/development/v0.9.0-final-acceptance.md)
and [single additive QA checklist](docs/qa/v0.9.0-physical-qa.md).
Physical QA remains pending, issues remain open, version remains 0.7.0, and v0.9
has not shipped. No unrelated backlog or release preparation is included.

## Stacked development — v0.13.0 Portability & Platform Foundations

[Milestone #13](https://github.com/raiseCatError/notMyShell/milestone/13) contains
Linux research #18, Windows research #19, Linux implementation #279 and
portability hardening #281. Its frozen cumulative base is PR #278 at
`cfc9c08a5fb7b5f3bc637400a59da7a714a58ae4`; lower published branches are unchanged.
Review #278 → #280 (Linux baseline/CI) → #282 (portability hardening) → final
v0.13 acceptance/docs PR. Every PR targets its immediate predecessor; no merge
or release is authorized. Package and lockfile remain 0.7.0. Physical QA is
intentionally deferred. Custom prompts #73, graphics #151, layout #79 and new
shell backends are outside this milestone.

## Backlog — Research and Future Features

These remain open and are not scheduled for a release.
Expand All @@ -120,13 +167,8 @@ These remain open and are not scheduled for a release.
|---|---|
| [#52](https://github.com/raiseCatError/notMyShell/issues/52) | Configured-zsh completion parity and fzf-tab interoperability |
| [#75](https://github.com/raiseCatError/notMyShell/issues/75) | Native parity with common zsh editor plugins |
| [#9](https://github.com/raiseCatError/notMyShell/issues/9) | Optional shell-tool discovery and first-run setup |
| [#73](https://github.com/raiseCatError/notMyShell/issues/73) | Custom user-defined prompt modules |
| [#78](https://github.com/raiseCatError/notMyShell/issues/78) | Chroma: gradients, animated color treatments, and transient visual effects |
| [#83](https://github.com/raiseCatError/notMyShell/issues/83) | Tool configuration center inside `/settings` |
| [#84](https://github.com/raiseCatError/notMyShell/issues/84) | Command inspector |
| [#85](https://github.com/raiseCatError/notMyShell/issues/85) | Interactive command/output block controls |
| [#106](https://github.com/raiseCatError/notMyShell/issues/106) | Command completion notifications for long-running commands |

zsh-autosuggestions and zsh-syntax-highlighting are not required plugins; NMSh provides those UI roles natively.

Expand All @@ -148,7 +190,7 @@ NMSh provides the surrounding interaction and presentation layer; tools such as

## Longer Term — Shells and Platforms

zsh remains the only first-class backend. ShellAdapter research and Linux/Windows investigations remain future work; multi-shell and those platform targets are not promised today.
zsh remains the only first-class backend. v0.13 implements a Linux development baseline and researches Windows/ConPTY/WSL; it is not a public platform release. Native Windows and additional shell backends remain unsupported. See [Linux foundations](docs/architecture/v013-linux-foundations.md), [Windows feasibility](docs/architecture/v013-windows-feasibility.md), and [deferred portability QA](docs/testing/v013-physical-qa.md).

| Issue | Title |
|---|---|
Expand Down
1 change: 1 addition & 0 deletions dev/tapes/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
output/
23 changes: 23 additions & 0 deletions dev/tapes/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# VHS development demos

These optional VHS tapes capture welcome, Settings v2, an ordinary command and native history selection. They are development tooling only; NMSh does not depend on VHS at runtime, and `npm test` does not invoke it.

## Run

From the repository root, install the normal project dependencies if needed, then run:

```sh
npm run build
mkdir -p dev/tapes/output
vhs validate 'dev/tapes/*.tape'
vhs dev/tapes/welcome.tape
vhs dev/tapes/settings.tape
vhs dev/tapes/command.tape
vhs dev/tapes/intelligence.tape
```

VHS writes GIFs under `dev/tapes/output/`, which is ignored by Git. VHS is not installed automatically. Install it using the instructions in the [official VHS repository](https://github.com/charmbracelet/vhs) if you want to record these demos.

The launch helper isolates HOME/preferences, disables update checks, opts out of the session service and uses the current `NMSH_DETERMINISTIC=1` seam. It never edits user config or attaches an existing session. Each tape exits so the helper can remove its private directory. Deterministic presentation freezes decorative motion and the completion clock only; real command durations, scheduling, font, build identity and cwd still vary. Review captures before sharing; these are not pixel goldens.

Prefer VHS 0.12.1 or later: the previously tested host 0.12.0 binary reported success without materializing recordings. Validation is useful locally; visual-golden CI is deferred because font/host/timing differences would make it fragile. No end-user QA or optional-tool installation is required. Keep captures short and offline.
20 changes: 20 additions & 0 deletions dev/tapes/command.tape
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Require node
Require zsh

Output dev/tapes/output/command.gif
Set Shell "zsh"
Set Width 1200
Set Height 650
Set FontSize 18
Set TypingSpeed 60ms

Hide
Type "node dev/tapes/launch.mjs" Enter
Wait+Screen /notMyShell/
Show
Type "echo 'Hello from NMSh'" Enter
Wait+Screen /Hello from NMSh/
Sleep 2s
Hide
Ctrl+D
Sleep 1s
22 changes: 22 additions & 0 deletions dev/tapes/intelligence.tape
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
Require node
Require zsh

Output dev/tapes/output/intelligence.gif
Set Shell "zsh"
Set Width 1200
Set Height 650
Set FontSize 18
Set TypingSpeed 60ms

Hide
Type "node dev/tapes/launch.mjs" Enter
Wait+Screen /notMyShell/
Show
Type "printf demo" Enter
Sleep 1s
Type "/history" Enter
Sleep 2s
Hide
Escape
Ctrl+D
Sleep 1s
31 changes: 31 additions & 0 deletions dev/tapes/launch.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import {spawn} from 'node:child_process';
import {mkdtempSync, mkdirSync, writeFileSync, rmSync} from 'node:fs';
import {tmpdir} from 'node:os';
import {join, resolve} from 'node:path';

// Isolate demo preferences and zsh startup; never change the user's config.
const root = mkdtempSync(join(tmpdir(), 'nmsh-demo-'));
const config = join(root, 'config', 'nmsh');
mkdirSync(config, {recursive: true});
writeFileSync(join(config, 'config.json'), JSON.stringify({onboardingComplete: true,
glyphChoiceComplete: true, glyphStyle: 'safe', welcome: 'vespyr', updateChecks: false,
liveSessionStartup: 'never', composerPosition: 'bottom', transcriptPresentation: 'normal'}));
try {
const child = spawn(process.execPath, [resolve('dist/index.js'), '--new'], {stdio: 'inherit',
env: {...process.env, HOME: root, XDG_CONFIG_HOME: join(root, 'config'),
NMSH_DETERMINISTIC: '1', NMSH_SESSION_SERVICE: '0'}});
const forward = () => child.kill('SIGTERM');
process.on('SIGINT', forward);
process.on('SIGTERM', forward);
try {
process.exitCode = await new Promise((accept, reject) => {
child.once('error', reject);
child.once('exit', code => accept(code ?? 1));
});
} finally {
process.off('SIGINT', forward);
process.off('SIGTERM', forward);
}
} finally {
rmSync(root, {recursive: true, force: true});
}
25 changes: 25 additions & 0 deletions dev/tapes/settings.tape
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
Require node
Require zsh

Output dev/tapes/output/settings.gif
Set Shell "zsh"
Set Width 1200
Set Height 650
Set FontSize 18
Set TypingSpeed 60ms

Hide
Type "node dev/tapes/launch.mjs" Enter
Wait+Screen /notMyShell/
Type "/settings" Enter
Wait+Screen /Settings/
Show
Sleep 2s
Right
Sleep 1s
Right
Sleep 1s
Hide
Escape
Ctrl+D
Sleep 1s
18 changes: 18 additions & 0 deletions dev/tapes/welcome.tape
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Require node
Require zsh

Output dev/tapes/output/welcome.gif
Set Shell "zsh"
Set Width 1200
Set Height 650
Set FontSize 18
Set TypingSpeed 60ms

Hide
Type "node dev/tapes/launch.mjs" Enter
Wait+Screen /notMyShell/
Show
Sleep 3s
Hide
Ctrl+D
Sleep 1s
15 changes: 15 additions & 0 deletions docs/architecture/language-identity-colors.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Language identity colors

NMSh exposes GitHub Linguist's language colors as identity data for tool cards and project metadata. These colors identify a language only. They do not indicate success, warning, failure, focus, or any other UI state. `languageIdentity(name)` returns Chroma's existing identity category; `statusMeaning` is always undefined for it. Consumers use Chroma's capability fallback and retain text labels with NO_COLOR. The dataset does not repaint existing prompt themes.

The generated mapping is checked in at `src/languages/linguistLanguageColors.generated.ts`. Normal rendering reads only this local TypeScript data and makes no network request. `languageIdentityColor(name)` normalizes Unicode, case, and whitespace; it recognizes canonical names and aliases published by Linguist. Unknown names return the neutral `UNKNOWN_LANGUAGE_IDENTITY_COLOR` value.

## Provenance and license

The source is [`github-linguist/linguist`'s `lib/linguist/languages.yml`](https://github.com/github-linguist/linguist/blob/main/lib/linguist/languages.yml). Linguist describes the `color` field as its CSS color for a language, and documents that aliases are used for language lookup. The source repository is distributed under the [MIT License](https://github.com/github-linguist/linguist/blob/main/LICENSE), reproduced at `licenses/GITHUB-LINGUIST-MIT.txt`. The generated file records the exact Linguist commit used.

## Updating the mapping

Run `node scripts/update-linguist-language-colors.mjs` intentionally when updating the cached dataset. The script reads the current Linguist revision, fetches its pinned `languages.yml`, extracts only names, aliases, and valid `#RRGGBB` colors, and writes entries in stable name order. Review the generated diff and source revision with the normal code review. Build, tests, and runtime do not invoke this script or require network access.

To add or change consumers, import `languageIdentityColor` from `src/languages/linguistLanguageColors.ts`. Keep any contrast-adjusted display color local to that rendering consumer; do not overwrite the identity color or use it as a semantic status color.
50 changes: 50 additions & 0 deletions docs/architecture/mise-project-awareness.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Optional mise project awareness

Refs #253 / #154. NMSh works without mise. `/tools` → mise → **M project
awareness** is also reachable through Settings and the command palette's Tools
action. Opening it checks executable availability and standard local/ancestor
markers using filesystem metadata only. It never reads templates or invokes
mise, even after cwd changes. The ordinary tools catalog does not version-probe
mise. Existing real-zsh hooks remain authoritative.

**I inspect** and **R refresh** open a default-No confirmation showing the two
metadata commands and explaining template execution and remote task fetching.
Only affirmative intent invokes `mise ls --current --json`, then
`mise tasks ls --json`. No `trust`, activation, config edits, installation or
environment application occurs. Refresh requires renewed consent. Esc cancels
the review or aborts the active detached metadata process group.

The dedicated capture uses argv, ignored stdin, a three-second deadline per
command and 128 KiB combined stdout/stderr limit. stderr is discarded; failures
are generic. JSON parsing retains tool names/versions and task names only.
Unknown fields, including `env`, `run`, descriptions and source paths, never
enter UI/cache/persistence. Metadata remains in memory, bounded to 32 identities
keyed by canonical cwd, binary and ancestor marker/project stat identity. Config
changes invalidate an identity; explicit refresh reruns inspection. No typing or
rendering invocation exists. A failed inspection is cached factually.

Task Enter inserts a quoted visible `mise run '<task>'` into the composer. A
separate Enter submits it through ordinary real-zsh execution. Tasks may execute
project actions or install tools; returned names carry no safety endorsement.
Option-like/control-containing names are rejected. No environment values or new
settings are persisted.

Current upstream behavior was checked against the
[ls reference](https://mise.jdx.dev/cli/ls.html),
[task-list reference](https://mise.jdx.dev/cli/tasks/ls.html),
[template execution warning](https://mise.jdx.dev/templates.html), and tagged
[`v2026.9.18` task source](https://github.com/jdx/mise/blob/v2026.9.18/src/cli/tasks/ls.rs).
The tool JSON is an object of version arrays; task JSON is an array of objects.
Task listing may fetch remote task files and evaluates resolved task directories.
The consent screen therefore does not describe metadata as side-effect-free.

Standard marker coverage is conservative, not a full reimplementation of mise
config selection: `mise.toml`, `.mise.toml`, `.mise/config.toml`,
`.config/mise/config.toml`, `.tool-versions`. Environment-specific/custom config
may exist without a detected marker. Metadata inspection remains explicitly
available when installed. There is no automatic task argument editor, active
hook inference or persistent metadata/consent.

Fake executable tests cover trust boundaries, bounded failures, schema/cache,
quoting and composer integration. Physical QA remains separate and only needs
mise checks when already installed/configured.
Loading
Loading