Skip to content

Repository files navigation

9ed

9ed

One browser tab for code, terminals, git, agents, and live browser inspection.

Quick Start | Features | Recent Changes | Release Binaries | Development

GoReactTerminalRelease

9ed is a self-hosted browser IDE designed for agent-assisted development. It combines a Monaco editor, PTY terminals, git source control, ACP-powered AI chat, and an inspectable in-app browser into one responsive workspace.

It runs as a normal Go server during development and can also be shipped as a single embedded binary for releases.

Why 9ed?

FocusWhat it gives you
Local-first controlYour workspace, terminal sessions, git operations, and browser tools stay behind your own server and Basic Auth.
Agent-ready workflowAI chat can see terminal context, route commands into the active terminal, and attach inspected browser elements to prompts.
Portable deliveryProduction builds can embed the frontend into the Go binary, leaving only the binary and .env to deploy.

Preview

Desktop - Explorer and EditorDesktop - Git Diff View

Features

Terminal

  • PTY-backed terminal sessions managed by a Go backend
  • Multi-tab terminal UI using xterm.js
  • Cross-platform shell detection (PowerShell, cmd, Git Bash, WSL, bash, zsh)

Web IDE

  • Monaco Editor with multi-tab file editing
  • File explorer with tree navigation and context menu (New, Rename, Delete, Copy, Cut, Paste)
  • Full-text search across project files
  • Multi-project workspace support
  • Real-time file watcher (auto-sync on external changes)
  • Workspace state persistence (open tabs, active file restored on reopen)
  • Vue & Svelte syntax highlighting
  • .gitignore-aware file dimming in explorer

Git Source Control

  • Full git panel: status, stage/unstage, commit, push, pull
  • Branch management: create, switch, delete, merge
  • Stash support: save, pop, apply, drop
  • Commit history with pagination
  • Diff view (Monaco DiffEditor, side-by-side) - click any changed file to see diff
  • Git gutter decorations (green=added, blue=modified, red=deleted)
  • File-level discard changes
  • Change count badge on activity bar icon
  • Untracked files show full content as added (green)

AI Chat (ACP Protocol)

  • ACP (Agent Client Protocol) - structured JSON-RPC 2.0 communication with AI agents
  • Supports: OpenCode, Claude Code, Codex CLI, Gemini, Pi, Amp, GitHub Copilot
  • Auto-install ACP adapters (npm) when agent is selected
  • Dynamic model picker, mode/agent selector, thinking level - all from ACP configOptions
  • Slash command autocomplete from available_commands_update
  • Streaming responses with markdown rendering
  • Tool call visualization (read, edit, search, execute) with collapsible details
  • Plan/todo tracking with progress indicators
  • Thinking/reasoning display (collapsible)
  • Diff view for file changes made by agent
  • Auto-title sessions from first message or agent-generated title
  • PTY fallback for agents without ACP adapter
  • Permission dialog - approve/reject tool calls (ACP session/request_permission)
  • Auto-approve mode - skip permission prompts for trusted environments
  • Message queue - type and queue messages while agent is streaming
  • @ file mentions - reference any project file with autocomplete (filename + directory path)
  • Voice input - dictate messages via Web Speech API with microphone access handling

Terminal <-> Chat Integration

  • Bidirectional terminal context: AI agent receives live terminal scrollback as context
  • Active terminal routing: agent terminal commands execute directly in the active terminal session
  • "Run in terminal" button: shell code blocks in chat messages can be executed with one click
  • Terminal-aware AI: agent knows shell type (PowerShell, bash, zsh) and adapts commands
  • Terminal scrollback replay: backend buffers terminal output for reconnection and AI context
  • Terminal tabs per project: terminal state persisted in workspace, survives navigation

Browser Inspect (Element Inspector for AI)

  • 4-layer box model overlay: margin, border, padding, content - color-coded canvas rendering
  • Smart hit-test: click any element in browser panel to inspect
  • Rich tooltip: shows tag, id, classes, dimensions, CSS properties
  • Keyboard navigation: Tab/Shift+Tab between elements, Escape to exit
  • AI context injection: selected element can be sent as inspect details or as an element-only screenshot
  • Mini inspect panel: Styles, Events, Accessibility tabs for selected element
  • Ruler lines: visual guides from selected element to viewport edges

Global Settings

  • Global Settings panel available from the sidebar and mobile nav
  • Tunneling management for additional local ports with persisted state, live status, engine tag, and current public URL
  • About section with 9ed version and runtime info

Mobile - ChatMobile - Editor

Responsive Layout

  • Consistent state across all form factors - desktop, tablet, and mobile share the same Zustand state
  • Desktop (>=1024px): Full panel layout with resizable sidebar, editor, terminal, chat
  • Tablet (768-1023px): Overlay sidebar and chat panels
  • Mobile (<768px): Single-panel view with bottom navigation
  • Responsive layout mode changes preserve panel state - no remounting or data loss
  • File/git click auto-switches to editor view on mobile/tablet
  • Floating save button on mobile/tablet

Editor Features

  • Context menu on tabs: Close, Close Others, Close Left/Right, Close All, Copy Path
  • Context menu on files: New File/Folder, Cut, Copy, Paste, Duplicate, Rename, Delete
  • Conflict detection: "File changed on disk" bar with Overwrite/Revert options
  • Deleted file detection: indicator + Recreate/Close options
  • External change auto-reload (when no unsaved edits)

Security

  • Basic Auth protection for UI, API, and WebSocket
  • Session cookie bridge for WebSocket authentication
  • Path traversal protection for filesystem operations

Browser Proxy

  • In-app browser panel with tab management
  • Full URL rewriting (HTML, CSS, JS, fetch, XHR, EventSource)
  • MutationObserver-based dynamic resource rewriting (script, link, iframe, img)
  • JavaScript property descriptor interception (HTMLScriptElement.src, HTMLLinkElement.href)
  • Service worker registration stubbing for proxied pages
  • Cross-tab navigation via postMessage protocol

Tunnel

  • Auto-start tunnel for public access - no manual setup needed
  • Cloudflare (default): Quick tunnel via cloudflared, generates random public URL
  • Bore: Fixed port tunnel via bore.pub, auto-installs binary
  • Toggle with TUNNEL=true/false, select engine with TUNNEL_ENGINE=cloudflare|bore
  • Global Settings -> Tunneling panel for managing additional tunnels to other local ports on the same machine
  • Additional tunnels persist in SQLite, remember active state, and auto-start again after 9ed restarts
  • Each custom tunnel shows its engine, live public URL, and runtime state in the Settings UI
  • Auto-restart watchdog: tunnel process auto-restarts on crash
  • Graceful shutdown: clean process termination with timeout
  • Output recording: tunnel logs captured for diagnostics
  • Auto-shutdown on server exit

Requirements

  • Go 1.24+
  • Node.js 20+
  • Git (for source control features)
  • Optional: OpenCode, Claude Code, Codex CLI, Gemini, Pi, Amp (for AI chat)

Quick Start

cp .env.example .env
# Edit .env with your credentials
npm run start
# Open http://localhost:8080

Scripts

CommandAction
npm run startInstall deps + build frontend + run server
npm run serverRun Go server only (dev)
npm run devVite dev server (frontend hot reload)
npm run buildBuild frontend
npm run server:buildCompile Go binary
npm run binary:buildBuild frontend and embed it into a single Go binary
npm run checkTypeScript typecheck + Go vet
npm run go:testRun all Go tests
npm run go:buildBuild all Go packages
npm run typecheckTypeScript typecheck only

Release Binaries

Release binaries are built with the frontend embedded into the Go executable.

npm run binary:build

For a deployed release, keep the generated binary next to a .env file with BASIC_AUTH_USERNAME, BASIC_AUTH_PASSWORD, and any runtime options you need. The server will serve the embedded app first and fall back to dist/ only for local development builds.

Environment Variables

VariableDescriptionDefault
PORTHTTP listen port8080
BASIC_AUTH_USERNAMERequired usernamerequired
BASIC_AUTH_PASSWORDRequired passwordrequired
WORKSPACE_ROOTDefault workspace directorycwd
AUTOKILL_PORTKill existing process on port before starttrue
TUNNELAuto-start tunnel for public accesstrue
TUNNEL_ENGINEcloudflare (random URL via cloudflared) or bore (fixed port via bore.pub)cloudflare
TERMINAL_AI_MAX_LINESMax terminal lines sent to AI as context100
DEBUGEnable verbose debug loggingfalse
DEBUG_WATCHEREnable watcher-specific debug logs (requires DEBUG=true)false
SESSION_RESUME_MAX_RETRIESMax ACP session auto-restart attempts3
SESSION_RESUME_BASE_DELAYBase delay for exponential backoff on session restart500ms
SESSION_RESUME_MAX_DELAYMax delay cap for session restart backoff30s
LIVENESS_FAILURE_THRESHOLDConsecutive liveness failures before session restart2
RECONNECT_BASE_DELAYBase delay for reconnect backoff150ms
RECONNECT_MAX_DELAYMax delay cap for reconnect backoff30s
PTY_RING_BUFFER_SIZEPTY output ring buffer size1MB
PTY_INPUT_LOCK_TTLTTL for per-pane input soft lock during TUI operations2s
STREAM_COALESCE_WINDOWCoalesce window for visual stream batching
SESSION_GRACE_WINDOWGrace window for session reconnect

AI Agent Support

AgentACP SupportAuto-InstallFallback
OpenCodeNative (opencode acp)Built inPTY
Claude CodeVia adapter (claude-agent-acp)npm i -g @agentclientprotocol/claude-agent-acpPTY
Codex CLIVia adapter (codex-acp)npm i -g @zed-industries/codex-acpPTY
GeminiNative (gemini --experimental-acp)Built inPTY
PiVia adapter (pi-acp)npm i -g pi-acpPTY
AmpVia adapter (amp-acp)npm i -g amp-acpPTY
GitHub CopilotVia adapter (github-copilot-cli)npm i -g github-copilot-cliNone

ACP adapters are auto-installed when you select an agent for the first time. No manual setup needed.

Keyboard Shortcuts

ShortcutAction
Ctrl+BToggle sidebar
Ctrl+`Toggle terminal
Ctrl+Shift+GOpen git panel
Ctrl+Shift+LToggle chat panel
F1Show keyboard shortcuts
Ctrl+SSave file
Ctrl+Shift+IInline AI prompt (select code first)
F2Rename file (in explorer)
Right-clickContext menu (explorer, tabs)

Project Structure

cmd/server/ - Application entry point (autokill, config)
internal/
config/ - .env loading and validation
auth/ - Basic Auth middleware + session cookies
shells/ - OS-aware shell discovery
terminal/ - PTY session spawning and management
filesystem/ - File operations with path security (recursive copy)
watcher/ - Real-time file watcher (fsnotify)
git/ - Git CLI wrapper (status, log, branch, diff, stash, blame, check-ignore)
chat/
acp/ - ACP client (JSON-RPC 2.0 over stdio)
protocol.go - ACP message types and constants
client.go - JSON-RPC transport (request correlation, notifications)
adapter.go - Subprocess lifecycle + high-level ACP methods
acpinstall/ - Auto-install ACP adapters via npm/pip
agentconfig/ - Agent config file detection (models, providers)
agent.go - Unified ChatSession interface (ACP + PTY + permission handling)
pty_session.go - PTY fallback implementation
session_manager.go - Session lifecycle management
store.go - SQLite persistence (chat history, workspace state, recent projects)
httpapi/ - REST API + WebSocket handlers
server/ - HTTP assembly and static serving
tunnel/ - Tunnel subprocess lifecycle (bore, cloudflare)
bininstall/ - Binary auto-download (ffmpeg, cloudflared, bore)
browser/ - Browser tab management with about:blank support
frontend/src/
apps/ide/ - Web IDE entry (workspace, project picker)
config/ - Monaco editor setup (TS/JS diagnostics, Vue/Svelte languages)
components/
editor/ - Monaco editor, diff view, tabs with context menu
git/ - Git panel, status list, branch picker, stash, diff view
chat/ - Chat panel, messages, input, agent picker, permission dialog, queue, voice
browser/ - Browser panel, inspect overlay, element selection, hit-test
sidebar/ - Activity bar (with badge), file tree (with context menu), search
settings/ - Global settings panel for tunnel management and about info
terminal/ - Terminal panel (xterm.js), tabs per project
shared/ - Bottom nav, shortcuts help, context menu
stores/ - Zustand state (workspace, git, chat)
hooks/ - Custom hooks (git status, gutter, chat, layout, workspace persistence, visual stream, gestures)
terminalConnection.ts - WebSocket lifecycle for terminal sessions
terminalRegistry.ts - Terminal handle registry (write/paste for chat-to-terminal routing)
terminalIntegration.ts - Shell language detection and command sanitization

Recent Changes (ADR Compliance)

A major stability and robustness mission was completed across 18 commits, addressing session resilience, streaming backpressure, PTY robustness, visual streaming, and race safety. All 58 validation assertions pass.

Session Resume & Liveness (ADR-0004, ADR-0006)

  • ACP sessions auto-restart with configurable exponential backoff (SESSION_RESUME_MAX_RETRIES, SESSION_RESUME_BASE_DELAY, SESSION_RESUME_MAX_DELAY)
  • Liveness failure threshold triggers restart after consecutive failures (LIVENESS_FAILURE_THRESHOLD, default 2)
  • Reconnect delay configuration (RECONNECT_BASE_DELAY, RECONNECT_MAX_DELAY)
  • Dev-only crash endpoint for testing (POST /api/_debug/crash-agent, requires -tags debug build)
  • Mock ACP echo adapter for automated testing

Catch-up & Backpressure (ADR-0002, ADR-0003)

  • Full fetch_timeline response shape per ADR-0002 (epoch, reset, staleCursor, gap, window, hasOlder, hasNewer, endCursor)
  • Stale cursor detection and gap detection with frontend epoch change handling
  • Replay-on-subscribe for new subscribers
  • Prioritized backpressure — subscribers are not dropped on overflow
  • Reconnect with exponential backoff

PTY Robustness (ADR-0005)

  • TUI detection with regex and carryover buffer (handles split-across-reads)
  • Per-pane input soft lock with dedicated input_locked event (PTY_INPUT_LOCK_TTL)
  • Primary client for TUI snapshot (first subscriber wins)
  • @xterm/addon-serialize for TUI snapshots
  • Input locked/disabled UI in ChatInput

Visual Streaming (ADR-0001)

  • Pixel-based JPEG tile diff (MAD, not byte equality)
  • Adaptive quality tiers (4 tiers: scale 0.65–1.0, quality 45–72)
  • H264 NAL unit boundary parsing (Annex B start codes)
  • ffmpeg auto-download via internal/bininstall/
  • DataChannel input wiring in BrowserPanel (HTTP fallback)
  • Gesture mapping: tap, long press, two-finger scroll, pinch zoom
  • Input throttling (mouse 8ms, key 25ms, text 100ms)
  • Resource cleanup with sync.Once and send-on-closed-channel guard
  • DEFAULT_URL changed to about:blank
  • Vanilla ICE gathering: GatheringCompletePromise ensures all ICE candidates are embedded in the answer SDP before sending
  • DataChannel role fix: server receives client's DataChannel via OnDataChannel() instead of creating a conflicting one
  • CDP screencast deadlock fix: frame acknowledgment made asynchronous to avoid Playwright CDPSession lock contention

Race Safety & E2E Validation

  • Zero data races across all packages (CGO_ENABLED=1 go test -race)
  • WebSocket concurrent write protection via per-connection mutex in chat handler
  • Full E2E chat lifecycle validated
  • Multi-client sync, reconnect-with-grace, backpressure recovery validated
  • PTY collaborative typing and TUI snapshot validated
  • WebRTC visual streaming E2E validated (frames render, input works, navigation updates tiles)

New Frontend Hooks

  • useVisualStream — WebRTC DataChannel visual streaming
  • useGestures — touch gesture recognition
  • SerializeAddon — TUI snapshot serialization
  • Input locked/disabled UI states

Development

# Run Go server (backend only)
npm run server
# Run frontend dev server (hot reload, proxy to Go backend)
npm run dev
# Run all checks
npm run check
# Run all Go tests
npm run go:test
# Build everything for production
npm run start

About

No description, website, or topics provided.

Resources

Stars

13 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages