Skip to content

docs: feasibility study for Swift-native on-device agentic IDE - #5

Closed
ThyFriendlyFox wants to merge 1 commit into
mainfrom
cursor/feasibility-swift-native-on-device-ide-5e91
Closed

docs: feasibility study for Swift-native on-device agentic IDE#5
ThyFriendlyFox wants to merge 1 commit into
mainfrom
cursor/feasibility-swift-native-on-device-ide-5e91

Conversation

@ThyFriendlyFox

Copy link
Copy Markdown
Collaborator

Summary

Adds a research/scoping document assessing the feasibility of the proposed Swift-native, fully on-device agentic IDE (iOS-first) architecture, grounded in the realities of iOS, the App Store, and the existing Mouse codebase.

File: docs/feasibility-swift-native-on-device-ide.md

Verdict

Mostly feasible, with App Store precedents (Pythonista, Pyto, a-Shell, Swift Playgrounds, Working Copy) — but it is a new ground-up native product, not an evolution of the current Capacitor/Codespaces client. Three proposal claims do not hold on iOS and drive most of the risk:

  1. No JIT for third-party apps — JavaScriptCore runs interpreter-only; WASM runtimes must be pure interpreters. (llama.cpp Metal is GPU compute, unaffected.)
  2. No runtime install of compiled codepip/npm of native modules and dlopen of downloaded binaries are blocked by code-signing + Guideline 2.5.2; ship a pre-built bundled package catalog instead.
  3. SourceKit-LSP is unavailable on-device — use tree-sitter + bundled linters.

Other key corrections: the "terminal" is a curated command dispatcher (no real shell/fork/exec); Python has no subprocess/fork; security-scoped bookmarks are only needed for external URLs; local LLMs are limited to small mmap'd quantized models (1B–4B Q4) by per-app memory ceilings.

Contents

  • Per-layer feasibility table and detailed analysis (sandbox/VFS, JS/Python/WASM runtimes, editor, terminal, git/libgit2, agent orchestrator + cloud/local models, persistence, native integration)
  • The two binding constraints (Guideline 2.5.2; no third-party JIT)
  • A corrections table mapping each proposal claim to its iOS reality
  • Risk register and a phased, MVP-first path (editor + git + cloud agent first; on-device execution and local inference behind capability/memory gates; optional remote runtime as escape hatch)

Documentation only — no code or build changes.

Open in Web Open in Cursor 

Co-authored-by: ThyFriendlyFox <thyfriendlyfox@gmail.com>
ThyFriendlyFox added a commit that referenced this pull request Aug 5, 2026
Phase T's pure-logic layer in Kotlin, from swift/Mouse/TerminalScreen.swift,
TerminalWidth.swift and the contract half of TerminalPrograms.swift. Faithful
re-implementation, not a bridge (invariant #5): the grid, the alt-screen
save/RESTORE pair, scroll regions, DECCKM, bracketed paste, the 103-range
UAX#11 width table, the byte-at-a-time ANSI parser with its query replies,
TerminalKey's xterm encodings, and the TerminalProgram/TerminalProgramIO
contract.

It is its own Gradle module — pure Kotlin/JVM, no Compose, no android.*, no
dependency but kotlin-stdlib — for the reason phase T learned on iOS: logic
that shares a file with UI is logic no harness can reach. :app depends on it
and dexes it (verified: com/reagentsystems/mouse/terminal/TerminalScreen is
in classes2.dex).

The gate is :screencheck, a main() with no JUnit (invariant #4), shaped like
the Swift harnesses in verify/. Its corpus is the iOS corpus ported assertion
for assertion — verify/main.swift, altscreen, widechars, widetui and the
screen-level half of tty — reading the SAME checked-in fixtures rather than
copies, because two platforms gated by different corpora is a parity claim
nobody can falsify. That includes the strongest one: the captured claude-code
frame rendered against pyte's own output.

  ./gradlew :screencheck:run
  SCREEN CORPUS: 182 checks — grid, parser, widths, keys, program contract,
  pyte frame — MATCH
  (width table: all 199 agree with Python's unicodedata)

Proven able to fail, twice, before it was believed: making TerminalTty.onlcr
a pass-through reddened the pyte cross-check with the exact diagonal shear
the iOS comment describes ("2 of 182 ... MISMATCH", exit 1), and a bogus
width for U+2014 reddened the table ("unicodedata=1 ours=9").

ANDROID_HOME=~/Library/Android/sdk ./gradlew clean :screencheck:run
assembleDebug — BUILD SUCCESSFUL.

Deliberately deferred, not forgotten: NodeProgram (the Node layer, milestone
3) and the less/top programs. Only TerminalTty.onlcr is lifted out of
NodeProgram, because it is tty truth the screen's own gate needs — the iOS
comment says as much where it sits.

Adaptations where the languages differ, semantics unchanged: a Swift
Character (grapheme cluster) is a String, since a Kotlin Char cannot hold an
emoji; the parser walks code points for the same reason; value-type array
copies are explicit deep copies; CellStyle/TerminalCell are immutable data
classes; Sendable and @mainactor have no equivalent and the main-thread
discipline is documented instead. One assertion had to be spelled
differently: Swift compares Strings by canonical equivalence, so its
"combined glyph" expectation is "é"; Kotlin compares code units, so it names
what the cell holds, "é". Same grid, stricter comparison.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.

2 participants