Skip to content

yu314-coder/CodeBench

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

112 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CodeBench

A self-contained developer / scientific / AI workstation for iPad and Mac. Python 3.14, Jupyter notebooks, C, C++, Fortran, pdflatex, and local LLMs — all running on-device, no internet required.

  iPad / iPadOS / Mac Catalyst
  ┌──────────────────────────────────────────────────────────┐
  │                                                          │
  │   Monaco editor ─── IntelliSense + signature help        │
  │       ▲                  ▲                               │
  │       │                  │                               │
  │       │            ┌─────┴───────┐                       │
  │       │            │  vim mode   │  ⌘P  ⌘,               │
  │       │            └─────────────┘                       │
  │       ▼                                                  │
  │   Notebook editor  ─── per-cell Run + persistent kernel  │
  │       │                                                  │
  │       ▼                                                  │
  │   Visual debugger ─── step / inspect / call stack        │
  │       │                                                  │
  │       ▼                                                  │
  │   Python / C / C++ / Fortran / pdflatex                  │
  │       │                                                  │
  │       ▼                                                  │
  │   SwiftTerm terminal ◄──► PTY ◄──► CPython REPL          │
  │       │                                                  │
  │       ▼                                                  │
  │   Local LLM chat + RAG + image gen                       │
  │   (bundled GGUF · OpenAI · Anthropic · Ollama remote)    │
  │                                                          │
  └──────────────────────────────────────────────────────────┘

Built on python-ios-lib — the Python 3.14 runtime + 30+ native iOS Python libraries project. Every library listed below has its own reference documentation in that repo; links go directly to each library's main doc.


What's new

AI Assist chat — ChatGPT-style UI

The in-editor AI chat was rebuilt around a streaming, conversational UI (open it from the editor toolbar):

  • Collapsible "thinking" — a reasoning model's <think> output folds into a pill you can expand; the final answer renders beneath it.
  • Compiled LaTeX / math$…$ and $$…$$ in replies render as native vector glyphs via SwiftMath, inline in the chat bubble (no web view).
  • Code cards — fenced code blocks become titled cards with copy + an inline Run button.
  • File attachments — a 📎 in the composer attaches PDFs / text / source files (shown as chips above the input) for the model to read.
  • Run Python from chat — with Auto-run AI code enabled, Python the assistant emits is executed automatically and its output (text, charts, tables) flows straight into the preview pane.

IntelliSense — full module & member completion

Autocomplete now indexes every importable module (not a hardcoded shortlist) and lazily fetches each module's members / attributes on demand from the live Python daemon — so typing a module name and . lists its real API surface, with kind-aware icons and signature help.

Jupyter notebook editor (.ipynb)

Tap any .ipynb file in the file browser → opens directly in the editor box as a cell-stacked notebook (not raw JSON in Monaco). Each cell has its own toolbar (Run ▶, move ↑/↓, insert +, delete 🗑, code↔markdown toggle 🅼/ƒ). Per-cell Run uses a persistent in-process Python kernel so variables defined in cell 1 are reachable from cell 2.

  • Output capture per cell: stdout, stderr, last-expression result, matplotlib PNG (auto-savefig), HTML (pandas DataFrames, plotly), red error tracebacks
  • Markdown cells render with GFM + KaTeX inline math, tap to switch to edit mode
  • Toolbar at top: ▶ Run All, ↻ Restart Kernel, 💾 Save (writes back to .ipynb JSON in nbformat v4)
  • No modal popup — the notebook lives inside editorContainer, replacing Monaco for the duration of .ipynb editing. Opening a .py swaps Monaco back inline.

Visual debugger

debug-gui script.py in the terminal → a floating toolbar appears at the top of the editor with:

  • Continue · ⏭ Step Over · ⤓ Step Into · ⤴ Step Out · ⏹ Stop
  • 🔍 Variable inspector panel (slides in from right) — live f_locals + f_globals tree, repr-clipped to 200 chars per value
  • Call stack — top 3 frames shown beneath the variables panel
  • Current-line arrow in Monaco's gutter (golden, auto-scrolls into view)
  • Persisted breakpoints (~/.codebench/breakpoints/<file>.bps) honoured at launch
  • Headless fallback — if the UI isn't compiled in (older build), the debugger auto-continues after 3 s so scripts don't hang

Configurable AI providers (⌘,)

The AI subsystem can now dispatch to any of four backends, switched per-request or per-session:

Provider Configure Notes
Bundled GGUF Models tab → tap a .gguf Default, runs through llama.cpp
OpenAI ⌘, → Settings → paste API key Streams chat/completions SSE
Anthropic ⌘, → Settings → paste API key Streams Messages API with system separation
OpenAI-compat ⌘, → set base URL (e.g. http://192.168.1.10:11434/v1) Ollama / vLLM / llama.cpp server

API keys are stored in Keychain (kSecAttrAccessibleWhenUnlockedThisDeviceOnly). Ctrl-C in the terminal cancels in-flight HTTP requests + local generations symmetrically.

Inline matplotlib / pandas display

plt.show() / display(df) / Image.show() / fig.show() from any script — Python or notebook cell — renders inline in the output panel with append semantics. No more "saves to disk, you have to open the file." Backed by a Python-side codebench_inline module that monkey-patches the show/display hooks and ships PNG / HTML artifacts to Swift via inline_*.json signal files.

Vim mode (in Monaco)

Toggle in ⌘, settings. Implements a ~80% subset of vim:

  • Modes: NORMAL · INSERT · VISUAL · V-LINE (status pill bottom-right)
  • Motion: h j k l · w b e · 0 $ ^ · gg G · { } %
  • Insert: i a I A o O
  • Edit: x X r · dd yy cc · d{motion} y{motion} c{motion} · p P · u <C-r> · J · . (last-change repeat)
  • Search: / ? n N
  • Visual: v V then d y c x
  • Cmdline: :w :q :wq :x (:w triggers Monaco save)
  • Counts: 3dd, 5j, 10G, etc.

Persists via localStorage.setItem('codebench.vim.enabled', '1') so it survives editor reloads.

Quick Open (⌘P) + Settings (⌘,)

  • ⌘P — VS Code-style fuzzy file picker. Recent files at the top with "recent · " subtitle, full workspace walk underneath (capped at 5 000 files). Arrow keys + Enter to open.
  • ⌘, — unified settings sheet: AI provider, API key, model name, temperature, max_tokens, vim mode toggle, inline-completion toggle.

Long-press Quick Look in file browser

Right-click / long-press any file in the file browser → "Quick Look" appears at the top of the context menu for:

  • .csv / .tsv → scrollable HTML grid (sticky header, row numbers, alt-row striping; capped at 5 000 × 100 cells)
  • .json → pretty-printed + regex syntax highlighting
  • .yaml / .yml / .toml → monospace pretty-print
  • .png / .jpg / .heic / .webp / .bmp / .tiff / .gif → pinch-zoomable image with dimensions caption
  • .npy / .npz → numpy table view (loaded in-process via the bundled Python; 1-D up to 1000 rows, 2-D up to 500×50)

REPL builtin (repl)

A persistent-namespace Python REPL — variables survive across invocations. Rich displayhook for pandas DataFrames (HTML table inline). Meta-commands :q :clear :show :save FILE. Use repl --keep to preserve the previous session's namespace.

Performance optimizations

Idle wake-ups dropped from ~117/sec to ~1.5/sec by moving three always-on timers to kqueue file-system event sources (DispatchSourceFileSystemObject) with a 2 s safety-net fallback:

Engine Old polling New idle Speedup
PywebviewBridge 10 ms (100 Hz) event-driven 200×
LaTeXEngine 100 ms event-driven 20×
AIEngine 150 ms event-driven 13×

Plus: IntelliSenseEngine 3 s blocking-loop → DispatchSource event watch (no held threads), MonacoEditorView.loadFileBatched collapses 3 JS round trips into 1 (~100 ms saved per file open), C/C++/Fortran Monaco providers lazy-register only on first non-Python file (saves ~210 symbol parses on pure-Python sessions). BackgroundExecutionGuard .sync.async to remove a Swift-Concurrency deadlock vector.

Auto-seeded test bundle (Workspace/Tests/)

On every launch, three test files auto-seed into your Workspace (respecting the .codebench_deleted tombstone so deletes stick):

  • codebench_features_test.py — automated 24-test feature suite for everything above
  • codebench_features_test.ipynb — sample notebook exercising every output type
  • codebench_debug_target.py — small target to step through under debug-gui

User-edited copies are detected by file-head SHA comparison and never overwritten on subsequent launches.


Recent improvements

  • Reliable inline preview for shell-launched pythonpython foo.py from the integrated terminal now displays the resulting matplotlib/plotly chart in the preview pane the same way the Run button does. Previously flaky for several reasons, all fixed:

    • PTY scanner missed [plot saved] /… / [manim rendered] /… markers prefixed with ANSI escape codes (CSI clear-line, prompt redraws). The hasPrefix check is now preceded by stripAnsiEscapes and also handles the [manim rendered] marker.
    • WKWebView.loadFileURL(allowingReadAccessTo:) flaked on macOS Catalyst — the access grant to the sandboxed WebContent process raced the actual load (WebProcessProxy::hasAssumedReadAccessToURL: no access). The HTML branch of showImageOutput now reads the file (up to 20 MB) and uses loadHTMLString(html, baseURL: parentDir), sidestepping the sandbox grant entirely.
    • A blank-HTML preload meant to drop a previous manim video DOM was causing back-to-back async loads for HTML→HTML transitions; the blank's cancellation (NSURLErrorCancelled -999) intermittently propagated into the chart load. Skipped when the next content is also HTML — the new HTML replaces the DOM atomically.
    • The dir-watcher's DispatchSource.makeFileSystemObjectSource(.write) fires on inode create (file size 0) but doesn't re-fire on subsequent content writes into an existing entry. Heavy plotly HTML can take 60–80 s to serialize on iOS Python. A new pollForChartCompletion polls every 0.5 s for up to 120 s once a too-small file is seen, then routes through tryShowChart when size ≥ 4 KB.
    • flush=True added to the embedded _offlinai_*_show print sites so the marker line definitely reaches the PTY.
    • Diagnostic NSLog lines added across the chain: filter Xcode console on [chart-watch] to trace dir-event → poll → load.
  • Inherited from python-ios-lib: matplotlib shim no longer crashes user scripts on chained attribute access (ax.xaxis.line.set_color(...) etc.), and full plotly styling — titles, axis ranges, backgrounds — now applies correctly (was being silently aborted by a __figure__ sentinel leak). See python-ios-lib's recent changes.


What CodeBench adds

Capability How
Monaco code editor (real VS-Code editor) WKWebView-hosted Python IntelliSense — indexes every importable module with lazy member/attribute completion, ~70-entry signature DB, hover docs, auto-resolve from a Python daemon for numpy / scipy / sklearn / matplotlib / sympy. Vim mode (NORMAL/INSERT/VISUAL/V-LINE), inline AI completion (ghost text, 350 ms debounced)
Jupyter notebook editor Cell-stacked .ipynb editor embedded inline in the editor box. Per-cell Run + persistent in-process kernel, output capture (stdout/stderr/PNG/HTML/error), markdown cells with GFM + KaTeX, save back to nbformat v4
Visual debugger Floating toolbar (Continue / Step Over / Step Into / Step Out / Stop) + variable inspector + call stack + golden current-line arrow in gutter. Driven by a Pdb subclass over signal files. Persisted breakpoints
Integrated terminal SwiftTerm backed by a PTY master/slave pair piping into the embedded CPython REPL
pdflatex on-device busytex WASM (pdftex 1.40.25 + xetex + luatex + bibtex8 + xdvipdfmx) running in a hidden WKWebView with TeX Live 2023 packages preloaded into MEMFS. A custom 23 MB overlay adds pgf / tikz / beamer / hyperref / mathtools / microtype / cleveref / fancyhdr / bbm / CJKutf8 / fontspec / ctex and ls-R index
Local + remote LLM chat llama.cpp for GGUF models + ExecuTorch + OpenAI / Anthropic / OpenAI-compat (Ollama, vLLM) HTTP streaming. ChatGPT-style UI: streaming, collapsible thinking, compiled LaTeX, code cards, 📎 file attachments, optional auto-run of AI-generated Python into the preview. Conversation export. API keys in Keychain. Provider switchable via ⌘,
RAG engine In-process vector store for RAG over user-imported docs
Image generation Offline image models via ExecuTorch
Inline rich output plt.show() / display(df) / Image.show() etc. render in the output panel with append semantics — figures, DataFrames, plotly all flow through
Quick Open (⌘P) VS Code-style fuzzy file picker (recent + workspace walk)
Quick Look (long-press file) Inline grid view for CSV/JSON/YAML/TOML/NPY/PNG/JPG without opening Monaco
File browser + tabs iOS document browser with multiple concurrent workspaces
Auto-save Debounced ~600 ms after keystroke, plus on run / tab-switch / view-disappear / app-backgrounding
Tombstone system Files deleted via UI are recorded in <Workspace>/.codebench_deleted so starter-script seeders don't resurrect them on next launch
Auto-seeded test bundle Workspace/Tests/ gets 3 test files on launch (respects tombstone + user-edit detection)

Languages

Language Runtime Main doc
Python 3.14 BeeWare-embedded CPython python-ios-lib README
Jupyter .ipynb Same CPython, cell-stacked editor with persistent in-process kernel (built-in; tap any .ipynb in the file browser)
C Pure-Swift tree-walking interpreter (3.4k LOC, 48 operators, structs, pointers, preprocessor) c-interpreter.md · interpreters.md
C++ Pure-Swift tree-walking interpreter (4.2k LOC, classes, STL, templates, inheritance) cpp-interpreter.md · interpreters.md
Fortran Pure-Swift tree-walking interpreter (4.1k LOC, modules, allocatable arrays, intrinsics) fortran-interpreter.md · fortran-runtime.md

All four languages share the same Monaco editor + IntelliSense pipeline and auto-save. Python additionally has the dedicated notebook editor for .ipynb files (cell-stacked UI in place of Monaco).


Python libraries — direct links to each library's doc

Every library below is bundled natively on-device. Click the library name to jump to its reference doc in python-ios-lib.

Scientific computing

Library Type Doc
NumPy 2.3.5 Native iOS (arm64) docs/libs/numpy.md · docs/numpy.md
SciPy 1.15.0 Pure Python shim docs/libs/scipy.md · docs/scipy-ios.md
SymPy 1.14.0 Pure Python docs/sympy.md · docs/libs/sympy.md
mpmath 1.4.1 Pure Python docs/mpmath.md

Machine learning

Library Type Doc
PyTorch 2.1.2 (patched) Native iOS (arm64) — full import torch, tensors, autograd, nn, optim, JIT, FFT, distributions. Accelerate-backed linalg docs/libs/pytorch.md
transformers 4.41.2 Pure Python — HuggingFace BERT / GPT-2 / T5 / BART, train + generate on-device docs/libs/transformers.md
tokenizers 0.19.1 Native iOS (Rust) — first public iOS build, real BPE/WordPiece/Unigram trainers, PyO3 bindings docs/libs/tokenizers.md
scikit-learn Pure NumPy (12k+ LOC, 40 modules, 38 metrics) docs/sklearn.md · docs/libs/sklearn.md

Visualization & media

Library Type Doc
matplotlib Native iOS docs/matplotlib.md · docs/libs/matplotlib.md
manim Pure Python docs/manim.md · docs/libs/manim.md
Pillow Native iOS (libjpeg-turbo + zlib) docs/pillow.md
PyAV / FFmpeg Native iOS (libavcodec, libavformat, libavfilter, …) docs/av-pyav.md · docs/libs/media.md
plotly Pure Python docs/plotly.md
svgelements Pure Python docs/svgelements.md
pydub Pure Python (ffmpeg-backed) docs/pydub.md

Utilities

Library Type Doc
networkx Pure Python docs/networkx.md
beautifulsoup4 Pure Python docs/beautifulsoup.md
click Pure Python docs/click.md
jsonschema Pure Python docs/jsonschema.md
PyYAML Pure Python docs/pyyaml.md
pygments Pure Python docs/pygments.md
rich Pure Python docs/rich.md
tqdm Pure Python docs/tqdm.md
Minor libs (requests, dateutil, psutil, watchdog, screeninfo, soupsieve, safetensors, regex, typing_extensions, …) Mixed docs/minor-libs.md

Full top-level reference: python-ios-lib/docs/README.md.


LaTeX (pdflatex)

CodeBench's pdflatex / latex / tex shell commands route to busytex WASM running in a hidden WKWebView. The TeX Live 2023 data packages (texlive-basic + ubuntu-texlive-{latex-base, latex-recommended, fonts-recommended, latex-extra, science}, ~230 MB compressed) preload into MEMFS on first run. A 23 MB overlay data package bundles extra packages pdflatex commonly needs:

  • PGF / TikZ / beamer + themes + translator
  • hyperref + dependencies (kvsetkeys, pdfescape, hycolor, …)
  • mathtools, microtype, cleveref, fancyhdr, geometry, setspace, bbm (+ bbm-macros)
  • CJK + CJKutf8 (CJK family)
  • amscls / amsthm / mathrsfs / booktabs / float / enumitem
  • A kpathsea ls-R index so lookups are O(1)

On top of the pipeline, the Swift-side BusytexEngine adds:

  • Sibling-file collection: scans \includegraphics, \includepdf, \input, \include, \bibliography references, bundles real files + synthesizes 1×1 placeholder PNG/PDF for missing ones so compiles don't abort on a missing figure.
  • Unicode sanitizer: replaces codepoints pdflatex can't render (CJK, symbols past U+0200) with [?] so stray Unicode doesn't fatal-error mid-compile.
  • Auto-lmodern injection: when the doc uses \usepackage[T1]{fontenc} without a T1-capable font family, auto-adds \usepackage{lmodern} so pdftex doesn't try to spawn mktexpk (which needs fork(), unavailable in WASM).
  • Live progress streaming: every pdftex stdout line streams to the terminal as it compiles, plus a Swift-side 3 s heartbeat so you know the engine is alive during long runs.

Full pdflatex doc: media.md#offlinai_latex--local-latex-engine.


Local & remote AI

The AI subsystem (chat, ai builtin, inline code-completion) routes to one of four backends, switchable per-session via ⌘, settings or per-request via the "provider" field in ai_request.json:

Backend Use case
Bundled GGUF (default) Fully offline. Load a .gguf from the Models tab. Runs through llama.cpp / Metal
OpenAI Streaming chat/completions SSE. Just paste an API key — defaults to https://api.openai.com/v1
Anthropic Streaming Messages API. Handles system separation automatically
OpenAI-compat Any endpoint that speaks chat/completions SSE — Ollama, vLLM, llama.cpp server, LM Studio

API keys live in Keychain (kSecAttrAccessibleWhenUnlockedThisDeviceOnly), one slot per provider. Ctrl-C in the terminal cancels in-flight HTTP requests and local generations symmetrically. Inline AI code-completion (ghost text, 350 ms debounced) uses whichever provider is configured.

The chat surface is a ChatGPT-style conversational UI: streaming replies, a collapsible "thinking" pill for reasoning models, inline-compiled LaTeX/math (SwiftMath), copyable code cards with a Run button, 📎 file attachments (PDF / text / source), and — when Auto-run AI code is enabled — automatic execution of the Python the assistant writes, with its output (text, charts, tables) routed into the preview pane.

  • GGUF models via llama.cpp integrated as an XCFramework. Load any Llama / Mistral / Qwen / Phi model, chat with streaming tokens.
  • ExecuTorch backends for Apple-Core-ML / XNNPACK / kernel-optimized inference of PyTorch models.
  • PyTorch → Metal GPU bridge (CodeBench/MetalMatmulBridge.swift) — exposes one @_cdecl C entry point backed by MPSMatrixMultiplication. Python's _torch_metal_bridge.py (in python-ios-lib) reaches it via dlopen(NULL) + dlsym and monkey-patches torch.matmul / mm / bmm / addmm / F.linear / F.scaled_dot_product_attention on every Python startup. Real on-device transformer training in fp32/fp16/bf16 with 2–10× speedup over CPU. Linker flags in OTHER_LDFLAGS (-Wl,-exported_symbol,_cb_metal_*) keep the symbol export-visible through Apple's archive / TestFlight strip pass.
  • LoRA fine-tuning via llama.cpp's Metal backward kernels (separate path from the PyTorch bridge) — see CodeBench/LlamaFinetuner.swift. Trains a LoRA adapter on a GGUF base model in-place.
  • RAG: in-process sentence-embedding + vector store over user-imported text / PDF / markdown.
  • Image generation via ExecuTorch-runnable diffusion-family models.

All models live in the app sandbox; no tokens leave the device.


Shell

The CodeBench shell IS a Python REPL — typing Python executes directly. On top of it there are builtins for POSIX-y operations iOS doesn't give you:

  • File/system: ls, cd, pwd, mkdir, rm, cp, mv, cat, head, tail, grep, find, file, touch, df, du, ncdu, top
  • Languages: python / python3 (with -V / -c / -m / full flag handling), cc / gcc / clang, c++ / g++ / clang++, gfortran / f77 / f90 / f95
  • LaTeX: pdflatex, latex, tex, pdftex, latex-diagnose
  • Markdown / notebook viewers: md / markdown (renders .md to the preview pane via markdown-it-py + KaTeX), nb / ipynb / notebook (read-only .ipynb preview — for the full cell-stacked editor, tap the file in the file browser)
  • AI: ai (chat with the configured provider — bundled GGUF or remote)
  • Debugger: debug (classic pdb in the terminal), debug-gui (floating toolbar + variable inspector in the editor)
  • REPL: repl (persistent-namespace Python with rich displayhook; repl --keep preserves last session's namespace)
  • Test runners: test-libs / test_libs (smoke-test every bundled library)
  • VCS: git clone (via zipball fetch — real Git protocol isn't available sandboxed; HuggingFace hf:// URLs supported via snapshot_download)
  • Package mgmt: pip (install to the per-workspace site-packages dir; smart-skips already-bundled deps)

python --help, python -V, python -c "print(1+1)", python -m pip install … all behave like real CPython.

Keyboard shortcuts

Shortcut Action
⌘P Quick Open file picker (fuzzy match)
⌘, Settings sheet (AI provider, vim mode, inline completion)
⌘/ Keyboard-shortcuts help
⌘A (in terminal) Select all terminal output
⌘C (in terminal) Copy selection
⌘V Paste (Monaco + terminal)
Ctrl-C (in terminal) Interrupt running script / cancel AI generation
Ctrl-D (in terminal) EOF / exit current REPL

Install / build

This repo contains the CodeBench-specific pieces (Swift source, Xcode project, resources, busytex data packages via LFS, build scripts). It depends on python-ios-lib for the runtime layer (Python.xcframework, llama.xcframework, ExecuTorch frameworks, app_packages, Monaco folder, SwiftTerm SPM).

Quickstart (recommended)

git clone https://github.com/yu314-coder/CodeBench
cd CodeBench
./scripts/setup.sh        # clones python-ios-lib + symlinks it in
open CodeBench.xcodeproj

setup.sh clones python-ios-lib into _vendor/python-ios-lib/ and creates symlinks at the workspace root (Frameworks/, app_packages/, Monaco/, Sources/, Package.swift) pointing into the vendored runtime. Both repos keep independent .git histories — pulling updates on either side is just git pull in the corresponding directory. Re-run ./scripts/setup.sh --update to also fast-forward the runtime.

Git LFS auto-pulls the busytex data packages (~244 MB) on clone via the configured filters. If your git client skipped them, run git lfs pull inside CodeBench/Resources/Busytex/ before building.

Manual layout (if you can't use symlinks)

Some setups (Windows-with-WSL, sandboxed CI) don't follow symlinks well. In that case, lay the two repos out side-by-side as one merged workspace:

git clone https://github.com/yu314-coder/python-ios-lib
cd python-ios-lib
git clone https://github.com/yu314-coder/CodeBench _codebench
cp -R _codebench/CodeBench _codebench/CodeBench.xcodeproj _codebench/Info.plist .
cp -R _codebench/scripts/* scripts/ 2>/dev/null || true

Either way, Xcode opens CodeBench.xcodeproj and finds Frameworks/, app_packages/, Monaco/, Sources/, and Package.swift at the workspace root.

Build target

Xcode scheme: CodeBench. Run on a real device, on TestFlight, or via My Mac (Designed for iPad). The first build takes a few minutes; subsequent builds are incremental.

Rebuilding llama.xcframework (optional, advanced)

llama.xcframework is prebuilt and shipped in python-ios-lib/Frameworks/, so the app links against it directly. Only rebuild from llama.cpp source if you need a different upstream version or build flags:

mkdir -p third_party
git clone https://github.com/ggerganov/llama.cpp third_party/llama.cpp
# Then run python-ios-lib/build-xcframework.sh + finish-ios-only.sh
# and replace python-ios-lib/Frameworks/llama.xcframework with the result.

Installed-bundle size

The finished CodeBench.app is ~1 GB:

  • 791 MB Frameworks/ (Python, llama, ExecuTorch xcframeworks — from python-ios-lib)
  • 484 MB app_packages/ (bundled Python site-packages — from python-ios-lib)
  • 254 MB CodeBench/ (Swift source + Resources, of which ~230 MB is the LaTeX data packages — this repo, via LFS)

What's in this repo vs python-ios-lib vs upstream

Verified against gh api /repos/yu314-coder/{repo}/contents/ as of this commit.

This repo (CodeBench) python-ios-lib Upstream only — re-clone if rebuilding
CodeBench/ — Swift source + Resources (busytex data via LFS) Frameworks/ — Python / llama / ExecuTorch / LaTeX xcframeworks third_party/llama.cpp/ggerganov/llama.cpp (~7.6 GB, only needed if rebuilding llama.xcframework)
CodeBench.xcodeproj/ app_packages/ — bundled Python site-packages
Info.plist Monaco/ — Monaco editor WebView bundle
scripts/ — CodeBench-specific build helpers: Sources/ + Package.swift — SwiftTerm SPM integration
  • fetch_busytex_assets.sh (LFS-fallback downloader) docs/ — per-library reference docs (linked from this README)
  • fetch_ios_wheels.py, unpack_wheels.sh, check_wheels.py fix_ffmpeg_paths.sh — install_name_tool rewrite for av.*.framework
  • fix_ffmpeg_paths.sh (mirror) C-lib build dirs: cairo/, cpp/, ffmpeg/, fortran/, gcc/, harfbuzz/, pango/, skia-pathops/
  • test_all_libs.py (smoke test for all 30+ libs) Python-pkg build dirs: numpy_ios/, pandas_ios/, pillow_ios/, psutil_ios/, audioop/, av/, matplotlib/, scipy/, sklearn/, manimpango/, mapbox_earcut/

Files / dirs not in either repo (local-only build scratch, never checked in): third_party/, DerivedData/, build/, .venv/, xcuserdata/. Generated on-demand by the build scripts in python-ios-lib.

Monaco editor: lives in python-ios-lib (14 MB — Monaco/ top-level folder reference). CodeBench's CodeBench.xcodeproj references it at the workspace root, so after you complete the step-2 clone recipe above, the Xcode project finds it.


Acknowledgements

CodeBench stands on:

  • python-ios-lib — the CPython 3.14 runtime and 30+ iOS-ported Python libraries that make the app work
  • BeeWare — the Python.xcframework embedding technique
  • SwiftTerm — xterm-compatible terminal emulator
  • Monaco Editor — VS Code's editor in WKWebView
  • busytex — TeX Live 2023 compiled to WASM
  • llama.cpp / ExecuTorch — local LLM inference
  • SwiftMath — native CoreText math rendering for $…$ inline expressions

License

See LICENSE. Individual dependencies retain their original licenses — consult each project's repo (linked above).

About

Self-contained developer/scientific/AI workstation for iPad and Mac — Python, C, C++, Fortran, pdflatex, local LLMs. All offline. Built on python-ios-lib.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors