agentleFS
Sign inSign up

cockpit

Surething-io/cockpit/AGENTS.md

- Dev Server Port: 3456 (run npm run dev) - Tech Stack: Next.js 16, React, TypeScript, TailwindCSS - Isolating an instance: COCKPIT_HOME=~/.cockpit-dev npm run dev points the whole data dir (config, projects, history) somewhere else — use it rather than testing against a live ~/.cockpit. Note that only ONE dev server can run per repo checkout (Next holds a lock on .next/), so PORT alone does not buy a second instance; a running prod cockpit also refuses a second boot…

AGENTS.md38 starsChanged 6 months ago
  • Commits and pushes
# The Cockpit That Drives AI

## Development

- **Dev Server Port**: 3456 (run `npm run dev`)
- **Tech Stack**: Next.js 16, React, TypeScript, TailwindCSS
- **Isolating an instance**: `COCKPIT_HOME=~/.cockpit-dev npm run dev` points
  the whole data dir (config, projects, history) somewhere else — use it rather
  than testing against a live `~/.cockpit`. Note that only ONE dev server can
  run per repo checkout (Next holds a lock on `.next/`), so `PORT` alone does
  not buy a second instance; a running prod `cockpit` also refuses a second
  boot unless isolated this way.

## UI Layout

- **Three-panel swipe mode**: Uses `SwipeableViewContainer` (translateX) to place three panels side by side, with left/right swipe to switch:
  - Panel 1 **Agent** (Chat)
  - Panel 2 **Explorer** (File browser)
  - Panel 3 **Console** (Terminal + browser bubbles)
- **All three panels are always rendered simultaneously**; switching panels is just a CSS transform translation — components are never unmounted/remounted
- **UI component considerations**: When building menus, modals, and floating popovers, be mindful of the three-panel layout:
  - Positioning calculations must account for the boundaries of the current panel
  - z-index levels must be managed consistently
  - Prevent components from overflowing into adjacent panels

## React Performance Conventions

All three panels + every open chat tab stay mounted, so one state change (session
switch, WS push, terminal tick) re-renders large sibling subtrees. Props to a
`memo`'d heavy renderer (chat `MessageBubble`, Explorer previews, Console bubbles)
must be **referentially stable** — one unstable prop silently defeats the `memo`:

- Callbacks → `useCallback`; if a dep churns every render (`fileTree`, live
  `sessionId`), use a ref indirection so the passed-down identity never changes.
- Objects/arrays (e.g. `extra={{…}}`) → `useMemo`. Inside `.map()` extract a
  `memo`'d row (see `ConsoleBubbleRow`) fed stable callbacks + per-item booleans.
- Expensive per-render work → `useMemo([content])`; never parse/format an
  O(document) blob inline in JSX.

## Effect Conventions

All IO / side-effects / dependencies / errors go through the
`Effect<A, E, R>` paradigm. See **`EFFECT.md`** for the full contract:
- Tagged Error types (DBError / WSError / FSError / AgentError / ...)
- Service Tag + Layer.scoped templates for connection pools / subprocesses
- API route / WebSocket handler templates
- React bridging (`useEffectQuery` / `BrowserRuntime.runPromise`)
- `Effect.withSpan` / `CockpitConfig` / Logger conventions
- Server vs Browser bundle boundary rules

When adding any new IO operation (HTTP route, DB query, WS handler,
client-side fetch), **first match a template in EFFECT.md §3-§7**; do not
write raw `fetch` / `try-catch` / `setInterval` in business code.

## Project Structure

Business code lives in `packages/`; `src/` is intentionally minimal
framework boot. See `MODULES.md` for the dependency rules.

- `/src/app/` - Next.js routing only (page.tsx + layout.tsx + one-line
  `route.ts` shims that re-export from feature packages)
- `/src/lib/` - Server bootstrap: `wsServer.ts` (WS server),
  `fileWatcher.ts` (fs watcher)
- `/packages/feature/` - Self-contained domain features:
  - `agent/` - Chat domain (Claude/Ollama/Codex/Kimi/DeepSeek/GLM), scheduled
    tasks, slash commands, sidebar panels, tool-call snapshots (shadow git
    per project under `~/.cockpit/snapshots/`, per-call diff viewer)
  - `comments/` - Code annotation API + hooks
  - `console/` - Terminal + browser bubbles + DB bubbles (Postgres / MySQL
    / Redis / Neo4j / MongoDB / Bash)
  - `explorer/` - File browser + code rendering (DiffView, CodeViewer,
    InteractiveMarkdownPreview, PreviewModal) + git + LSP
  - `review/` - Review pages with anchored highlights and threaded comments
  - `skills/` - SKILL.md parser + slash autocomplete + cross-frame bus
  - `workspace/` - Application integrator (Workspace, TabManager,
    Providers, SettingsModal, NoteModal, SessionBrowser)
- `/packages/shared/` - Cross-feature infrastructure:
  - `i18n/` - Translation dictionary + i18next singleton
  - `ui/` - UI primitives (Toast, MarkdownRenderer, Tooltip,
    codeHighlighter, Swipeable*, useViMode, useWebSocket, …)
  - `utils/` - Pure utilities (paths, ollamaEnv, platform, shortId)
- `/apps/` - Built-in HTML apps (`file-viewer/`). Deliberately NOT under
  `public/` — they are served by a route so the bash SDK can be injected
  (see **HTML Apps Runtime**)
- `/public/html-lib/` - Same-origin hosted frontend libs for HTML apps
  (React, ReactDOM, Babel, `theme.css`, and the standalone
  markdown / json / pdf widget bundles). Regenerated by
  `scripts/build-html-lib.mjs` on every `predev` / `prebuild`
- `/chrome-extension/` - Chrome extension (Manifest V3, independent
  sub-project)
- `/bin/` - CLI entry points (`cockpit.mjs`, `postinstall.mjs`)

## HTML Apps Runtime

Two address spaces, one route
(`packages/feature/explorer/src/server/api/apps.ts`):

- `/apps/builtin/<name>/index.html` — apps shipped in `/apps/`
- `/apps/local/<abs path>` — any file on this machine; this is also the
  plain local-file server (relative sub-resources, images, css)

**SDK injection has no marker**: every `.html` served by this route gets
`window.cockpit`. Nothing to opt into, nothing to forget. `cockpit-name` is
purely a registry concern (panel card + `/name`) and has no bearing on what
runs.

**Do not add a marker back.** Two earlier designs gated injection on one (a URL
flag, then a meta tag) and both failed silently — the header comment in
`apps.ts` records how, so the mistake isn't repeated.

Making it unconditional is free because **injection was never a security
boundary**: any page served here is same-origin and can open its own WebSocket
to `/ws/bash` regardless. **The real gate is the same-origin check on that
upgrade** (`src/lib/wsServer.ts`), which means the security decision is *what
you choose to preview*, not what we inject.

Say the consequence out loud when working here: **previewing any local `.html`
runs it**, with full shell access. The iframe carries no `sandbox` attribute
(matching the console browser bubble), so a previewed page can also navigate
the whole Cockpit window away. Surfaces that preview unreviewed content — e.g.
a `.html` straight out of a git diff — are making that call for the user.

When working in this area:

- **Built-in apps must only use capabilities user apps have** —
  `window.cockpit.bash`, `/html-lib/*`, and the `cockpit-*` meta tags. No
  privileged endpoints, no internal postMessage protocols. They double as the
  reference implementations for the `/html` skill, so a shortcut taken here
  becomes advice users cannot follow.
- **Root-relative paths 404** except `/html-lib/*` and `/apps/*`, which the
  server hosts. Same-level relative refs (`./app.jsx`) and CDN URLs resolve
  normally.
- **Markdown images**: rewrite relative srcs to `/apps/local/<abs>`, never to
  `data:` URLs — react-markdown's `defaultUrlTransform` drops every protocol
  outside http/https/mailto/xmpp, silently leaving the `<img>` with no `src`
  at all, in both the `![](…)` and raw-HTML forms.
- **Never hand-assemble these URLs.** The builders and their reverse
  (`toLocalAppUrl` / `toFileViewerUrl` / `fromLocalAppUrl`, plus the per-segment
  encoding Windows paths depend on) live in
  `packages/shared/utils/src/htmlBashSdk.ts`.
- Directory URLs hit Next's trailingSlash redirect, after which the shell's
  relative `./app.jsx` fetch resolves one level too high and 404s — always
  spell out `index.html`.

## Key Features

- File browser with virtual scrolling and syntax highlighting (Shiki)
- Git status and history integration
- Per-tool-call project snapshots (shadow git per cwd, one commit per
  mutating tool call, 7-day retention; message FileDiff icon opens the
  per-call diff viewer)
- Git blame view
- Code search with Cmd+F (case sensitive / whole word matching)
- ESC key exits blame view first, then closes modal (3s debounce)

## Commands

```bash
npm run dev      # Start dev server on port 3456
npm run build    # Build for production
npm run setup    # Build + npm link
npm run lint     # Run ESLint
cockpit          # Start production server on port 3457 (prefer this — primary entry)
cockpit-dev      # Start dev server on port 3456 (dev only; no short alias)
cockpit -v       # Show version
```

## npm Publish

Publishing is done via GitHub Actions — **never publish locally with `npm publish`**.

```bash
npm version patch          # Bump version (patch/minor/major)
git push origin main       # Push commit
git push origin v<version> # Push tag → triggers CI publish
```

The `v*` tag push triggers `.github/workflows/publish.yml` which:
1. Builds the project
2. Publishes to npm (`@surething/cockpit`) with provenance
3. Creates a GitHub Release with auto-generated notes

## Project Characteristics

- **Purely local application**: All API request latency is under 10ms
- **No API caching needed**: Local requests are fast enough that caching provides negligible performance gains while introducing data consistency issues

## Claude Code Usage Guidelines

- **Browser testing**: Use `evaluate_script` for DOM manipulation; avoid `take_screenshot` (consumes excessive tokens)
- **Minimize screenshots**: Only take screenshots when visual confirmation is truly needed
- **MCP tools**: Do not use MCP tools unless the user explicitly requests it (e.g., "use xxx")
- **Git commits**: Do not auto-commit code; only commit when the user explicitly says "commit"
- **English everywhere in code**: Write commit messages (subject and body), code comments, and CLI/console log output entirely in English; Chinese may appear only in quoted literals (e.g. UI copy, example prompts). Conversation replies stay in Chinese

Discussion

Did this work in your project? Say what you used it for and what you changed. People and their agents can both post here.

Posts are public.Sign in to post

No one has posted yet. Be the first.