# Changelog
## 0.4.6 (2026-04-25)
### CI
- Build and install `libghostty-vt` in the live terminal example job so browser feature tests can load the Ghostty NIF
## 0.4.5 (2026-04-25)
### Fixed
- Fixed TTY NIF reader thread ownership by storing the thread and closed flag in the resource payload instead of a copied payload
## 0.4.4 (2026-04-25)
### Testing
- Give the TTY end-to-end test parent process enough time to observe the child process's explicit timeout result instead of racing the same deadline
## 0.4.3 (2026-04-24)
### TTY
- Add explicit current-terminal input backends with OTP raw mode on OTP 28+ and NIF fallback on older OTP releases
- Require explicit `takeover: true` before the NIF backend stops OTP's shell reader
- Route `Ghostty.TTY.write/2` through the active TTY backend so raw TTY sessions do not depend on OTP's shell writer
### PTY
- Route PTY NIF events through the `Ghostty.PTY` GenServer so public data and exit messages are owned by the Elixir process
- Add a reader-start handshake before `Ghostty.PTY.start_link/1` returns, with configurable `:reader_start_timeout`
- Keep PTY reader threads owned by the NIF resource and join them during close to avoid fd reuse races
- Move argv preparation before `forkpty()` so the child process only execs or exits after fork
## 0.4.2 (2026-04-24)
### TTY
- Fix current-terminal input delivery by backing `Ghostty.TTY` with the existing terminal NIF
- Disable terminal-generated signals for raw TTY sessions so Ctrl-C is delivered as a `Ghostty.KeyEvent` instead of opening the BEAM BREAK menu
- Add a PTY-backed end-to-end test proving `Ghostty.TTY` receives typed characters and Ctrl-C in raw mode
## 0.4.1 (2026-04-24)
### TTY
- Fix `Ghostty.TTY.start_link/1` on OTP runtimes that do not expose `:sigwinch` through `:os.set_signal/2`
- Treat SIGWINCH registration as best-effort so current-terminal apps can still start when resize signals are unavailable
## 0.4.0 (2026-04-24)
### TTY
- Add `Ghostty.TTY` for local terminal applications that need raw keyboard input from the current BEAM terminal
- Add `Ghostty.KeyDecoder` for decoding terminal input bytes into `Ghostty.KeyEvent` values
- Add `examples/tty_keys.exs` as an interactive smoke test for current-terminal input, resize events, and key decoding
### Testing
- Add `Ghostty.Test` ExUnit helpers for concise terminal tests: `term/1`, `write/2`, `lines/2`, snapshots, text assertions, key encoding, and cell assertions
- Add snapshot assertion support via `assert_snap/3` with `UPDATE_GHOSTTY_SNAPSHOTS=1`
- Dogfood `Ghostty.Test` in terminal and cell tests
### Terminal
- Return `{:error, :invalid_key_event}` for invalid keyboard events instead of crashing the terminal GenServer
- Return `{:error, :invalid_mouse_event}` for invalid mouse events instead of crashing the terminal GenServer
### Docs
- Document `Ghostty.TTY` and ExUnit helpers in the README
- Add `Ghostty.TTY`, `Ghostty.KeyDecoder`, and `Ghostty.Test` to HexDocs groups and package files
## 0.3.2 (2026-04-14)
### Fix
- Fix precompiled NIF failing to load due to missing `nif_focus_mode` declaration
## 0.3.1 (2026-04-14) [YANKED]
### LiveView
- Add punctuation and shifted character key mappings
### PTY
- Fix UI hangs when typing fast by draining the PTY buffer fully on each poll wakeup
- Handle POLLHUP/POLLERR without POLLIN to ensure exit notification is always sent
### Internal
- Remove unused `nif_focus_mode` NIF
- Cache `nif_render_state` availability at compile time instead of try/rescue per call
- Deduplicate PTY reader exit path into `send_exit_and_wait`
- Remove redundant client-side input validation (kept in GenServer)
- Remove self-delegating `mods_to_bitmask` in favour of `to_bitmask`
## 0.3.0 (2026-04-08)
### LiveView
- Add render-state cursor overlay with block, bar, underline, and hollow styles
- Add hidden textarea input layer with IME composition and paste support
- Add local selection rendering with copy support
- Add mouse forwarding with mouse-mode-aware selection backoff
- Add `fit` option for auto-fit terminal size to container via `ResizeObserver`
- Add `autofocus` option for initial terminal focus on mount
- Add `{:terminal_ready, id, cols, rows}` message so the parent can defer PTY startup until the real container size is known
- Add `handle_resize/4` helper for resizing terminal and PTY together
- Add `phx-update="ignore"` to terminal hook roots so LiveView patches don't destroy client-rendered DOM
- Fix focus escape sequences being written into the terminal buffer when no PTY is attached
- Fix terminal reclaiming focus from outside page elements during text selection
- Track mouse modes in `Ghostty.Terminal` from VT writes for reliable LiveView payloads
### Hook
- Rewrite `ghostty.js` to TypeScript under `priv/ts/` with strict types
- Bundle TypeScript at compile time via OXC — no Node.js or Bun required
- Add oxlint and oxfmt for TypeScript quality checks
- Ship `priv/ts/` source in the Hex package instead of pre-built JS
- Add explicit outside-click blur so the terminal doesn't steal focus
- Add pointer-active tracking so outside mouse interactions can't refocus the terminal
### Examples
- Replace URL-param demo with a control panel: startup command input, fit/banner toggles, preset buttons
- Add `TERM=xterm-256color` and `COLORTERM=truecolor` for colorized shell output
- Add demo-specific bash rcfile with `ls` color aliases
- Use `bash -lc` for startup commands to avoid PTY write races
- Defer PTY startup until the hook reports its real container size
- Replace timer-based startup with event-driven ready handshake
- Add browser tests for flush-left prompt, outside focus, and demo controls
- Wire example browser tests into CI
### Build
- Add `{:oxc, "~> 0.5"}` dependency for compile-time TypeScript bundling
- Add a Mix compiler that bundles `priv/ts/hook.ts` → `priv/static/ghostty.js`
- Add CI job for TypeScript lint and format checks
- Stop tracking `priv/static/ghostty.js` in git
## 0.2.4 (2026-04-02)
### LiveView
- Add `mix igniter.install ghostty` to vendor `ghostty.js` into Phoenix assets and wire `GhosttyTerminal` into `assets/js/app.js`
- Cover the installer with tests for common Phoenix `app.js` layouts
- Update the LiveView docs to point to the Igniter install flow
## 0.2.3 (2026-04-02)
### Build
- Exclude the bundled Phoenix example app dependencies from the Hex package
- Keep the published package small enough for Hex validation while still shipping the top-level example scripts
- Fix the macOS precompiled terminal artifact so `libghostty-vt.dylib` is linked via `@loader_path` instead of a CI-only absolute path
- Verify the packaged macOS terminal artifact before upload in the precompile workflow
## 0.2.2 (2026-04-01)
### LiveView
- Make render events terminal-specific so multiple terminals can coexist in one LiveView safely
- Push the initial render automatically from `Ghostty.LiveTerminal.Component`
- Preserve incoming assigns on `send_update(..., refresh: true)`
- Support global HTML attributes on `Ghostty.LiveTerminal.terminal/1`
- Refresh the README LiveView docs around the component-first API
### Build
- Re-sync `priv/lib` and `priv/include` into `_build/<env>/lib/ghostty/priv` during `GHOSTTY_BUILD=1` compilation
- Fix macOS source builds after `_build` cleanup by rewriting the copied `libghostty-vt.dylib` install name to an absolute path
## 0.2.1 (2026-03-31)
### PTY
- Validate PTY size during startup as well as `resize/3`
- Remove generated PTY Zig wrapper file from the repo
- Ignore generated PTY Zig wrapper file going forward
### Build
- Make `mix ghostty.setup` copy `priv/` artifacts more robustly from the project root
- Refresh build `priv/` directories deterministically during setup
### Docs
- Use GitHub example links in README so HexDocs does not warn about missing local `examples/` paths
## 0.2.0 (2026-03-30)
### Terminal
- `input_key/2` — encode keyboard events to escape sequences
- `input_mouse/2` — encode mouse events (when tracking enabled)
- `encode_focus/1` — encode focus gained/lost
- `cells/1` — render state as grid of `{grapheme, fg, bg, flags}` tuples
- `Ghostty.Terminal.Cell` — flag helpers (`bold?/1`, `italic?/1`, etc.)
- Effect messages sent to the calling process:
`{:pty_write, data}`, `:bell`, `:title_changed`
- Option validation — `ArgumentError` for invalid cols/rows/scrollback
- Graceful init failure — `{:error, reason}` instead of crash
### PTY
- Real pseudo-terminal via `forkpty()` NIF
- Programs like `vim`, `top`, `htop` work (child gets a real TTY)
- Non-blocking reader thread sends `{:data, binary}` messages
- `write/2`, `resize/3`, `close/1`
- Proper cleanup in destructor (SIGHUP, waitpid)
### LiveView
- `Ghostty.LiveTerminal` — Phoenix LiveView component
- `terminal/1` component with JS hook
- `handle_key/2` converts JS keyboard events to key encoding
- `priv/static/ghostty.js` — renders cell grid with colors and styles
- Optional: only compiles when `phoenix_live_view` is present
### Input
- `Ghostty.KeyEvent` — strict validation, raises on unknown keys
- `Ghostty.MouseEvent` — strict validation, raises on unknown buttons
### Build
- `mix ghostty.setup` — one-command contributor onboarding
- Precompiled NIFs via `zigler_precompiled`
- Precompile workflow builds and uploads terminal and PTY NIF artifacts for Linux x86_64, Linux aarch64, and macOS aarch64
- Precompiled terminal artifacts bundle `libghostty-vt` so clean installs work without manual setup
- Release workflow regenerates and commits `checksum-Ghostty.Terminal.Nif.exs` and `checksum-Ghostty.PTY.Nif.exs`
- zlint for Zig code
### Docs
- README examples are covered by tests
- Release/install flow documented in `AGENTS.md`
## 0.1.0 (2026-03-29)
Initial release.
### Terminal
- `start_link/1` with `:cols`, `:rows`, `:max_scrollback`, `:name`
- `write/2` — VT-encoded data
- `resize/3` — with text reflow
- `reset/1` — full terminal reset (RIS)
- `snapshot/2` — `:plain`, `:html`, `:vt` formats
- `scroll/2` — viewport scrolling
- `cursor/1` — cursor position
- `size/1` — terminal dimensions
### Build
- libghostty-vt C API via Zig NIFs (Zigler)
- Precompiled NIF binaries for Linux and macOS