Skip to content

Conversation

@remorses
Copy link
Contributor

@remorses remorses commented Dec 23, 2025

Stacked on #439 (zig 0.15 upgrade).

Adds terminal rendering support using ghostty-vt:

  • StatelessTerminalRenderable - fast renderer for first few lines of output (renders in ~ms, for opencode bash previews)

The terminal output is renderd line by line instead of using character cells. This should make it pretty fast even for super long ANSI outputs if they don't use many colors. Each line will simply be a line of text in opentui.

Includes VTerm FFI bindings and registration in React, Solid, and Vue.

Here is how bash outputs looks like in opencode using these terminal renderables (only stateless for now):

Screen.Recording.2025-12-24.at.13.15.29.mov

@remorses
Copy link
Contributor Author

Here is the multiplexing demo running 4 focusable opencode processes with support for mouse, scrolling and keys forwarding

Screen.Recording.2025-12-24.at.12.59.23.mov

- update build.zig for zig 0.15 API (createModule, standardOptimizeOption)
- add ghostty-vt dependency for terminal emulation
- use -gnu suffix for linux targets to fix PIC linker errors
- update CI workflows to use zig 0.15.2
- update all zig source files for 0.15 compatibility
…inux

- Update React and Solid workflows to use Zig 0.15.2 (required by ghostty-vt)
- Skip macOS targets when building on non-macOS hosts (ghostty's apple-sdk
  doesn't support cross-compilation from Linux)
- Update TypeScript build script to handle missing platform builds gracefully
- Add mitchellh/zig-build-macos-sdk dependency (official SDK used by Ghostty)
- Configure SDK paths on module before loading ghostty dependencies
- Update to latest ghostty commit
- Remove skip logic for macOS targets since SDK is now provided
Native binaries for all platforms are built in the release workflow
(build-native.yml on macOS). PR checks only need to build the TypeScript
library and run tests.
macOS can cross-compile to all platforms (Linux, Windows, macOS).
This avoids the complexity of setting up macOS SDK on Linux runners.
- By default, zig build now only builds for the native platform
- Add -Dall option to zig build for building all platforms
- Add --all flag to TypeScript build script
- Update release workflow to use --all for cross-compilation

This allows Linux users to run `bun run build` without failing on macOS targets.
- ArrayList.init(allocator) → ArrayListUnmanaged with allocator per-method
- std.fmt.formatIntBuf → std.fmt.bufPrint
- std.fmt.formatInt → writer.print
- std.zon.parse.Status removed, use fromSlice directly
- Add vterm.zig with ghostty-vt integration for terminal emulation
- Add VTerm FFI functions to lib.zig and zig.ts
- Add StatelessTerminalRenderable and TerminalRenderable classes
- Fix renderer.zig to skip stdout writes in testing mode (fixes hanging tests)
- Fix circular dependency by moving VTerm types to lib/vterm-ffi.ts
mitchellh added a commit to ghostty-org/ghostty that referenced this pull request Jan 7, 2026
Adds `-fPIC` flag for musl targets when building highway and simdutf C++
dependencies, matching the existing freebsd behavior.

## What is PIC?

Position Independent Code (PIC) generates machine code using relative
addresses instead of absolute ones, allowing the code to be loaded at
any memory address. This is required when linking static libraries into
shared libraries (.so files).

## Why both freebsd and musl need it

Both freebsd and musl use strict relocation policies that reject non-PIC
code in shared libraries. Without `-fPIC`, linking fails with errors
like:

```
relocation R_X86_64_PC32 cannot be used against symbol '__cxa_begin_catch'
```

glibc is more permissive and handles these relocations at runtime, which
is why linux-gnu targets work without this flag.

## Context

This enables cross-compiling ghostty-vt to musl/Alpine Linux targets.
Discovered while integrating ghostty-vt into opentui:
anomalyco/opentui#440

---

This PR was created with help from Claude Opus 4.5.
matrix:
include:
- os: ubuntu-latest
name: linux-x64
Copy link
Contributor Author

@remorses remorses Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added more OS machines in SO that would run the tests. Currently tests are failing for other OS other than linux but the binaries build correctly. I have another branch that fixes the flaky tests in other OSes

@remorses remorses marked this pull request as ready for review January 8, 2026 11:30
Copilot AI review requested due to automatic review settings January 8, 2026 11:30
@remorses remorses requested a review from Hona as a code owner January 8, 2026 11:30
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds terminal rendering support to OpenTUI using the ghostty-vt library. It introduces two new renderables: TerminalRenderable for interactive stateful terminal sessions and StatelessTerminalRenderable for fast rendering of static ANSI output (useful for previews). The implementation includes comprehensive FFI bindings between TypeScript and Zig, integration with React/Solid/Vue frameworks, and support for both glibc and musl Linux targets.

Key changes:

  • Adds ghostty-vt dependency for terminal emulation with VT100/ANSI escape sequence parsing
  • Implements FFI layer for terminal creation, feeding, resizing, and output retrieval
  • Adds terminal renderables with mouse support and stream-based I/O
  • Extends build system to support Linux musl targets (Alpine/Docker)

Reviewed changes

Copilot reviewed 27 out of 28 changed files in this pull request and generated 17 comments.

Show a summary per file
File Description
packages/core/src/zig/vterm.zig New Zig module implementing terminal emulation FFI, JSON serialization, and terminal state management
packages/core/src/zig/lib.zig Exports VTerm FFI functions and adds log suppression for ghostty-vt
packages/core/src/zig.ts TypeScript FFI bindings and wrapper methods for VTerm functions with buffer management
packages/core/src/renderables/Terminal.ts Two terminal renderables with stream I/O, mouse support, and text rendering
packages/core/src/renderables/Terminal.test.ts Comprehensive test suite with stress tests for large inputs and concurrent operations
packages/core/src/lib/vterm-ffi.ts Helper functions to convert VTerm data to StyledText format
packages/react/src/components/index.ts Registers terminal and stateless-terminal components for React
packages/solid/src/elements/index.ts Registers terminal and stateless_terminal components for Solid
packages/vue/src/elements.ts Registers terminalRenderable and statelessTerminalRenderable for Vue
packages/core/src/zig/build.zig Adds ghostty dependency and musl Linux target support
packages/core/src/zig/build.zig.zon Declares ghostty-vt dependency pinned to specific commit
packages/core/scripts/build.ts Updates build script to handle musl variants
.github/workflows/build-core.yml Restructures CI to build native libraries once and test on multiple platforms
packages/solid/examples/components/terminal-grid-demo.tsx Demo showing 2x2 grid of interactive terminals with PTY spawning
packages/core/src/examples/terminal-simple-demo.ts Simple demo for stateless terminal with ANSI sample output
packages/core/src/examples/terminal-interactive-demo.ts Interactive demo with PTY-backed terminal and button controls

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@remorses
Copy link
Contributor Author

Deleted the interactive TerminalRenderable to make the PR easier to review. Only StatelessTerminalRenderable remains now, which is what opencode would use to render bash outputs with colors.

remorses

This comment was marked as outdated.

@remorses remorses changed the title Add Terminal and StatelessTerminal renderables Add StatelessTerminal renderable. Render ANSI as opentui styled text Jan 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant