Skip to content
Open
Show file tree
Hide file tree
Changes from 5 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
49 changes: 48 additions & 1 deletion build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -609,7 +609,6 @@ fn configureObj(b: *Build, opts: *BunBuildOptions, obj: *Compile) void {

obj.no_link_obj = opts.os != .windows and !opts.no_llvm;


if (opts.enable_asan and !enableFastBuild(b)) {
if (@hasField(Build.Module, "sanitize_address")) {
if (opts.enable_fuzzilli) {
Expand Down Expand Up @@ -800,6 +799,11 @@ fn addInternalImports(b: *Build, mod: *Module, opts: *BunBuildOptions) void {
});
}

// libghostty-vt: Terminal VT emulator library from Ghostty
// Provides terminal escape sequence parsing, state management, input encoding
// Source is cloned by CMake to vendor/ghostty
addGhosttyModule(b, mod);

// Finally, make it so all modules share the same import table.
propagateImports(mod) catch @panic("OOM");
}
Expand Down Expand Up @@ -832,6 +836,49 @@ fn validateGeneratedPath(path: []const u8) void {
}
}

/// Adds the ghostty-vt module for terminal emulation functionality.
/// Ghostty source is cloned to vendor/ghostty by CMake (see BuildGhosttyVt.cmake).
///
/// The ghostty-vt module provides:
/// - VT escape sequence parsing (CSI, OSC, DCS, etc.)
/// - Terminal state management (screen, cursor, colors)
/// - Input encoding for terminal applications
fn addGhosttyModule(b: *Build, mod: *Module) void {

// Create the ghostty-vt module from vendor/ghostty/src/lib_vt.zig
const ghostty_vt = b.createModule(.{
.root_source_file = b.path("vendor/ghostty/src/lib_vt.zig"),
});

// Add terminal_options - build configuration for the terminal module
ghostty_vt.addAnonymousImport("terminal_options", .{
.root_source_file = b.path("src/deps/ghostty/terminal_options.zig"),
});

// Add unicode_tables - stub tables for unicode property lookups
ghostty_vt.addAnonymousImport("unicode_tables", .{
.root_source_file = b.path("src/deps/ghostty/unicode_tables.zig"),
});

// Add symbols_tables - stub tables for symbol detection
ghostty_vt.addAnonymousImport("symbols_tables", .{
.root_source_file = b.path("src/deps/ghostty/symbols_tables.zig"),
});

// Add props module for Properties type used by unicode_tables
ghostty_vt.addAnonymousImport("props", .{
.root_source_file = b.path("vendor/ghostty/src/unicode/props.zig"),
});

// Add build_options for ghostty's SIMD code
ghostty_vt.addAnonymousImport("build_options", .{
.root_source_file = b.path("src/deps/ghostty/build_options.zig"),
});

// Export ghostty module to bun
mod.addImport("ghostty", ghostty_vt);
}

const WindowsShim = struct {
exe: *Compile,
dbg: *Compile,
Expand Down
1 change: 1 addition & 0 deletions cmake/targets/BuildBun.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ set(BUN_DEPENDENCIES
LibArchive # must be loaded after zlib
HdrHistogram # must be loaded after zlib
Zstd
GhosttyVt # libghostty-vt terminal emulator library
)

include(CloneZstd)
Expand Down
75 changes: 75 additions & 0 deletions cmake/targets/BuildGhosttyVt.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Build libghostty-vt - Terminal VT emulator library from Ghostty
# This clones the ghostty repository so Bun's build.zig can import it as a Zig module.
#
# libghostty-vt provides:
# - Terminal escape sequence parsing
# - Terminal state management (screen, cursor, scrollback)
# - Input event encoding (Kitty keyboard protocol)
# - OSC/DCS/CSI sequence handling
#
# Usage in Zig: @import("ghostty") gives access to the lib_vt.zig API

register_repository(
NAME
ghostty
REPOSITORY
ghostty-org/ghostty
TAG
v1.1.3
)

# utfcpp - header-only UTF-8 library for error handling in SIMD code
register_repository(
NAME
utfcpp
REPOSITORY
nemtrif/utfcpp
TAG
v4.0.5
)
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Verify utfcpp release information and check for CVE advisories
curl -s "https://api.github.com/repos/nemtrif/utfcpp/releases" | jq -r '.[] | "\(.tag_name): \(.published_at)"' | head -20

Repository: oven-sh/bun

Length of output: 630


Update ghostty and utfcpp to newer versions.

Ghostty v1.2.3 (released October 23, 2025) is available; the current pin to v1.1.3 is outdated. Ghostty v1.2.0 (September 15, 2025) introduced a security fix where Ghostty now unconditionally asks for permission prior to executing any script or executable, which is not present in v1.1.3.

For utfcpp, v4.0.8 (released September 2025) is the latest available; the current pin to v4.0.5 (released December 2023) is nearly two years old with multiple newer patch releases (v4.0.6, v4.0.7, v4.0.8) available.

🤖 Prompt for AI Agents
In cmake/targets/BuildGhosttyVt.cmake around lines 12 to 29 the repository TAG
pins are outdated; update the ghostty TAG from v1.1.3 to v1.2.3 and update the
utfcpp TAG from v4.0.5 to v4.0.8 to pick up the security and patch fixes, then
run a configure/build and tests to ensure compatibility after the version bumps.


# The ghostty source is cloned to ${VENDOR_PATH}/ghostty
# Bun's build.zig will reference it directly as a Zig module

# Build the SIMD acceleration library for ghostty
# This provides optimized UTF-8 decoding for terminal escape sequence parsing
set(GHOSTTY_SIMD_SRC ${VENDOR_PATH}/ghostty/src/simd/vt.cpp)

add_library(ghostty-simd STATIC ${GHOSTTY_SIMD_SRC})

target_include_directories(ghostty-simd PRIVATE
# Bun's compatibility headers (simdutf.h wrapper)
${CWD}/src/deps/ghostty
# Ghostty's own headers
${VENDOR_PATH}/ghostty/src
# Highway SIMD library (from Bun's vendor)
${BUILD_PATH}/highway
${VENDOR_PATH}/highway
# simdutf from webkit
${WEBKIT_INCLUDE_PATH}
${WEBKIT_INCLUDE_PATH}/wtf
# utfcpp for UTF-8 error handling
${VENDOR_PATH}/utfcpp/source
)

target_compile_definitions(ghostty-simd PRIVATE
# Highway configuration
HWY_STATIC_DEFINE
)

# Enable exceptions for this file only - utfcpp's replace_invalid uses them
set_source_files_properties(${GHOSTTY_SIMD_SRC} PROPERTIES
COMPILE_FLAGS "-fexceptions"
)

# Ensure dependencies are built first
add_dependencies(ghostty-simd clone-ghostty clone-utfcpp)
if(TARGET highway)
add_dependencies(ghostty-simd highway)
endif()

# Link ghostty-simd into bun
target_link_libraries(${bun} PRIVATE ghostty-simd)

# Link highway library
target_link_libraries(${bun} PRIVATE ${BUILD_PATH}/highway/libhwy.a)
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider linking against the highway target instead of hardcoded path.

Line 75 uses a hardcoded path to libhwy.a. If the highway target is available (checked on line 67), linking against the target would be more robust and portable.

Apply this diff to use target-based linking:

 # Link ghostty-simd into bun
 target_link_libraries(${bun} PRIVATE ghostty-simd)
 
-# Link highway library
-target_link_libraries(${bun} PRIVATE ${BUILD_PATH}/highway/libhwy.a)
+# Link highway library (if available as a target, use it; otherwise fall back to path)
+if(TARGET highway)
+  target_link_libraries(${bun} PRIVATE highway)
+else()
+  target_link_libraries(${bun} PRIVATE ${BUILD_PATH}/highway/libhwy.a)
+endif()
🤖 Prompt for AI Agents
In cmake/targets/BuildGhosttyVt.cmake around lines 65 to 75, replace the
hardcoded link to ${BUILD_PATH}/highway/libhwy.a with target-based linking when
the highway target exists: modify the target_link_libraries call to link PRIVATE
highway if TARGET highway is true (e.g. use if(TARGET highway)
target_link_libraries(${bun} PRIVATE highway) else target_link_libraries(${bun}
PRIVATE ${BUILD_PATH}/highway/libhwy.a) endif()), preserving the existing
add_dependencies so the highway target is built first and falling back to the
file path only when the target is not available.

70 changes: 70 additions & 0 deletions src/bun.js/api/Terminal.classes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,76 @@ export default [
getter: "getControlFlags",
setter: "setControlFlags",
},

// ----- Virtual Terminal (ghostty-vt) API -----
// These methods provide terminal emulation: parsing escape sequences,
// maintaining screen state (cells, cursor, colors), and rendering.

// Feed data to the virtual terminal parser
// This processes escape sequences and updates the screen state
feed: {
fn: "feed",
length: 1,
},

// Get a specific cell from the screen buffer at (x, y)
// Returns { char, wide, styled } or null if out of bounds
at: {
fn: "at",
length: 2,
},

// Get a line of text relative to the bottom of the screen
// line(0) = bottom line, line(1) = one above bottom, etc.
line: {
fn: "line",
length: 1,
},

// Get the full screen content as text (getter)
text: {
getter: "getText",
},

// Get cursor position { x, y, visible, style }
cursor: {
getter: "getCursor",
},

// Get current screen dimensions
cols: {
getter: "getCols",
},
rows: {
getter: "getRows",
},

// Get terminal title (set via OSC sequences)
title: {
getter: "getTitle",
},

// Check if terminal is in alternate screen mode
alternateScreen: {
getter: "getAlternateScreen",
},

// Get scrollback buffer size
scrollbackLines: {
getter: "getScrollbackLines",
},

// Clear the screen
clear: {
fn: "clearScreen",
length: 0,
},

// Reset terminal to initial state
reset: {
fn: "resetTerminal",
length: 0,
},
},
}),
];
Loading