Skip to content

Bump libghostty-spm 1.5.1, MSDisplayLink 2.2.0, and libghostty-vt - #10

Open
rudironsoni wants to merge 4 commits into
arcboxlabs:masterfrom
rudironsoni:chore/bump-dependencies
Open

Bump libghostty-spm 1.5.1, MSDisplayLink 2.2.0, and libghostty-vt#10
rudironsoni wants to merge 4 commits into
arcboxlabs:masterfrom
rudironsoni:chore/bump-dependencies

Conversation

@rudironsoni

Copy link
Copy Markdown

Closes #6.

Bumps vendor pins past the July drift issue, plus Expo 57.0.19 and the JS/CI toolchain.

What

  • libghostty-spm 1.3.1 → 1.5.1 (XCFramework upstream.1.3.1-2, Ghostty v1.3.1)
  • MSDisplayLink 2.1.0 → 2.2.0
  • libghostty-vt b094737 → ghostty 3c1ef5b (Zig 0.16.0, Nerd Fonts v3.5.1)
  • Android JNI matches the new vt C API (ghostty_terminal_new cols/rows, mode via GHOSTTY_TERMINAL_DATA_MODE, colors via GHOSTTY_RENDER_STATE_DATA_COLORS)
  • Expo 57.0.19, react-native 0.86.3 (Expo 57's recommended pin; 0.87.1 does not compile against this SDK)
  • ESLint 10.9.1 / typescript-eslint 8.69.0. tsc is TypeScript 7.0.2 (@typescript/native); the typescript package is @typescript/typescript6 because TypeScript 7 still has no compiler API for ESLint

vendor-watch now compares libghostty-spm package version tags (X.Y.Z), not storage.* tags.

Android tarball host

vendor-manifest.json currently points at a public tarball on the contributor fork:

https://github.com/rudironsoni/expo-libghostty/releases/tag/storage.libghostty-vt.3c1ef5b32fc5.r1

Please re-run build-android-libs.yml on this repo for 3c1ef5b32fc5ea6b93d28493fabf193f595139cf and re-pin the URL + sha256 before merge if you do not want the package to download from the fork.

How to test

pnpm install
pnpm lint
pnpm exec tsc --noEmit
pnpm test

Android (CI-equivalent):

export ANDROID_HOME="${ANDROID_HOME:-$HOME/Library/Android/sdk}"
pnpm --dir example exec expo prebuild --platform android --no-install
cd example/android
./gradlew :expo-libghostty:testDebugUnitTest
./gradlew :app:assembleRelease \
  -Pandroid.enableMinifyInReleaseBuilds=true \
  -Pandroid.enableShrinkResourcesInReleaseBuilds=true

iOS (CI-equivalent):

pnpm --dir example exec expo prebuild --platform ios --no-install
cd example/ios
pod install
xcodebuild -workspace expolibghosttyexample.xcworkspace \
  -scheme expolibghosttyexample -configuration Debug \
  -sdk iphonesimulator -destination 'generic/platform=iOS Simulator' \
  CODE_SIGNING_ALLOWED=NO build

Local verification

  • pnpm lint, pnpm exec tsc --noEmit, pnpm test pass
  • Android unit tests + R8 assembleRelease BUILD SUCCESSFUL
  • iOS simulator xcodebuild Build Succeeded
  • react-native 0.87.1 was tried and reverted: Expo 57's ExpoReactNativeFactory does not compile against it, and AGP wants Gradle 9.4.1 while Expo 57 prebuild still writes 9.3.1

Sync libghostty-spm 1.5.1, MSDisplayLink 2.2.0, and
libghostty-vt to ghostty 3c1ef5b. JNI follows the new
C ABI. Expo stays on SDK 57.0.19 with react-native
0.86.3; ESLint 10 runs against TypeScript 7's tsc.
Copilot AI lite review requested due to automatic review settings September 2, 2026 08:51
@greptile-apps

greptile-apps Bot commented Sep 2, 2026

Copy link
Copy Markdown

Greptile Summary

The PR updates the vendored Ghostty components, Android C API integration, Expo/React Native stack, and JS/CI toolchain, while adding an iOS policy that sends OSC 52 writes through host approval.

  • Updates libghostty-spm, libghostty-vt, MSDisplayLink, Expo, React Native, TypeScript, ESLint, and associated lockfiles and CI.
  • Synchronizes the Android JNI bridge and iOS vendored terminal sources with the new native APIs.
  • Adds richer iOS clipboard, paste, input, and file-handling behavior, but the new file-path escaping permits line terminators to reach a live shell prompt.

Confidence Score: 3/5

The PR is not safe to merge until pasted and dropped file paths escape line terminators before reaching a live shell prompt.

The new shell-path escaping copies CR and LF unchanged, and the file URL drop path sends that result directly to the terminal, allowing a newline-bearing filename to introduce a separate shell command.

Files Needing Attention: ios/vendor/GhosttyTerminal/Platform/Shared/TerminalShellEscape.swift, ios/vendor/GhosttyTerminal/Platform/Shared/TerminalPasteboardContent.swift, ios/vendor/GhosttyTerminal/Platform/UIKit/UITerminalView+Drop.swift

Security Review

The new iOS file-path paste/drop handling does not escape carriage returns or newlines. A newline-bearing filename can therefore inject an additional shell command when its path is inserted into a terminal prompt.

Important Files Changed

Filename Overview
ios/ExpoLibghosttyView.swift Configures clipboard-write as ask and denies program-originated clipboard requests while allowing user-started paste.
ios/vendor/GhosttyTerminal/Controller/TerminalController+Callbacks.swift Adds length-bounded clipboard payload handling and routes confirmed OSC 52 writes through the host delegate.
ios/vendor/GhosttyTerminal/Platform/Shared/TerminalShellEscape.swift Adds shell escaping for pasted paths but omits CR and LF, allowing line terminators to alter shell command structure.
android/src/main/cpp/ghostty_jni.cpp Adapts terminal creation, mode lookup, and render-state color access to the updated libghostty-vt C API.
vendor-manifest.json Re-pins the native vendor sources and checksummed binary artifacts, including the documented contributor-fork Android tarball.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  File[Clipboard or dropped file URL] --> Path[Extract pathname]
  Path --> Escape[TerminalShellEscape.escape]
  Escape --> Input[Send text to terminal surface]
  Input --> Shell[Live shell prompt]
  Escape -. CR/LF remain unchanged .-> Shell
Loading

Reviews (4): Last reviewed commit: "chore(ios): bump libghostty-spm to 1.5.2..." | Re-trigger Greptile

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

It introduces at least one build-breaking Swift callsite (TerminalPasteboardContent.text()) and confirmed logic bugs in new routing/frame-rate code that should be fixed before merge.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR updates the repo’s pinned vendor dependencies (libghostty-spm, MSDisplayLink, libghostty-vt) and aligns the iOS/Android wrapper layers + JS/CI toolchain with the newer upstream APIs and behaviors (notably display link pacing/frame-rate control, clipboard gating, resize throttling, and new input/key paths).

Changes:

  • Bump vendor pins (SPM/CocoaPods + Android tarball) and vendor drift detection logic (vendor-watch).
  • Update iOS terminal wrapper code (MSDisplayLink frame-rate ranges, display-link driven ticking, focus/visibility handling, clipboard confirmation, paste/drop staging, shell integration resources).
  • Update Android JNI bindings to match the new libghostty-vt C API + refresh Expo/React Native + lint/tooling + CI actions.
File summaries
File Description
vendor-manifest.json Updates pinned vendor tags/commits and artifact URLs + checksums.
scripts/vendor-watch.sh Changes drift detection to compare numeric package tags instead of storage.* release tags.
README.md Updates Android toolchain note (Zig version).
pnpm-workspace.yaml Updates pnpm minimum-release-age exclusions for Expo 57.x packages.
package.json Bumps Expo/RN/tooling dependencies; introduces TS 7 via @typescript/native and TS6 compiler API shim for ESLint.
ios/vendor/README.md Updates vendored iOS component tag table.
ios/vendor/MSDisplayLink/DisplayLinkFrameRateRange.swift Adds platform-neutral frame-rate range type and union logic.
ios/vendor/MSDisplayLink/DisplayLinkDriver+Helper.swift Adds helper methods to resolve and re-apply frame-rate preferences across drivers.
ios/vendor/MSDisplayLink/DisplayLinkDriver+CA.swift Applies preferred frame-rate range to CADisplayLink (incl. iOS 15+ range API).
ios/vendor/MSDisplayLink/DisplayLinkDriver.swift Adds per-driver preferred frame-rate range propagation to the shared helper.
ios/vendor/MSDisplayLink/DisplayLink+SwiftUI.swift Adds SwiftUI modifier support for passing a preferred frame-rate range.
ios/vendor/MSDisplayLink/DisplayLink.swift Exposes preferredFrameRateRange and makes DisplayLink/delegation open.
ios/vendor/GhosttyTerminal/View/TerminalViewRepresentable@UIKit.swift Uses host-provided platform view factory and updates focus bridging hooks.
ios/vendor/GhosttyTerminal/View/TerminalViewRepresentable@AppKit.swift Uses host-provided platform view factory and updates focus bridging hooks + guard order.
ios/vendor/GhosttyTerminal/View/TerminalViewRepresentable.swift Adds stored isSurfaceVisible, prevents re-stamping visibility, and syncs accessory items.
ios/vendor/GhosttyTerminal/Surface/TerminalSurfaceViewDelegate.swift Adds clipboard confirmation and scrollbar delegate types.
ios/vendor/GhosttyTerminal/Surface/TerminalSurfaceView.swift Forwards isSurfaceVisible into the representable.
ios/vendor/GhosttyTerminal/Surface/TerminalSurfaceOptions.swift Adds command, waitAfterCommand, and resize-throttle policy; updates equivalence rules.
ios/vendor/GhosttyTerminal/Surface/TerminalSurfaceCoordinator.swift Reworks tick pacing around a shared display link, adds resize throttling and visibility/attach safeguards.
ios/vendor/GhosttyTerminal/Surface/TerminalSurface.swift Makes mouse + selection helpers public and removes isMouseCaptured.
ios/vendor/GhosttyTerminal/Surface/TerminalKeyPress.swift Adds programmatic keypress API and convenience TerminalSurface.sendKey helpers.
ios/vendor/GhosttyTerminal/Surface/TerminalKey.swift Adds a complete key enum mirroring libghostty key definitions + US layout mapping.
ios/vendor/GhosttyTerminal/State/TerminalViewState+Delegate.swift Defers @Published mutations to next runloop turn; adds clipboard confirmation + scrollbar updates.
ios/vendor/GhosttyTerminal/State/TerminalViewState.swift Adds attached view hooks, view factory, focus requests, visibility control, accessory items, and key/paste API cleanup.
ios/vendor/GhosttyTerminal/Resources/Ghostty/shell-integration/zsh/ghostty-integration Adds new zsh shell integration script.
ios/vendor/GhosttyTerminal/Resources/Ghostty/shell-integration/zsh/.zshenv Adds zsh bootstrap that defers loading until after user .zshrc.
ios/vendor/GhosttyTerminal/Resources/Ghostty/shell-integration/bash/LICENSE-bash-preexec.md Adds license for vendored bash-preexec.
ios/vendor/GhosttyTerminal/Resources/Ghostty/shell-integration/bash/ghostty.bash Adds bash shell integration script with injected startup replay support.
ios/vendor/GhosttyTerminal/Resources/Ghostty/shell-integration/bash/bash-preexec.sh Vendors bash-preexec with Ghostty-specific patch to avoid HISTCONTROL modification.
ios/vendor/GhosttyTerminal/Platform/UIKit/UITerminalView+UITextInput.swift Improves software keyboard routing (semantic enter, IME commits), inline prediction disabling, and delegate storage.
ios/vendor/GhosttyTerminal/Platform/UIKit/UITerminalView+Snapshot.swift Adds UIKit snapshot helper using drawHierarchy.
ios/vendor/GhosttyTerminal/Platform/UIKit/UITerminalView+PublicSticky.swift Broadens UIKit guards and fixes macCatalyst gating.
ios/vendor/GhosttyTerminal/Platform/UIKit/UITerminalView+PublicInput.swift Adds public focus/paste/sendKey helpers for UIKit views.
ios/vendor/GhosttyTerminal/Platform/UIKit/UITerminalView+PinchZoom.swift Refactors pinch zoom state and adds explicit min/max font sizes.
ios/vendor/GhosttyTerminal/Platform/UIKit/UITerminalView+Lifecycle.swift Hardens attach behavior, adds scene activation support, adjusts sublayer sizing under resize throttling, and focus bridge hooks.
ios/vendor/GhosttyTerminal/Platform/UIKit/UITerminalView+InputAccessory.swift Improves paste behavior + key event synthesis and guards for visionOS/catalyst behavior.
ios/vendor/GhosttyTerminal/Platform/UIKit/UITerminalView+Drop.swift Adds drag-and-drop support for files/URLs/text on UIKit/Catalyst.
ios/vendor/GhosttyTerminal/Platform/UIKit/UITerminalView.swift Refactors internal state storage, adds edit-menu interaction, and exposes setSurfaceVisible.
ios/vendor/GhosttyTerminal/Platform/UIKit/TerminalTextPosition.swift Removes unused start/end position helpers.
ios/vendor/GhosttyTerminal/Platform/UIKit/TerminalTextInputHandler@UIKit.swift Routes typed text through key events to avoid bracketed-paste semantics for normal typing.
ios/vendor/GhosttyTerminal/Platform/UIKit/TerminalStickyModifierState.swift Broadens UIKit guards and fixes macCatalyst gating.
ios/vendor/GhosttyTerminal/Platform/UIKit/TerminalInputBarKey.swift Adds metadata (titles/symbols) for accessory items for host UIs.
ios/vendor/GhosttyTerminal/Platform/UIKit/TerminalInputAccessoryView.swift Uses item-provided titles/symbols and adds visionOS blur fallback logic.
ios/vendor/GhosttyTerminal/Platform/UIKit/TerminalInputAccessoryStyle.swift Broadens UIKit guards and fixes macCatalyst gating.
ios/vendor/GhosttyTerminal/Platform/Shared/TerminalShellEscape.swift Adds POSIX shell escaping utility for pasted/staged paths.
ios/vendor/GhosttyTerminal/Platform/Shared/TerminalPasteboardContent.swift Adds pasteboard readers matching Ghostty behavior (URLs first, file URLs escaped).
ios/vendor/GhosttyTerminal/Platform/Shared/TerminalMainActor.swift Adds “next turn” main-queue helper to avoid publishing during SwiftUI updates.
ios/vendor/GhosttyTerminal/Platform/Shared/TerminalInputText.swift Adds software key commit router enums/utilities.
ios/vendor/GhosttyTerminal/Platform/Shared/TerminalIMEComposition.swift Adds platform-neutral IME routing logic for hardware keys.
ios/vendor/GhosttyTerminal/Platform/Shared/TerminalHardwareKeyRouter.swift Removes direct-raw-byte side channel; routes all keys through libghostty key path.
ios/vendor/GhosttyTerminal/Platform/Shared/TerminalFileStaging.swift Adds staging for pasted/dropped data into files and returns escaped paths.
ios/vendor/GhosttyTerminal/Platform/PlatformSupport.swift Adds a single compile-time platform assertion (UIKit or AppKit required).
ios/vendor/GhosttyTerminal/Platform/AppKit/TerminalTextInputHandler@AppKit.swift Normalizes platform guard ordering.
ios/vendor/GhosttyTerminal/Platform/AppKit/TerminalKeyEventHandler@AppKit.swift Removes direct-input bypass; refactors key echo state access.
ios/vendor/GhosttyTerminal/Platform/AppKit/KeyboardLayout.swift Normalizes platform guard ordering.
ios/vendor/GhosttyTerminal/Platform/AppKit/AppTerminalView+Snapshot.swift Adds AppKit snapshot helper using cacheDisplay.
ios/vendor/GhosttyTerminal/Platform/AppKit/AppTerminalView+PublicInput.swift Adds public focus/paste/sendKey helpers and deprecates old sendText naming.
ios/vendor/GhosttyTerminal/Platform/AppKit/AppTerminalView+NSTextInputClient.swift Normalizes platform guard ordering.
ios/vendor/GhosttyTerminal/Platform/AppKit/AppTerminalView+Lifecycle.swift Adds focus-bridge struct and pending-focus replay scheduling.
ios/vendor/GhosttyTerminal/Platform/AppKit/AppTerminalView+Input.swift Refactors key-echo/pointer state into structs.
ios/vendor/GhosttyTerminal/Platform/AppKit/AppTerminalView.swift Refactors internal state and adds live resize-throttle setter.
ios/vendor/GhosttyTerminal/Metrics/TerminalScrollModifiers.swift Normalizes AppKit guard ordering.
ios/vendor/GhosttyTerminal/Metrics/TerminalInputModifiers.swift Adds Hashable conformance to modifier OptionSet.
ios/vendor/GhosttyTerminal/InMemory/TerminalCallbackBridge.swift Adds scrollbar action forwarding and clipboard confirmation bridge.
ios/vendor/GhosttyTerminal/InMemory/InMemoryTerminalSurfaceAccess.swift Buffers output while detached and flushes on attach (bounded).
ios/vendor/GhosttyTerminal/InMemory/InMemoryTerminalSession.swift Adds optional suppression of pixel-only resizes; documents/uses buffered output semantics.
ios/vendor/GhosttyTerminal/Debug/TerminalDebugLog.swift Removes debugSummary for deleted TerminalHardwareKeyDelivery type.
ios/vendor/GhosttyTerminal/Controller/TerminalController+Surface.swift Wires new surface config fields (command, wait_after_command).
ios/vendor/GhosttyTerminal/Controller/TerminalController+Callbacks.swift Updates clipboard read/write semantics and introduces confirmation flows.
ios/vendor/GhosttyTerminal/Controller/TerminalController.swift Adds multi-surface wakeup observers and configures runtime resources env before init.
ios/vendor/GhosttyTerminal/Configuration/GhosttyRuntimeResources.swift Adds resource bundle lookup + GHOSTTY_RESOURCES_DIR environment configuration.
ios/MSDisplayLink.podspec Bumps MSDisplayLink CocoaPods version.
ios/GhosttyTerminalBundle+CocoaPods.swift Adds CocoaPods Bundle.module shim for GhosttyTerminal resource bundle.
ios/GhosttyTerminal.podspec Bumps GhosttyTerminal version and bundles Ghostty + terminfo resources for CocoaPods.
ios/GhosttyKit.podspec Bumps GhosttyKit CocoaPods version.
ios/ExpoLibghostty.podspec Excludes the CocoaPods Bundle.module shim from the parent pod.
example/package.json Updates example app Expo/RN and dev tooling versions.
eslint.config.cjs Adds React version pin to avoid ESLint 10 incompatibility in react plugin detect logic.
CHANGELOG.md Documents dependency bumps and related behavioral changes.
android/src/main/cpp/ghostty_jni.cpp Updates JNI usage for new ghostty terminal/render-state APIs and mode/color queries.
.github/workflows/ci.yml Updates setup actions to v6 and disables new proprietary cache component for gradle action.
.github/workflows/build-android-libs.yml Updates defaults and toolchain env for new ghostty commit, Zig, and Nerd Fonts.
Review details
  • Files reviewed: 16/87 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread vendor-manifest.json
Comment on lines +18 to +19
"url": "https://github.com/rudironsoni/expo-libghostty/releases/download/storage.libghostty-vt.3c1ef5b32fc5.r1/libghostty-vt-android-3c1ef5b32fc5-r1.tar.gz",
"sha256": "39ae5ed0eb0b0330a583045c98ed5cc0dc5adff0b0d7d87a884bfc0ef995fcea"

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Cannot re-pin this from the fork. gh workflow run build-android-libs.yml on arcboxlabs/expo-libghostty returns 403 (needs admin).

The tarball is still checksum-pinned at:

https://github.com/rudironsoni/expo-libghostty/releases/tag/storage.libghostty-vt.3c1ef5b32fc5.r1

sha256 39ae5ed0eb0b0330a583045c98ed5cc0dc5adff0b0d7d87a884bfc0ef995fcea

A maintainer with write on this repo needs to run build-android-libs.yml for 3c1ef5b32fc5ea6b93d28493fabf193f595139cf and update vendor-manifest.json. Leaving this thread open until that lands.

Set clipboard-write = ask so program writes go through host
confirmation. Deny OSC 52 read/write; allow user paste.
Copilot AI review requested due to automatic review settings September 2, 2026 09:36

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔵 Needs a closer look

It introduces a compile-breaking TerminalPasteboardContent.text() call mismatch and still pins the Android vendor tarball to a contributor fork URL, which should be repinned before merge.

Review details

Suppressed comments (1)

vendor-manifest.json:20

  • The pinned Android libghostty-vt tarball is currently hosted on a contributor fork (rudironsoni/expo-libghostty). This is a supply-chain risk and also makes the build depend on a third-party repo's retention policies; per the PR description, it should be rebuilt/uploaded in this repo and url+sha256 repinned before merge.
  • Files reviewed: 17/88 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Call TerminalPasteboardContent.text(from: .general) instead of
the defaulted text() form Copilot flagged as a mismatch.
Copilot AI review requested due to automatic review settings September 2, 2026 09:55
@rudironsoni

Copy link
Copy Markdown
Author

Addressed this Copilot review:

TerminalPasteboardContent.text() — the no-arg call was text(from: .general) via a default argument and already compiled (xcodebuild Build Succeeded). Call sites now pass .general explicitly.

Fork tarball — still blocked. We cannot dispatch build-android-libs.yml on arcboxlabs/expo-libghostty (403). A maintainer has to rebuild and re-pin. Thread: #10 (comment)

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Sync vendor sources and pin the XCFramework from
upstream.c4e16970a803 (ghostty c4e16970). Keep the
explicit pasteboard text(from: .general) call sites.
Copilot AI review requested due to automatic review settings September 3, 2026 08:09

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Comment on lines +16 to +19
private static let escapedCharacters: Set<Character> = [
"\\", " ", "(", ")", "[", "]", "{", "}", "<", ">", "\"", "'", "`",
"!", "#", "$", "&", ";", "|", "*", "?", "\t",
]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 security Line terminators bypass path escaping

When a pasted or dropped filename contains a newline followed by shell syntax, escape copies the newline unchanged and the drop path sends it to the live terminal, causing the remainder of the filename to be interpreted as a separate shell command.

How this was verified: The escape set omits CR and LF, while the file-URL path passes through this function before being sent to the terminal surface.

Suggested change
private static let escapedCharacters: Set<Character> = [
"\\", " ", "(", ")", "[", "]", "{", "}", "<", ">", "\"", "'", "`",
"!", "#", "$", "&", ";", "|", "*", "?", "\t",
]
private static let escapedCharacters: Set<Character> = [
"\\", " ", "(", ")", "[", "]", "{", "}", "<", ">", "\"", "'", "`",
"!", "#", "$", "&", ";", "|", "*", "?", "\t", "\r", "\n",
]

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.

Vendor drift: upstream pins are behind

2 participants