Skip to content
Merged
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
64 changes: 64 additions & 0 deletions .github/actions/setup-zig/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
name: 'Setup Zig'
description: 'Install Zig compiler'
inputs:
version:
description: 'Zig version to install'
required: true
default: '0.15.2'
runs:
using: 'composite'
steps:
- name: Cache Zig
uses: actions/cache@v4
id: cache-zig
with:
path: |
~/zig
key: zig-${{ runner.os }}-${{ inputs.version }}

- name: Download and install Zig
if: steps.cache-zig.outputs.cache-hit != 'true'
shell: bash
run: |
set -e
VERSION="${{ inputs.version }}"

# Determine platform
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
PLATFORM="linux"
ARCH="x86_64"
elif [[ "$OSTYPE" == "darwin"* ]]; then
PLATFORM="macos"
if [[ "$(uname -m)" == "arm64" ]]; then
ARCH="aarch64"
else
ARCH="x86_64"
fi
else
echo "Unsupported OS: $OSTYPE"
exit 1
fi

# Download from ziglang.org
# Note: Format changed in 0.14.1+ from zig-linux-x86_64 to zig-x86_64-linux
TARBALL="zig-${ARCH}-${PLATFORM}-${VERSION}.tar.xz"
URL="https://ziglang.org/download/${VERSION}/${TARBALL}"

echo "Downloading Zig ${VERSION} for ${PLATFORM}-${ARCH}..."
curl --retry 3 --retry-delay 5 -L -o "/tmp/${TARBALL}" "${URL}"

# Extract to home directory
mkdir -p ~/zig
tar -xf "/tmp/${TARBALL}" -C ~/zig --strip-components=1

echo "Zig ${VERSION} installed to ~/zig"

- name: Add Zig to PATH
shell: bash
run: |
echo "$HOME/zig" >> $GITHUB_PATH

- name: Verify Zig installation
shell: bash
run: |
zig version
27 changes: 27 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,20 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive

- uses: oven-sh/setup-bun@v1
with:
bun-version: latest

- uses: ./.github/actions/setup-zig
with:
version: 0.15.2

- name: Build WASM
run: ./scripts/build-wasm.sh

- name: Install dependencies
run: bun install

Expand All @@ -76,11 +85,29 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive

- uses: oven-sh/setup-bun@v1
with:
bun-version: latest

- uses: ./.github/actions/setup-zig
with:
version: 0.15.2

- name: Build WASM
run: ./scripts/build-wasm.sh

- name: Check WASM size
run: |
SIZE=$(stat -c%s ghostty-vt.wasm)
echo "WASM size: $SIZE bytes"
if [ "$SIZE" -gt 524288 ]; then
echo "❌ Error: WASM exceeds 512 KB limit"
exit 1
fi

- name: Install dependencies
run: bun install

Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@ dist/
.DS_Store
*.log
.vite/

# WASM build output (built locally and in CI)
ghostty-vt.wasm
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "ghostty"]
path = ghostty
url = https://github.com/ghostty-org/ghostty.git
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ coverage/
.git/
.vite/
bun.lock
ghostty/
14 changes: 12 additions & 2 deletions INSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ npm install github:coder/ghostty-web
bun add github:coder/ghostty-web
```

**Note:** When installing from git, the package automatically builds itself via a `postinstall` script. This requires Bun to be installed and may take a few seconds during installation.
**Note:** Git installs require manually building the package first. See [Local Development](#local-development) for build instructions.

## Basic Usage

Expand Down Expand Up @@ -91,7 +91,17 @@ ws.onmessage = (event) => {

## WASM File Handling

The library requires the `ghostty-vt.wasm` file at runtime. Most bundlers handle this automatically.
The library requires the `ghostty-vt.wasm` file at runtime. When installing from npm, the WASM is pre-built and included in the package.

### Local Development

After cloning:

```bash
./scripts/build-wasm.sh
```

The script will automatically initialize the submodule if needed. The WASM file is generated locally and gitignored.

### Vite (Recommended)

Expand Down
54 changes: 35 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ Or install from GitHub:
npm install github:coder/ghostty-web
```

**Note:** Git installs will auto-build during `postinstall` (requires Bun).

## Quick Start

```typescript
Expand Down Expand Up @@ -218,30 +216,48 @@ WebSocket Server (server/file-browser-server.ts)
└── ghostty-vt.wasm - Ghostty VT100 parser (122 KB)
```

## Building
## Building WASM

The WASM binary is built from source, not committed to the repo.

**Requirements:**

Requires:
- Zig 0.15.2+
- Git submodules initialized

- **Zig 0.15.2+** (to build WASM)
- **Ghostty source** (from GitHub)
**Build:**

```bash
# Install Zig 0.15.2
curl -L -o zig-0.15.2.tar.xz \
https://ziglang.org/download/0.15.2/zig-x86_64-linux-0.15.2.tar.xz
tar xf zig-0.15.2.tar.xz
sudo cp -r zig-x86_64-linux-0.15.2 /usr/local/zig-0.15.2
sudo ln -sf /usr/local/zig-0.15.2/zig /usr/local/bin/zig

# Clone Ghostty
git clone https://github.com/ghostty-org/ghostty.git
cd ghostty
# Initialize submodule (first time only)
git submodule update --init --recursive

# Build WASM
./scripts/build-wasm.sh
# or
bun run build:wasm
```

# Build WASM (~20 seconds)
zig build lib-vt -Dtarget=wasm32-freestanding -Doptimize=ReleaseSmall
# Output: zig-out/bin/ghostty-vt.wasm (122 KB)
**What it does:**

1. Initializes `ghostty/` submodule (ghostty-org/ghostty)
2. Applies patches from `patches/ghostty-wasm-api.patch`
3. Builds WASM with Zig (takes ~20 seconds)
4. Outputs `ghostty-vt.wasm` (404 KB)
5. Reverts patch to keep submodule clean

**Updating Ghostty:**

```bash
cd ghostty
git fetch origin
git checkout <commit-or-tag>
cd ..
./scripts/build-wasm.sh
# Test, then commit the updated submodule pointer
```

**CI:** The WASM is built as part of the `test` and `build` jobs.

## Testing

Run the test suite:
Expand Down
1 change: 1 addition & 0 deletions ghostty
Submodule ghostty added at 0f64b9
Binary file removed ghostty-vt.wasm
Binary file not shown.
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@
},
"scripts": {
"dev": "vite --port 8000",
"build": "bun run clean && bun run build:lib && bun run build:wasm-copy",
"build": "bun run clean && bun run build:wasm && bun run build:lib && bun run build:wasm-copy",
"build:wasm": "./scripts/build-wasm.sh",
"build:lib": "vite build",
"build:wasm-copy": "cp ghostty-vt.wasm dist/",
"clean": "rm -rf dist",
Expand All @@ -57,8 +58,7 @@
"fmt:fix": "prettier --write .",
"lint": "biome check .",
"lint:fix": "biome check --write .",
"prepublishOnly": "bun run test && bun run build",
"postinstall": "[ -d dist ] || bun run build"
"prepublishOnly": "bun run test && bun run build"
},
"devDependencies": {
"@biomejs/biome": "^1.9.4",
Expand Down
Loading