Skip to content

Repository files navigation

M2Terminal

A macOS-native development console for running and managing terminal coding agents — Codex, Claude Code, and more — in one libghostty-powered workspace.

Terminals · AI sessions · MCP servers · Skills · API tokens · Browser panes, unified in one place.

platform ui engine core status license

English · 简体中文


Overview

M2Terminal is a macOS-first local development console built for working alongside terminal-based coding agents. It pulls the things a developer normally spreads across many tools into one native workspace: terminal panes, Codex / Claude Code sessions, MCP servers, skills, API tokens, and freely-placeable browser panes.

The goal is to feel like a native terminal workspace, not an Electron dashboard wrapped around a shell:

  • Terminal semantics belong to a mature engine. ANSI/VT parsing, the terminal state machine, scrollback, reflow, and font handling are owned by libghostty (Ghostty's terminal kernel, consumed through the libghostty-vt C ABI). Swift/AppKit is a native host and input router — it does not implement a second terminal.
  • Processes and state belong to a Rust core. A Rust daemon/library owns PTY supervision, workspace/session lifecycle, MCP processes, SQLite metadata, config import/export, hooks, runbooks, and a local automation interface.
  • M2Terminal owns the canonical config. The MCP/skills configuration is app-owned and exported to Codex- and Claude Code-compatible formats through adapters — never the other way around.
  • Secrets stay in Keychain. Token values live only in the macOS Keychain; SQLite and exported config store references only, and plaintext secrets are never rendered into terminal command text.

⚠️ Pre-1.0 (currently 0.2.2). Architecture and some behavior are still evolving; interfaces and storage formats may change.


Features

🖥️ Terminal workspace

  • Native AppKit workspace shell: sidebar, tab strip, terminal groups, split panes, status bar, tab history.
  • Default Metal grid renderer (TerminalMetalGridView) that GPU-paints the libghostty-vt TerminalFrame; falls back to the AppKit grid when Metal is unavailable or M2TERMINAL_GPU_RENDER=0. Both have full parity: text (incl. color emoji and ligatures), selection, find, cursor, underlines, URL underlines, IME composition, and predicted local echo.
  • Full input-method (IME) support, soft-wrap-aware copy, URL detection with Command-Click, and command highlighting.
  • Ctrl+Tab / Ctrl+Shift+Tab cycle tabs in order within a workspace.

🤖 AI session management

  • Discover Codex and Claude Code sessions from their own local JSONL history, plus the current workspace's terminal output.
  • Filter by provider, inspect transcripts, filter messages, copy the resume command, restore, and delete the source file.
  • Restoring a session creates a new workspace tab and runs the provider's native resume command (codex resume <id> / claude --resume <id>).

🧩 Management Center

  • SwiftUI settings surfaces: general settings, MCP servers, skills, API-token references, per-workspace enablement, agent environment templates, shortcuts, and trash.
  • The canonical MCP/skills config is independent of any single agent's file format; exporters generate Codex- and Claude Code-compatible output with dry-run, diff, and drift detection.

🌐 User-controlled browser panes

  • WKWebView-based, placeable as a workspace browser tab, a split pane, a separate app window, or delegated to the system browser.
  • App-owned link routing and network policy: embedded host allowlist, always-external rules, HTTP host allowlist, and System / HTTP CONNECT / SOCKS / No Proxy modes with a connection self-check.
  • Page summaries sent to agent panes carry an explicit untrusted-source boundary and are delivered via bracketed paste — never injected straight into terminal input.

🔀 Git and tab history

  • Lightweight git status in the workspace footer; Git Diff / Git Branches open as workspace tabs without growing the main window.
  • Local branch management: checkout and new-branch creation from the current or a selected source branch.
  • Closed tabs and a workspace trash retain enough metadata to restore.

⚙️ Local automation & acceptance

  • The Rust core exposes a Unix domain socket + JSON-RPC automation interface, plus CLI/runbook/hook workflows.
  • A built-in app-control socket (M2TERMINAL_APP_CONTROL=1) drives authorization-free acceptance flows via scripts/app-control.sh.

Architecture

flowchart TD
    App["Swift / AppKit workspace UI"]
    SwiftUI["SwiftUI settings / management"]
    TerminalHost["Terminal host views"]
    GhosttyVT["libghostty-vt bridge"]
    Browser["WKWebView panes / windows"]
    CoreClient["Swift CoreClient"]
    Core["Rust m2terminal-core"]
    SQLite["SQLite metadata"]
    Keychain["macOS Keychain"]
    PTY["PTY processes"]
    Agents["Codex / Claude Code / shell"]
    MCP["MCP processes"]
    Config["Canonical MCP/skills config"]
    Exporters["Codex / Claude Code exporters"]

    App --> SwiftUI
    App --> TerminalHost
    App --> Browser
    TerminalHost --> GhosttyVT
    App <--> CoreClient
    CoreClient <--> Core
    Core <--> SQLite
    App <--> Keychain
    Core <--> PTY
    PTY <--> Agents
    Core <--> MCP
    Core <--> Config
    Core --> Exporters
Loading

Key boundaries

  • Terminal truth source: libghostty-vt owns the active VT state and the formatted scrollback/search/snapshot text. TerminalOutputBuffer and NSTextView are fallback, selection/accessibility mirrors, and regression models — not the product terminal truth source.
  • Process / session ownership: the Rust core is the preferred owner of PTY lifecycle and session metadata; Swift local PTY paths remain fallback/test support.
  • Secrets boundary: token values live only in Keychain; SQLite and exported config store references or non-secret metadata only. Agent launches pass a typed TerminalLaunchEnvironment (env map + managed-key removals) straight to the PTY — never an env KEY=value command prefix.

See docs/TECHNICAL_ARCHITECTURE.md for the target architecture and docs/CURRENT_ARCHITECTURE.md for the current implementation snapshot.


Stack

Layer Technology Notes
Primary language / UI shell Swift · AppKit Owns windows, splits, terminal host, keyboard handling, native macOS ergonomics
Settings / management UI SwiftUI Settings, forms, and management surfaces
Terminal engine libghostty / libghostty-vt ANSI/VT parsing, terminal state, fonts, reflow, scrollback
Terminal rendering Metal (default) + AppKit fallback GPU-paints the libghostty-vt TerminalFrame
Core orchestration Rust (m2terminal-core) Process supervision, PTY, socket API, state machines, config, agent lifecycle
Browser WKWebView Native embedding with controllable pane/window placement
Secrets macOS Keychain Tokens never hit plaintext files
Metadata SQLite Workspace/session state, MCP/skills registries, logs
User config TOML / JSON Easy to edit and diff
Automation Unix domain socket + JSON-RPC Local-first, scriptable, reusable by CLI tools

Build from source

Prerequisites

  • macOS 14 (Sonoma) or newer
  • Swift 6 toolchain (Xcode 16+ or an equivalent Swift toolchain)
  • Rust toolchain (cargo, for crates/m2terminal-core)
  • libghostty-vt — a linkable library + headers. Build it from Ghostty source with the bundled script (requires Zig 0.15.2), or provide it yourself via pkg-config (libghostty-vt / libghostty) or the LIBGHOSTTY_INCLUDE_DIR + LIBGHOSTTY_LIBRARY_PATH environment variables.

Steps

# 1) Clone
git clone https://github.com/MetaMortise/M2Terminal.git
cd M2Terminal

# 2) Build libghostty-vt from Ghostty source (requires Zig 0.15.2)
#    Output lands in .build/libghostty-vt by default
scripts/build_libghostty_vt.sh

# 3) Build and sign the app bundle → .build/M2Terminal.app
scripts/build_app.sh

# 4) Run
open .build/M2Terminal.app

Run scripts/check_libghostty.sh to verify the libghostty dependency is in place. If you already provide libghostty-vt via pkg-config or env vars, you can skip step 2.


Repository layout

Path Owner
Sources/M2Terminal/ macOS app: AppKit workspace shell, SwiftUI management surfaces, terminal host, browser panes, app-control hooks, localization, user workflows
Sources/M2Terminal/Core/ Swift client + models for the Rust core JSON-RPC boundary (split by workspace / config / session / PTY / automation)
Sources/M2TerminalGhosttyShim/ C module boundary that links the Ghostty VT runtime into Swift
crates/m2terminal-core/ Rust core daemon/library: SQLite metadata, workspace/session state, PTY supervision, MCP lifecycle, config import/export, hooks, runbooks, CLI
Tests/M2TerminalTests/ Swift unit/integration coverage: terminal behavior, workspace UX, preferences, localization, app-control
scripts/ Build, packaging, app-control, Ghostty runtime, and benchmark helpers
docs/ Target/current architecture, TODOs, runbooks, hooks, packaging, audits, and problem records

Develop & test

# Full Swift test suite
swift test

# A single test
swift test --filter TerminalMVPTests

# Rust core tests (when changing Rust code)
cargo test --manifest-path crates/m2terminal-core/Cargo.toml

# Pre-commit sanity check
git diff --check

Two-gate validation discipline: every requirement passes two gates — (1) scripted validation (unit/integration tests or project scripts), and (2) real-app acceptance (launch the packaged app with M2TERMINAL_APP_CONTROL=1, then drive the user-facing flow via scripts/app-control.sh). See Requirement Completion Validation in AGENTS.md.


Documentation


Roadmap (development phases)

  • Phase 1 — Proof of terminal workspace: native window, single terminal pane, PTY lifecycle, launch Codex/Claude Code, basic scrollback and input, basic settings window.
  • Phase 2 — Agent workspace: multiple panes, session list, status detection, attention notifications, workspace restore metadata.
  • Phase 3 — Browser & context routing: WKWebView pane, user-selectable placement, send browser URL/context to a selected agent.
  • Phase 4 — Management Center: MCP/skills registries, Keychain token management, per-workspace enablement, canonical config, Codex/Claude Code exporters, dry-run/diff/drift detection.
  • Phase 5 — Automation: local socket API, CLI, hooks, runbooks, scriptable agent/browser/workspace actions.

Current progress and open work: docs/TODO.md.


License

Released under the MIT License.

M2Terminal depends on Ghostty (also MIT-licensed) via libghostty-vt; building from source fetches Ghostty source, so please observe its license terms as well.

About

macOS-native development console for terminal coding agents (Codex, Claude Code) — a libghostty-powered workspace unifying terminals, AI sessions, MCP servers, skills, API tokens, and browser panes, backed by a Rust core.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages