Architecture

Module Overview

Namu is organized around four main code areas with clear boundaries:

AreaDirectoryPurpose
NamuKit NamuKit/ Core logic. Domain models, Ghostty FFI, IPC, relay, services, alerting, browser, remote. No SwiftUI imports.
NamuUI NamuUI/ SwiftUI and AppKit views. App entry point, workspace rendering, browser views, settings, notifications, update UI.
CLI CLI/ The namu command-line client plus tmux compatibility, Claude hooks, Codex hooks, ref ID resolution, and helper entry points.
Remote Helper daemon/remote/ Go daemon providing 12 RPC methods for remote session management, PTY resize, SOCKS5/HTTP CONNECT proxy, and stream multiplexing.

NamuKit Internals

SubdirectoryResponsibility
Domain/Core value types: Workspace, Panel, PaneTree, session snapshots, WorkspaceRemoteConfiguration, and workspace placement settings.
Terminal/Ghostty bridge/config/keyboard wrappers, TerminalSurfaceRegistry (pointer safety), PortalHostLease system, session lifecycle, CJK IME, dictation, middle-click paste, shell integration, copy mode, image transfer (Kitty + SCP), SSH detection, and ZDOTDIR overlay.
IPC/SocketServer, RelayServer (TCP with HMAC-SHA256), command registry/dispatcher, access control, event bus, command namespaces, middleware, and password auth.
Services/Workspace/panel managers, persistence, notifications (status/progress/log APIs), layout, appearance, analytics, PortScanner (batched ps+lsof), project config watcher, and app coordination.
Alerting/Outbound channel delivery for Slack, Telegram, Discord, and generic webhook with rate limiting and credential security.
Browser/BrowserProfileStore, BrowserHistoryStore, browser models, MarkdownPanel with file watching, 84+ browser command handlers, network tracing, and proxy configuration.
Remote/RemoteSessionController, DaemonRPCClient, RemoteProxyBroker, RemoteProxyTunnel, and CLI relay server for SSH remote workspaces.
Debug/Keystroke latency profiling (TypingTiming, 34 instrumentation points always compiled in).
Scripting/AppleScript support (4 classes, 11 commands via SDEF).
Config/Project configuration, directory trust, config hot-reload, and command execution.

Dependency Graph

NamuUI
  |
  +---> NamuKit
  |       |
  |       +---> Domain
  |       +---> Terminal (Ghostty C FFI)
  |       +---> IPC (socket + relay + command dispatch)
  |       +---> Services (workspace, panel, notifications, config watcher)
  |       +---> Alerting
  |       +---> Browser (84+ commands, network tracing)
  |       +---> Remote (SSH orchestration, proxy broker)
  |
  +---> AppKit (hosting, overlays, browser integration)

CLI ---> Unix Socket ---> NamuKit/IPC
     \-> Short ref IDs resolved locally before RPC

daemon/remote ---> TCP relay ---> RelayServer ---> CommandDispatcher

Runtime Flows

Keyboard Input

NSEvent
  --> AppKit routing
    --> performKeyEquivalent
    --> keyDown
    --> interpretKeyEvents (NSTextInputClient, CJK IME, dictation)
      --> GhosttyKeyboard
        --> Ghostty surface

Local Socket Command

CLI / automation client
  --> SocketServer (access control + optional password auth)
    --> CommandDispatcher
      --> CommandRegistry
        --> namespace handler
          --> manager / service / terminal

SSH Remote Workspace

namu ssh user@host
  --> RemoteSessionController
    --> SSH process (BatchMode, ServerAliveInterval, ControlSocket)
      --> DaemonRPCClient (hello + capability negotiation)
        --> daemon binary (SHA256-verified, provisioned on demand)
          --> session.attach / session.resize / session.detach
          --> proxy.socks5 / proxy.http_connect (browser traffic)
  --> CLIRelayServer (HMAC-SHA256 local socket)
    --> forwarded commands via SSH tunnel to remote daemon

Alert Flow

EventBus event (process.exit | output.match | port.change | shell.idle)
  --> AlertEngine (4 trigger types)
    --> AlertRouter
      --> Slack / Telegram / Discord / Webhook channel
        --> outbound API delivery

Sidebar Notification APIs

CLI: namu sidebar set_status / set_progress / log
  --> SocketServer
    --> SidebarStatusCommands / SidebarLogCommands
      --> WorkspaceManager
        --> SidebarMetadata update
          --> SwiftUI sidebar re-render (colored pills, progress bar, log entries)

Remote Relay Flow

Remote helper / forwarded client
  --> RelayServer (TCP with HMAC-SHA256 constant-time verification)
    --> Access control check
      --> CommandDispatcher
        --> JSON-RPC handler
          --> response sent over relay socket

Port Scanner Flow

Background timer
  --> PortScanner (batched ps+lsof)
    --> coalesce + burst detection
      --> port.change event published
        --> EventBus subscribers notified
          --> NAMU_PORT / NAMU_PORT_RANGE env vars updated per workspace

Key Design Decisions

Clean Architecture

Namu uses proven patterns — Ghostty embedding, socket namespaces, layout persistence, portal-style UI coordination — with a modular codebase. The main architectural goal is to avoid god objects and keep responsibilities narrow and testable.

Folder-Based Modules in a Single App Target

Most of the app builds as a single Xcode target organized by directory, rather than as many Swift packages. That keeps build complexity low while the architecture is still settling.

NamuKit Avoids UI Imports

Core logic lives in NamuKit and avoids SwiftUI/UIKit imports. The main exception is AppKit where Ghostty surface hosting requires it.

TerminalBackend Boundary

TerminalBackend defines the abstraction boundary while TerminalSession is the concrete Ghostty-backed implementation. Session lifecycle is modeled explicitly through SessionState.

Immutable PaneTree

Layout state is modeled as an indirect enum. Operations return new trees instead of mutating nested nodes, which keeps persistence and snapshotting simple.

Focus Policy

Only workspace.select and pane.focus are allowed to steal focus. All other commands preserve the current user focus state unless --no-focus is passed.

Short Ref IDs

All list responses include a ref field alongside id. The CLI resolves workspace:1, pane:2, and surface:3 notation locally before sending RPCs, so scripts do not need to track full UUIDs.

Security Model

The relay uses CryptoKit constant-time HMAC comparison to prevent timing attacks. The proxy tunnel blocks 169.254.169.254 (cloud metadata SSRF). Daemon binary manifests are path-traversal checked before download. Relay and proxy response sizes are capped (1MB and 64KB respectively).

Performance Targets

MetricTargetMeasurement
Typing latency (p99)< 5msGhostty/keyboard-path instrumentation in debug builds
Socket command (read)< 10msDispatcher entry/exit timing
Socket command (write)< 50msDispatcher entry/exit timing
Alert routing< 3sAlertEngine emit to channel API response
Session restore< 2sLaunch to rendered surfaces