Web UI dashboard for a multi-repository workspace manager and task executer for Claude Code.
Provides a browser interface on localhost:3741 to view workspace status, TODO progress, reviews, git history, and trigger operations (init, execute, review, create-pr, etc.) that run Claude Code via Bun.spawn + claude -p --output-format stream-json. A separate WebSocket chat server runs on port 3742 for interactive Claude sessions.
This tool is under development through real usecases. The latest version breaks easily.
# Run from the ai-workspace root directory
bunx github:sters/ai-workspace-v2
# Or specify the path explicitly
bunx github:sters/ai-workspace-v2 /path/to/ai-workspace
# Or use an environment variable
AIW_WORKSPACE_ROOT=/path/to/ai-workspace bunx github:sters/ai-workspace-v2
# Force update to latest version (bunx users)
bunx github:sters/ai-workspace-v2 --self-update
# Development mode (hot reload)
bunx github:sters/ai-workspace-v2 --devThe UI starts on http://localhost:3741, chat server on http://localhost:3742.
AIW_WORKSPACE_ROOT is resolved in this order:
- CLI argument:
bunx github:sters/ai-workspace-v2 /path/to/ai-workspace - Environment variable:
AIW_WORKSPACE_ROOT - Current working directory
The root directory must contain workspace/ and repositories/ subdirectories. If they don't exist, you'll be prompted to create them.
Config and database are stored per-workspace under {workspaceRoot}/.ai-workspace/:
/path/to/ai-workspace/
.ai-workspace/
config.yml # per-workspace config
db.sqlite # per-workspace database
This ensures each workspace has isolated settings and operation history.
Three-tier config system (priority: env vars > config file > defaults):
- Config file:
{workspaceRoot}/.ai-workspace/config.yml(auto-created on first run)
Environment variables (all optional, override config file values):
| Variable | Default | Description |
|---|---|---|
AIW_WORKSPACE_ROOT |
cwd | ai-workspace root directory |
AIW_PORT |
3741 | Next.js server port |
AIW_CHAT_PORT |
3742 | WebSocket chat server port |
AIW_CLAUDE_PATH |
auto-detect | Custom Claude CLI path |
AIW_DISABLE_ACCESS_LOG |
false |
Silence Next.js dev access logs (also server.disableAccessLog in config.yml) |
The "Open in..." menu is configured via the openers field in config.yml:
openers:
- name: Editor (VSCode)
command: code {path}
- name: Terminal
command: open -a Terminal {path}
- name: Cursor
command: cursor {path}Legacy editor: and terminal: keys are auto-migrated into openers at runtime; you can keep them or replace them with the block above.
On every startup, ai-workspace syncs a small set of managed hooks into ${AIW_WORKSPACE_ROOT}/.claude/settings.local.json and writes the corresponding scripts under .claude/hooks/aiw-*.sh. Managed entries are identified by the aiw- command prefix; any user-authored hooks without that prefix are preserved as-is. Toggle each one in config.yml:
hooks:
sessionStartGitContext: true # SessionStart: inject `git branch` + `git status --short` as additionalContext
blockDangerousBash: true # PreToolUse(Bash): block `rm -rf /...`, `git push --force` (without --force-with-lease), `git reset --hard`suggest:
enabled: true # set false to disable the post-operation workspace-suggestion background jobNext.js 16 App Router with React 19, TypeScript strict mode, Tailwind CSS 4, and SWR for data fetching.
- Workspace state: API routes under
src/app/api/read workspace data directly from the filesystem (workspace/directory inAIW_WORKSPACE_ROOT). Core reading logic is insrc/lib/workspace/reader.ts. - Pipeline orchestration: Operations (init, execute, review, create-pr, autonomous, batch, search, etc.) are sequences of
PipelinePhases. Entry point:startOperationPipeline()insrc/lib/pipeline/orchestrator.ts. Pipeline definitions per operation type insrc/lib/pipelines/. Max 3 concurrent operations. Operations interrupted by a server shutdown are settled as failed on restart rather than resumed. - Claude Code execution: Spawns Claude Code processes via
Bun.spawnwithclaude -p --output-format stream-json(src/lib/claude/cli.ts). HandlesAskUserQuestionvia--resume {session_id}. - SQLite persistence: Per-workspace database in
{workspaceRoot}/.ai-workspace/db.sqliteviabun:sqlite. Events are buffered in memory and flushed every 5000ms or 50 events (src/lib/db/event-buffer.ts). - Configuration: Per-workspace config resolution (env vars > config file > defaults) in
src/lib/config/resolver.ts, cached onglobalThis. Workspace root determines the config directory viasrc/lib/config/workspace-dir.ts. - Parsers (
src/lib/parsers/): Extract structured data from markdown — TODO items, README metadata, review summaries, and stream-json log entries. - Web Push notifications (
src/lib/web-push/): Browser push notifications for operation completion events.
- SWR hooks (
src/hooks/): Auto-refreshing data fetching (10s for workspace list, 5s for detail). - SSE streaming (
use-sse.ts): Real-time operation output via/api/events?operationId=. - Operation persistence (
use-operation.ts): Active operation ID is stored in localStorage so navigating away and returning reconnects to the stream.
/— Dashboard listing all workspaces with search/new— New workspace creation/suggestions— Workspace suggestions/workspace/[name]— Workspace detail with tabs: Overview, TODOs, Reviews, History, Operations/workspace/[name]/todo— TODO management/workspace/[name]/review/[timestamp]— Individual review detail/workspace/[name]/chat/quick— Quick ask interface/workspace/[name]/chat/interactive— Full interactive chat with terminal/workspace/[name]/operations— Operations history/workspace/[name]/history— Git/operation history timeline/utilities— Utility hub:aiw-settings— Application settings viewer/editorclaude-auth— Claude authenticationclaude-settings— Claude settings browser (project / local / user scopes)claude-version— Claude version infomcp-servers— MCP server managementcheck-update— Update checkerrunning— Running operations monitor (also lists up to 50 most recent completed/failed operations)operation-prune— Operation cleanupworkspace-prune— Workspace cleanup
Claude configuration files and MCP server definitions are resolved relative to AIW_WORKSPACE_ROOT. If the root changes, the referenced paths change accordingly.
| Scope | Path | Description |
|---|---|---|
| project | ${AIW_WORKSPACE_ROOT}/.claude/settings.json |
Project settings (tracked in git) |
| local | ${AIW_WORKSPACE_ROOT}/.claude/settings.local.json |
Local overrides (not tracked in git) |
| user | ~/.claude/settings.json |
Global user settings |
MCP servers are loaded from two sources:
- Project scope:
${AIW_WORKSPACE_ROOT}/.mcp.json - Local scope:
~/.claude.jsonunderprojects[absolutePath].mcpServers(keyed by the absolute path ofAIW_WORKSPACE_ROOT)
These configurations can be viewed and edited from the Settings / MCP Servers page in the Web UI.
# Install dependencies
bun install
# Development with hot reload
bun run dev:hot
# Production build + start
bun run build && bun run start
# Lint (runs tsc --noEmit + eslint)
bun run lint
# Run all tests
bun run test
# Run tests in watch mode
bun run test:watch
# Run a single test file (--bun is required so bun:sqlite resolves)
bun --bun vitest run src/__tests__/lib/parsers/todo.test.tsTests use Vitest with jsdom environment, @testing-library/react, and @testing-library/jest-dom matchers. Test files live in src/__tests__/ mirroring the src/ structure.
bun run test # Run all tests
bun run test:watch # Watch mode
bun --bun vitest run <file> # Single file (plain `bunx vitest` fails to bundle bun:sqlite)- Next.js 16 (App Router) with React 19
- TypeScript (strict mode)
- Tailwind CSS 4 with shadcn/ui-style theme
- SWR for data fetching
- Monaco Editor (
@monaco-editor/react) for code/config editing - xterm.js (
@xterm/xterm) for terminal UI - Zod for request/runtime data validation
- react-markdown + remark-gfm for markdown rendering
- lucide-react for icons
- web-push for browser push notifications
- Vitest + @testing-library/react for testing
- Claude Code CLI (
claude -p --output-format stream-json) for headless execution