A CSV viewer and editor designed equally for human users and AI agents.
Built with Electrobun, React, Vite, Tailwind, shadcn/ui, and Papa Parse for CSV handling.
Humans get a familiar spreadsheet grid. Agents get a structured CLI with JSON output. Both work on the same files.
| Decision | Choice |
|---|---|
| Human UI | Spreadsheet grid — click cells, arrow keys, inline edit |
| Agent interface | CLI with JSON output always (--pretty optional for humans in terminal) |
| CLI modes | Headless — operate on a file directly; Attach — route to the GUI session that has the file open |
| Attach routing | By absolute file path |
| Headers | Row 1 is column names by default (--no-header for raw indices) |
| Conflicts | Last write wins; mutating responses include the previous value |
| Persistence | Headless: immediate write-through. GUI open: edit buffer until Save (⌘S) or save CLI |
ElectroBun bundles the GUI; the CLI runs as plain Bun. Two entrypoints, one shared core:
src/
├── core/ # CSV engine (Papa Parse wrapper), schema (shared)
├── cli/index.ts # headless + attach client → JSON stdout
├── bun/index.ts # ElectroBun main process, GUI + attach server
└── mainview/ # React + Vite spreadsheet grid UI
GUI — bun start or the packaged .app
CLI — bun run cli -- <command> --file path.csv
Attach mode — when the GUI has a file open, the Bun process exposes a local HTTP server and registers open files in ~/.csv007/sessions.json. The CLI looks up the session by file path and sends commands to the in-memory grid state.
GUI
- Open a CSV (file dialog or drag-and-drop)
- Spreadsheet grid with header row
- Click/keyboard cell editing
CLI commands (JSON out)
schema— column namesrows --limit --offset— read dataget --column --row— single cellset --column --row --value— single celladd-row,delete-rowsave— write edit buffer to disk (when file is open in GUI)status— whether the app is running and which file is open (no--file)
Headless mode writes mutations directly to disk. When the file is open in the app, mutations update the in-memory buffer; use Save (⌘S) or save to persist.
Both modes use --file path.csv. When that file is open in the app, CLI commands attach automatically via ~/.csv007/sessions.json.
Out of v1: undo, multi-file tabs, add/delete columns, type coercion, large-file streaming.
bun run cli -- status
bun run cli -- open --file ./output.csv
bun run cli -- schema --file fixtures/sample.csv
bun run cli -- rows --file fixtures/sample.csv --limit 2
bun run cli -- get --file fixtures/sample.csv --row 0 --column name
bun run cli -- set --file fixtures/sample.csv --row 0 --column name --value "Alice"
bun run cli -- add-row --file fixtures/sample.csv --values '{"name":"Dan","email":"dan@example.com","city":"NYC"}'
bun run cli -- delete-row --file fixtures/sample.csv --row 1
bun run cli -- save --file fixtures/sample.csvBuild the .app once, then agents can open files in the GUI and mutate via attach:
bun run build
# Agent creates a CSV, opens it in csv007, then revises
bun run cli -- open --file ./output.csv
bun run cli -- set --file ./output.csv --row 0 --column status --value done
bun run cli -- save --file ./output.csvIf the app is not running, open launches csv007.app automatically. Default path: build/dev-macos-arm64/csv007-dev.app. Override with ~/.csv007/config.json:
{ "appPath": "/Applications/csv007.app" }Human GUI development still uses bun run dev:hmr; agent testing targets the built .app.
bun install
bun start # build + launch GUI
bun run dev:hmr # launch with Vite HMR on :5173Open a CSV, click cells to edit — use File → Save (⌘S) to write changes to disk. Unsaved changes are marked with • in the title bar; you'll be prompted on close.
Shared CSV core, full headless CLI, GUI spreadsheet grid, attach mode, and CLI open (agent → GUI handoff) are implemented.