Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
9 changes: 9 additions & 0 deletions docs/development/native-appearance-welcome/DECISIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,12 @@ Ruling: preserve valid unchanged numeric blur above the normal UI range during u
- Assets: absolute, cwd-relative and `~/` paths plus a local picker filtered to PNG/JPEG/WebP/GIF/APNG/.ans/.txt. Admission before decode: ≤8 MiB, ≤2,000,000 source pixels; GIF/APNG through the bounded decoder (#518: 75 frames, 32 MiB, 5 s). ANSI/ASCII ≤64 KiB, 40 rows, 240 columns, printable text + numeric SGR only. Originals are never modified; no persistent derived cache. External capture sanitization unchanged; one capture per provider, shared.
- One composition: `composeWelcome` (pure) drives the editor preview, startup and the P preview through `NativeWelcomePresentation`/`paintWelcome`; one `WelcomeSequencer` on the shared PresentationClock (≤5 s, ≤~30 repaints/s at startup); Reduced Motion / Effects Off / NO_COLOR give frame 0 with no subscription. Still-image effects are whole-image Portable treatments (no segmentation or invented motion).
- Startup playback never blocks the composer; input, resize, scroll, handover and shutdown stop it and release graphics by owner; a loading image says "Loading image…" and stores no still. P shows the current draft on NMSh's own alternate screen (no OS resize, no new session, no re-capture); any key closes it and is swallowed; draft and selection return unchanged.

## Native host fixes (2026-10-29)

- Host identity: one `terminalProfile()` for every surface. A terminal-specific `TERM` (`xterm-kitty`, `xterm-ghostty`) wins over `TERM_PROGRAM`. Cursor facts and `detectTerminalHost` use it. Inside tmux, the outer host's markers still name the host, as before.
- First run: `/cursor › Host native setup` in Kitty 0.49+ opens the Kitty studio even without the older include. Kitty below 0.49 keeps the built-in `cursor_trail` setup.
- A Kitty trail that is written must also be drawn. NMSh's own fragment sets `cursor_trail 3` when the effective value would otherwise be 0. This is judged without NMSh's own line, so later syncs keep it. A later line forcing 0 refuses. Confirming a trail sets `/cursor` Motion Off → Tail and Portable → Auto, and the review says so. Motion Off removes NMSh's trail, like a Portable renderer.
- Reload: after a confirmed write, a removal or a gate sync, NMSh sends Kitty's documented SIGUSR1 to `KITTY_PID`, but only when that process is one of NMSh's parents and its program is kitty. Otherwise it shows the reload keys. The review discloses this before writing. Ghostty is unchanged: it is never signalled, and L marks the reload.
- Host native chosen before setup: Portable draws, labelled "Portable fallback · <host> native is not set up yet". Before this, the cursor looked frozen. A host with no native effects keeps "Host native is not available".
- Previews: each trail style has its own shape (Blaze band, Lightning bolt and forks, Motion-blur ghosts, Comet taper, plain tail).
1 change: 1 addition & 0 deletions docs/development/native-appearance-welcome/QA_CHECKLIST.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Automated tests use private HOMEs, headless host parsers and proxy compiles. Non
## Kitty (0.49.x)

### Kitty shaders
0. First run: in a Kitty opened from a Ghostty or Zed shell, `/appearance` shows "Kitty shaders" (not Ghostty), and `/cursor` › Host native setup opens the Kitty studio. Switch Lightning ↔ Blaze: the bolt vs the amber band changes without a manual reload ("Kitty was asked to reload…").
1. Open `/appearance` → Kitty shaders. Enable Lightning trail, Northern Lights, then CRT or CRT (blue) (only one can be on), and Bloom or Water.
2. Check the review diff. Your `custom_shaders` names stay in order, and placement is Before/After.
3. Kitty auto-reloads. Check that every effect is visible and that there is exactly one cursor trail.
Expand Down
9 changes: 9 additions & 0 deletions docs/development/native-appearance-welcome/RESEARCH.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,12 @@ Kitty0.49.2 installed catalog probe (headless, private HOME): read_kitty_resourc
- Observed ordering with `+show-config` (both versions): root `config` → root `config.ghostty` → macOS roots → include queue in encounter order; relative include and shader paths resolved per file.
- Compile check: Kitty's bundled `slangc -lang glsl -allow-glsl -stage fragment -target spirv` compiles prefix+shader (rejects re-declaring gl_FragCoord, so that one prefix line is dropped). It accepts every NMSh preset and rejects a 1.3-only preset against the 1.2 prefix and real type errors. It is a PROXY: Ghostty uses glslang + SPIRV-Cross/Metal; GPU output is not verified.
- Third-party shaders (sahaj-b/cursor-shaders MIT, hackrdotsh/ghostty-shaders unverified) were not downloaded, executed or used; NMSh's presets are original.

## Native host fixes (verified 2026-10-29, Kitty 0.49.2, Ghostty 1.3.1; evidence /Volumes/T7Tmp/ai-dev/nmsh-native-host-fixes-20261029)

- Host identity: Kitty sets `TERM=xterm-kitty`, `KITTY_WINDOW_ID`, `KITTY_PID` and passes an inherited `TERM_PROGRAM` through unchanged. A Kitty started from a Ghostty shell reported `TERM_PROGRAM=ghostty`, `TERM_PROGRAM_VERSION=1.3.1` and `GHOSTTY_RESOURCES_DIR` (kitty-env/env.txt), so NMSh treated it as Ghostty. The terminal's own `TERM` is the stronger signal.
- Shipped shaders read through `read_kitty_resource` (kitty-probe/out): Blaze is a filled amber parallelogram with a red edge (0.5 s). Lightning is a 12-segment jagged bolt with 3 forks (0.14 s, bolt #ffd1b8, glow #bd0000). Motion blur and Default differ again. The four pipelines share one structure (cursor-trail-move/stop); NMSh's emitted pipelines referenced the right shader.
- Kitty draws trail shaders only while `cursor_trail` > 0. `/cursor` Motion Off writes `cursor_trail 0`, and Kitty's default is 0.
- Kitty's config watcher (`kitten __watch_conf__`) watches only kitty.conf (and /etc/xdg/kitty/kitty.conf), not included files. NMSh's preset switch changes only its included pipeline, so Kitty kept drawing the previous effect. Kitty documents SIGUSR1 as "reload config". One SIGUSR1 reloaded an unchanged `custom_shaders` path (kq/shots/exp-*.png).
- Ghostty on macOS reads its macOS config even with a private HOME, and NMSh refuses `--config-file` launches by design, so an NMSh-driven Ghostty write cannot run against a private config. The generated passes were checked by loading them in an isolated instance instead.
- Official references: https://sw.kovidgoyal.net/kitty/custom-shaders/, https://sw.kovidgoyal.net/kitty/conf/ (cursor_trail, auto_reload_config, SIGUSR1 reload), https://ghostty.org/docs/config/reference (command, custom-shader).
6 changes: 6 additions & 0 deletions docs/development/native-appearance-welcome/TEST_RESULTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,9 @@ NOT RUN: physical terminal QA of image/animation playback and P; GPU/graphics pr
- Welcome startup frame (compose + paint, 120 columns) 0.14–0.19 ms; at ≤30 repaints/s for ≤5 s that is under 30 ms CPU in total; asset admission (64×64 PNG 0.45 ms, 12-frame GIF 3.6 ms) runs off the readiness path.
- CI recorded once per PR (2026-10-29 ~00:35): #517, #519, #520 all checks pass; #521 pending; #518 failed one live test on Ubuntu (`/resume shows LIVE and ARCHIVED…` timed out waiting for `sleep` to run; Verify jobs fail as its dependants) — a live session test unrelated to the graphics-only change, not rerun (policy).
- NOT RUN: physical QA (QA_CHECKLIST.md), GPU output, whole-app idle RSS/CPU on real hosts.

## Native host fixes (Claude, 2026-10-29; branch fix/native-host-shaders-20261029)

- Related focused tests: 180/180 pass, run through the repository runner's isolation (appearanceHub, cursorCapabilities, cursorEffects, cursorVisuals, ghosttyShaderPanel, ghosttyShaders, graphicsCapabilities, hostAppearance, hostIntegration, hostProfiles, kittyShaderPanel, kittyShaders, renderRouting, setupCoverage, shaderPreview, terminalHost, textSizing). tsc is clean. Red check: the 7 new or changed regressions fail on the original source.
- Physical Kitty 0.49.2 QA (disposable config, inherited TERM_PROGRAM=ghostty, build ebe54eb). The Kitty studio was offered, and the first-run `/cursor` Host native route opened it. Lightning drew an electric bolt on the GPU; Blaze drew an amber flame band. NMSh-only switching was correct 4/4 in cycles, with 1 earlier miss in 7 switches on a freshly launched Kitty that did not recur. Blaze + Northern Lights + CRT were visible, with 5 groups and one trail. R removed everything, restored kitty.conf byte for byte, and the effects were gone. Screenshots: /Volumes/T7Tmp/ai-dev/nmsh-native-host-fixes-20261029/kq/shots.
- Physical Ghostty 1.3.1 GPU check: NMSh-generated Comet + Aurora loaded in an isolated instance were visible (gq/shots). NMSh-driven Ghostty write, the Portable switch and removal were NOT RUN physically, because they would write the real Ghostty config; private-HOME tests cover them.
Loading
Loading