indifferentketchup 48a972e139 project-ux: archive/rename/Open-in-Gitea sidebar context menu, archived projects landing, create-project bootstrap with Gitea remote
Server:
- projects.status + projects.gitea_remote (additive) with CHECK ('open','archived')
- GET /api/projects?status=archived; PATCH /api/projects/:id (rename);
  POST /api/projects/:id/archive | unarchive; POST /api/projects/create
- POST /api/projects ON CONFLICT (path) DO UPDATE SET status='open': re-add
  of archived path restores existing row (preserves id + FKs); already-open
  path returns 409. Detected-repos picker now excludes only status='open'.
- New gitea.ts (createGiteaRepo + GiteaRepoExistsError) and
  project_bootstrap.ts (sanitize name, mkdir under PROJECT_ROOT_WHITELIST,
  git init -b main + first commit with -c user.name/email per-command, optional
  Gitea repo create + remote add + push; all via execFile, no shell).
- 3 new user-stream frames: project_archived, project_unarchived, project_updated.
- sidebar.ts now selects path + gitea_remote and filters status='open'.
- Gitea env added to config.ts (GITEA_BASE_URL, GITEA_USER, GITEA_TOKEN,
  GITEA_SSH_HOST).
- docker-compose.yml /opt mount flipped to rw so create-project can mkdir.
- auto_name.ts gate relaxed from `!== 1` to `< 1` (fires on every turn while
  chat name is empty, not only the first).

Web:
- ProjectSidebar: project rows use proper Radix ContextMenu; items Rename /
  Archive / Open in Gitea. Inline rename, archive confirm dialog.
  Removed obsolete handleRemove + DropdownMenu hack.
- Home: Add-existing + Create-new buttons; collapsible Archived Projects
  section with Restore.
- New CreateProjectModal: name + live folder preview, commit msg, Private/
  Public radio, create-Gitea-remote checkbox, toast on success/warnings.
- New projectUrls.ts giteaUrlFor() — uses gitea_remote when present,
  falls back to convention URL.
- 3 new event types in sessionEvents.ts with idempotent useSidebar handlers.
- SidebarProject extended with path + gitea_remote so Open-in-Gitea can
  resolve without a separate fetch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 02:51:59 +00:00
2026-05-14 19:24:50 +00:00
2026-05-14 19:24:50 +00:00
2026-05-14 19:24:50 +00:00
2026-05-14 19:24:50 +00:00
2026-05-14 19:24:50 +00:00
2026-05-14 19:24:50 +00:00
2026-05-14 19:24:50 +00:00
2026-05-14 19:24:50 +00:00

boocode

Self-hosted single-user developer chat app. v1: chat only.

Stack

  • Node 20, Fastify, postgres (porsager/postgres), ws, zod
  • React 18, Vite, TypeScript, Tailwind v4, shadcn/ui
  • Postgres 16
  • pnpm workspaces

Layout

  • apps/server — Fastify API + WebSocket + inference loop + file-read tools
  • apps/web — React frontend; served by Fastify in production, Vite in dev

Local dev

Requires Node 20, pnpm, Docker (for Postgres), and ripgrep.

# install
pnpm install

# bring up postgres only
cp .env.example .env
# edit POSTGRES_PASSWORD if you like; default DATABASE_URL points at the container
docker compose up -d boocode_db

# run server (port 3000) and web (port 5173) in two shells
DATABASE_URL=postgres://boocode:devpass@127.0.0.1:5500/boocode \
LLAMA_SWAP_URL=http://100.101.41.16:8401 \
pnpm dev:server

pnpm dev:web

The Vite dev server proxies /api and /api/ws/* to the Fastify backend with a synthetic Remote-User: sam header so the Authelia auth layer can be skipped during development.

Production

cd /opt/boocode
docker compose up --build -d

Binds to 100.114.205.53:9500 (Tailscale). Authelia is expected to gate the upstream and inject Remote-User. Postgres binds loopback only.

What v1 has

Project sidebar, sessions per project, chat with streaming responses over WebSocket, four file-read tools scoped to the project root (view_file, list_dir, grep, find_files), and a model picker driven by llama-swap's /v1/models.

What v1 does not have lives in v2 (terminal pane) and v3 (Coder pane).

Description
No description provided
Readme AGPL-3.0 7.7 MiB
Languages
TypeScript 94.1%
CSS 1.9%
JavaScript 1.2%
Shell 0.8%
Go 0.6%
Other 1.4%