Skip to content

Commit ac75af6

Browse files
committed
Prepare v0.2.1 responsive binary release
1 parent 0efbf25 commit ac75af6

23 files changed

Lines changed: 860 additions & 145 deletions

.gitignore

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
node_modules/
2-
dist/
3-
.env
2+
dist/
3+
internal/webassets/dist/
4+
.env
45
coverage/
56
*.exe
67
/server

AGENTS.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ npm run go:test # go test ./...
1313
npm run test # vitest run --environment jsdom (frontend tests)
1414
npm run build # vite build (frontend only)
1515
npm run server:build # go build -o server ./cmd/server
16+
npm run binary:build # build frontend + embed assets into single Go binary
1617
```
1718

1819
### Dev workflow
@@ -68,7 +69,7 @@ go test ./internal/chat/ -run TestCreateAndListSessions
6869
| `hooks/` | Custom hooks |
6970
| `config/` | Monaco language setup (TS/JS diagnostics, Vue/Svelte) |
7071

71-
Vite builds two entry points: `frontend/index.html` (terminal) and `frontend/ide.html` (IDE). Output goes to `dist/`.
72+
Vite builds two entry points: `frontend/index.html` (terminal) and `frontend/ide.html` (IDE). Normal frontend output goes to `dist/`. Release binaries use `npm run binary:build`, which builds the frontend into `internal/webassets/dist/` and embeds it with the `embedassets` Go build tag.
7273

7374
## Key Facts for Agents
7475

README.md

Lines changed: 107 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,45 @@
1-
# 9ed
1+
<p align="center">
2+
<img src="docs/logo.svg" alt="9ed" width="420">
3+
</p>
24

3-
Browser-based IDE with terminal, git source control, AI chat (ACP + PTY), browser inspect, terminal↔chat integration, tunnel support, and responsive layout.
5+
<h1 align="center">9ed</h1>
46

5-
![Desktop - Explorer & Editor](docs/screenshots/desktop-explorer.png)
7+
<p align="center">
8+
<strong>One browser tab for code, terminals, git, agents, and live browser inspection.</strong>
9+
</p>
10+
11+
<p align="center">
12+
<a href="#quick-start">Quick Start</a>
13+
|
14+
<a href="#features">Features</a>
15+
|
16+
<a href="#release-binaries">Release Binaries</a>
17+
|
18+
<a href="#development">Development</a>
19+
</p>
20+
21+
<p align="center">
22+
<img alt="Go" src="https://img.shields.io/badge/Go-1.24+-00ADD8?style=flat-square&logo=go&logoColor=white">
23+
<img alt="React" src="https://img.shields.io/badge/React-18-61DAFB?style=flat-square&logo=react&logoColor=111827">
24+
<img alt="Terminal" src="https://img.shields.io/badge/PTY-xterm.js-f9e2af?style=flat-square">
25+
<img alt="Release" src="https://img.shields.io/badge/release-single_binary-94e2d5?style=flat-square">
26+
</p>
27+
28+
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.
29+
30+
It runs as a normal Go server during development and can also be shipped as a single embedded binary for releases.
31+
32+
## Why 9ed?
33+
34+
| Focus | What it gives you |
35+
|-------|-------------------|
36+
| Local-first control | Your workspace, terminal sessions, git operations, and browser tools stay behind your own server and Basic Auth. |
37+
| Agent-ready workflow | AI chat can see terminal context, route commands into the active terminal, and attach inspected browser elements to prompts. |
38+
| Portable delivery | Production builds can embed the frontend into the Go binary, leaving only the binary and `.env` to deploy. |
39+
40+
## Preview
41+
42+
![Desktop - Explorer and Editor](docs/screenshots/desktop-explorer.png)
643
![Desktop - Git Diff View](docs/screenshots/desktop-git-diff.png)
744

845
## Features
@@ -27,17 +64,17 @@ Browser-based IDE with terminal, git source control, AI chat (ACP + PTY), browse
2764
- Branch management: create, switch, delete, merge
2865
- Stash support: save, pop, apply, drop
2966
- Commit history with pagination
30-
- Diff view (Monaco DiffEditor, side-by-side) click any changed file to see diff
67+
- Diff view (Monaco DiffEditor, side-by-side) - click any changed file to see diff
3168
- Git gutter decorations (green=added, blue=modified, red=deleted)
3269
- File-level discard changes
3370
- Change count badge on activity bar icon
3471
- Untracked files show full content as added (green)
3572

3673
### AI Chat (ACP Protocol)
37-
- **ACP (Agent Client Protocol)** structured JSON-RPC 2.0 communication with AI agents
74+
- **ACP (Agent Client Protocol)** - structured JSON-RPC 2.0 communication with AI agents
3875
- Supports: OpenCode, Claude Code, Codex CLI, Gemini, Pi, Amp, GitHub Copilot
3976
- Auto-install ACP adapters (npm) when agent is selected
40-
- Dynamic model picker, mode/agent selector, thinking level all from ACP `configOptions`
77+
- Dynamic model picker, mode/agent selector, thinking level - all from ACP `configOptions`
4178
- Slash command autocomplete from `available_commands_update`
4279
- Streaming responses with markdown rendering
4380
- Tool call visualization (read, edit, search, execute) with collapsible details
@@ -46,13 +83,13 @@ Browser-based IDE with terminal, git source control, AI chat (ACP + PTY), browse
4683
- Diff view for file changes made by agent
4784
- Auto-title sessions from first message or agent-generated title
4885
- PTY fallback for agents without ACP adapter
49-
- **Permission dialog** approve/reject tool calls (ACP `session/request_permission`)
50-
- **Auto-approve mode** skip permission prompts for trusted environments
51-
- **Message queue** type and queue messages while agent is streaming
52-
- **@ file mentions** reference any project file with autocomplete (filename + directory path)
53-
- **Voice input** dictate messages via Web Speech API with microphone access handling
86+
- **Permission dialog** - approve/reject tool calls (ACP `session/request_permission`)
87+
- **Auto-approve mode** - skip permission prompts for trusted environments
88+
- **Message queue** - type and queue messages while agent is streaming
89+
- **@ file mentions** - reference any project file with autocomplete (filename + directory path)
90+
- **Voice input** - dictate messages via Web Speech API with microphone access handling
5491

55-
### Terminal Chat Integration
92+
### Terminal <-> Chat Integration
5693
- **Bidirectional terminal context**: AI agent receives live terminal scrollback as context
5794
- **Active terminal routing**: agent terminal commands execute directly in the active terminal session
5895
- **"Run in terminal" button**: shell code blocks in chat messages can be executed with one click
@@ -61,7 +98,7 @@ Browser-based IDE with terminal, git source control, AI chat (ACP + PTY), browse
6198
- **Terminal tabs per project**: terminal state persisted in workspace, survives navigation
6299

63100
### Browser Inspect (Element Inspector for AI)
64-
- **4-layer box model overlay**: margin, border, padding, content color-coded canvas rendering
101+
- **4-layer box model overlay**: margin, border, padding, content - color-coded canvas rendering
65102
- **Smart hit-test**: click any element in browser panel to inspect
66103
- **Rich tooltip**: shows tag, id, classes, dimensions, CSS properties
67104
- **Keyboard navigation**: Tab/Shift+Tab between elements, Escape to exit
@@ -73,11 +110,11 @@ Browser-based IDE with terminal, git source control, AI chat (ACP + PTY), browse
73110
![Mobile - Editor](docs/screenshots/mobile-editor.png)
74111

75112
### Responsive Layout
76-
- **Consistent state across all form factors** desktop, tablet, and mobile share the same Zustand state
77-
- **Desktop** (1024px): Full panel layout with resizable sidebar, editor, terminal, chat
78-
- **Tablet** (7681023px): Overlay sidebar and chat panels
113+
- **Consistent state across all form factors** - desktop, tablet, and mobile share the same Zustand state
114+
- **Desktop** (>=1024px): Full panel layout with resizable sidebar, editor, terminal, chat
115+
- **Tablet** (768-1023px): Overlay sidebar and chat panels
79116
- **Mobile** (<768px): Single-panel view with bottom navigation
80-
- Responsive layout mode changes preserve panel state no remounting or data loss
117+
- Responsive layout mode changes preserve panel state - no remounting or data loss
81118
- File/git click auto-switches to editor view on mobile/tablet
82119
- Floating save button on mobile/tablet
83120

@@ -102,7 +139,7 @@ Browser-based IDE with terminal, git source control, AI chat (ACP + PTY), browse
102139
- Cross-tab navigation via postMessage protocol
103140

104141
### Tunnel
105-
- Auto-start tunnel for public access no manual setup needed
142+
- Auto-start tunnel for public access - no manual setup needed
106143
- **Cloudflare** (default): Quick tunnel via `cloudflared`, generates random public URL
107144
- **Bore**: Fixed port tunnel via `bore.pub`, auto-installs binary
108145
- Toggle with `TUNNEL=true/false`, select engine with `TUNNEL_ENGINE=cloudflare|bore`
@@ -136,18 +173,29 @@ npm run start
136173
| `npm run dev` | Vite dev server (frontend hot reload) |
137174
| `npm run build` | Build frontend |
138175
| `npm run server:build` | Compile Go binary |
176+
| `npm run binary:build` | Build frontend and embed it into a single Go binary |
139177
| `npm run check` | TypeScript typecheck + Go vet |
140178
| `npm run go:test` | Run all Go tests |
141179
| `npm run go:build` | Build all Go packages |
142180
| `npm run typecheck` | TypeScript typecheck only |
143181

182+
## Release Binaries
183+
184+
Release binaries are built with the frontend embedded into the Go executable.
185+
186+
```bash
187+
npm run binary:build
188+
```
189+
190+
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.
191+
144192
## Environment Variables
145193

146194
| Variable | Description | Default |
147195
|----------|-------------|---------|
148196
| `PORT` | HTTP listen port | `8080` |
149-
| `BASIC_AUTH_USERNAME` | Required username | |
150-
| `BASIC_AUTH_PASSWORD` | Required password | |
197+
| `BASIC_AUTH_USERNAME` | Required username | required |
198+
| `BASIC_AUTH_PASSWORD` | Required password | required |
151199
| `MODE` | `simple` (terminal only) or `full` (IDE) | `simple` |
152200
| `WORKSPACE_ROOT` | Default workspace directory | cwd |
153201
| `AUTOKILL_PORT` | Kill existing process on port before start | `true` |
@@ -162,13 +210,13 @@ npm run start
162210

163211
| Agent | ACP Support | Auto-Install | Fallback |
164212
|-------|-------------|--------------|----------|
165-
| OpenCode | Native (`opencode acp`) | | PTY |
213+
| OpenCode | Native (`opencode acp`) | Built in | PTY |
166214
| Claude Code | Via adapter (`claude-agent-acp`) | `npm i -g @agentclientprotocol/claude-agent-acp` | PTY |
167215
| Codex CLI | Via adapter (`codex-acp`) | `npm i -g @zed-industries/codex-acp` | PTY |
168-
| Gemini | Native (`gemini --experimental-acp`) | | PTY |
216+
| Gemini | Native (`gemini --experimental-acp`) | Built in | PTY |
169217
| Pi | Via adapter (`pi-acp`) | `npm i -g pi-acp` | PTY |
170218
| Amp | Via adapter (`amp-acp`) | `npm i -g amp-acp` | PTY |
171-
| GitHub Copilot | Via adapter (`github-copilot-cli`) | `npm i -g github-copilot-cli` | |
219+
| GitHub Copilot | Via adapter (`github-copilot-cli`) | `npm i -g github-copilot-cli` | None |
172220

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

@@ -189,46 +237,46 @@ ACP adapters are auto-installed when you select an agent for the first time. No
189237
## Project Structure
190238

191239
```
192-
cmd/server/ Application entry point (autokill, config)
240+
cmd/server/ - Application entry point (autokill, config)
193241
internal/
194-
config/ .env loading and validation
195-
auth/ Basic Auth middleware + session cookies
196-
shells/ OS-aware shell discovery
197-
terminal/ PTY session spawning and management
198-
filesystem/ File operations with path security (recursive copy)
199-
watcher/ Real-time file watcher (fsnotify)
200-
git/ Git CLI wrapper (status, log, branch, diff, stash, blame, check-ignore)
242+
config/ - .env loading and validation
243+
auth/ - Basic Auth middleware + session cookies
244+
shells/ - OS-aware shell discovery
245+
terminal/ - PTY session spawning and management
246+
filesystem/ - File operations with path security (recursive copy)
247+
watcher/ - Real-time file watcher (fsnotify)
248+
git/ - Git CLI wrapper (status, log, branch, diff, stash, blame, check-ignore)
201249
chat/
202-
acp/ ACP client (JSON-RPC 2.0 over stdio)
203-
protocol.go ACP message types and constants
204-
client.go JSON-RPC transport (request correlation, notifications)
205-
adapter.go Subprocess lifecycle + high-level ACP methods
206-
acpinstall/ Auto-install ACP adapters via npm/pip
207-
agentconfig/ Agent config file detection (models, providers)
208-
agent.go Unified ChatSession interface (ACP + PTY + permission handling)
209-
pty_session.go PTY fallback implementation
210-
session_manager.go Session lifecycle management
211-
store.go SQLite persistence (chat history, workspace state, recent projects)
212-
httpapi/ REST API + WebSocket handlers
213-
server/ HTTP assembly and static serving
214-
tunnel/ Tunnel subprocess lifecycle (bore, cloudflare)
250+
acp/ - ACP client (JSON-RPC 2.0 over stdio)
251+
protocol.go - ACP message types and constants
252+
client.go - JSON-RPC transport (request correlation, notifications)
253+
adapter.go - Subprocess lifecycle + high-level ACP methods
254+
acpinstall/ - Auto-install ACP adapters via npm/pip
255+
agentconfig/ - Agent config file detection (models, providers)
256+
agent.go - Unified ChatSession interface (ACP + PTY + permission handling)
257+
pty_session.go - PTY fallback implementation
258+
session_manager.go - Session lifecycle management
259+
store.go - SQLite persistence (chat history, workspace state, recent projects)
260+
httpapi/ - REST API + WebSocket handlers
261+
server/ - HTTP assembly and static serving
262+
tunnel/ - Tunnel subprocess lifecycle (bore, cloudflare)
215263
frontend/src/
216-
apps/ide/ IDE mode entry (workspace, project picker)
217-
apps/terminal/ Simple terminal mode
218-
config/ Monaco editor setup (TS/JS diagnostics, Vue/Svelte languages)
264+
apps/ide/ - IDE mode entry (workspace, project picker)
265+
apps/terminal/ - Simple terminal mode
266+
config/ - Monaco editor setup (TS/JS diagnostics, Vue/Svelte languages)
219267
components/
220-
editor/ Monaco editor, diff view, tabs with context menu
221-
git/ Git panel, status list, branch picker, stash, diff view
222-
chat/ Chat panel, messages, input, agent picker, permission dialog, queue, voice
223-
browser/ Browser panel, inspect overlay, element selection, hit-test
224-
sidebar/ Activity bar (with badge), file tree (with context menu), search
225-
terminal/ Terminal panel (xterm.js), tabs per project
226-
shared/ Bottom nav, shortcuts help, context menu
227-
stores/ Zustand state (workspace, git, chat)
228-
hooks/ Custom hooks (git status, gutter, chat, layout, workspace persistence)
229-
terminalConnection.ts WebSocket lifecycle for terminal sessions
230-
terminalRegistry.ts Terminal handle registry (write/paste for chatterminal routing)
231-
terminalIntegration.ts Shell language detection and command sanitization
268+
editor/ - Monaco editor, diff view, tabs with context menu
269+
git/ - Git panel, status list, branch picker, stash, diff view
270+
chat/ - Chat panel, messages, input, agent picker, permission dialog, queue, voice
271+
browser/ - Browser panel, inspect overlay, element selection, hit-test
272+
sidebar/ - Activity bar (with badge), file tree (with context menu), search
273+
terminal/ - Terminal panel (xterm.js), tabs per project
274+
shared/ - Bottom nav, shortcuts help, context menu
275+
stores/ - Zustand state (workspace, git, chat)
276+
hooks/ - Custom hooks (git status, gutter, chat, layout, workspace persistence)
277+
terminalConnection.ts - WebSocket lifecycle for terminal sessions
278+
terminalRegistry.ts - Terminal handle registry (write/paste for chat-to-terminal routing)
279+
terminalIntegration.ts - Shell language detection and command sanitization
232280
```
233281

234282
## Development

docs/logo.svg

Lines changed: 49 additions & 0 deletions
Loading

frontend/ide.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<html lang="en">
33
<head>
44
<meta charset="UTF-8" />
5-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover, interactive-widget=resizes-content" />
66
<title>Web IDE</title>
77
</head>
88
<body>

frontend/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<html lang="en">
33
<head>
44
<meta charset="UTF-8" />
5-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover, interactive-widget=resizes-content" />
66
<title>Web Terminal</title>
77
</head>
88
<body>

frontend/src/apps/ide/main.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@ import ReactDOM from 'react-dom/client';
44
import '../../config/monacoSetup';
55
import '../../config/monacoLanguages';
66
import { IDEApp } from './IDEApp';
7+
import { installViewportVars } from '../../utils/viewport';
78
import '../../styles/ide.css';
89

10+
installViewportVars();
11+
912
ReactDOM.createRoot(document.getElementById('root')!).render(
1013
<React.StrictMode>
1114
<IDEApp />

0 commit comments

Comments
 (0)