npm package: @newsails/veil-studio
Description: Visual IDE for Veil CLI agents — drag-and-drop canvas, real-time chat, and agent editor
Latest version: 1.0.1

# Veil Studio

Visual workflow IDE for VeilCLI — an LLM agent runner.  
Drag agents, sessions, tasks, memories, and data blocks onto an infinite canvas, wire them together, and watch everything run in real time.

---

## Features

- **Infinite canvas** — place any element type, wire ports, organize with zones and saved views
- **Real-time sync** — all board mutations broadcast to every connected client instantly
- **Live chat** — stream token-by-token responses from any agent session, directly in the canvas
- **External session monitoring** — sessions started by other apps or agent tools appear in Studio in real time, with live streaming, tool indicators, and user messages
- **File explorer** — browse, edit, and add project files to the board as elements
- **Custom elements** — drop a folder into `.veil-studio/elements/` to add any element type without rebuilding
- **No build step** — Express server is plain CommonJS; starts instantly

---

## Quick Start

```bash
# Install globally
npm install -g @newsails/veil-studio

# Run (from any directory — that directory becomes the workspace)
veil-studio
```

Open **http://localhost:4444**

> **Node ≥18 required** for running. Node 20 is only needed if building the frontend from source.

### CLI Options

```
veil-studio [options]

  --port,     -p  <number>  Studio port                  (default: 4444)
  --api,      -a  <url>     VeilCLI API base URL       (default: http://localhost:5050)
  --api-port, -ap <number>  VeilCLI port on localhost  (shortcut for --api)
  --project,  -d  <path>    Workspace directory          (default: cwd)
  --secret,   -s  <token>   VeilCLI API secret token
  --dev,      -D            Force dev mode
  --help,     -h            Show help
```

Positional shorthand: `veil-studio <port> [api] [project] [secret]`

### Run from source

```bash
npm install
node bin/veil-studio.js
# or
npm start
```

---

## Architecture

```
Browser (Nuxt 3 SPA — TypeScript, Pinia, TailwindCSS)
  │  Socket.IO   ← board mutations, chat, VeilCLI proxy
  │  REST /api/files/*  ← file system only
  ▼
Express server (port 4444) — Plain CommonJS, no build step
  ├── Socket.IO handlers    server/socket.js
  ├── REST routes           server/routes/files.js
  ├── SQLite (sync)         .veil-studio/studio.db
  ├── In-memory Maps        board state (elements, links, zones, views)
  └── WebSocket client  ──► VeilCLI /ws (port 5050)
                            real-time events for all sessions & tasks
```

**Key rules:**
- Browser **never** talks to VeilCLI directly — all calls proxied via Studio Socket.IO
- Board state is **server-authoritative** — clients never optimistically mutate
- Socket.IO for everything board/agent/chat; REST only for `/api/files/*`

---

## Environment Variables

| Variable | Default | Purpose |
|---|---|---|
| `STUDIO_PORT` | `4444` | Studio server port |
| `VEIL_API` | `http://localhost:5050` | VeilCLI base URL (auto-read from `.veil/settings.json`) |
| `VEIL_SECRET` | _(empty)_ | `X-Veil-Secret` auth header (auto-read from `.veil/settings.json`) |
| `PROJECT_DIR` | `process.cwd()` | Working directory (files, custom elements, DB) |

---

## Project Structure

```
VeilCLI_Studio/
├── server/                   Backend — plain CommonJS
│   ├── index.js              Entry: startup sequence, dev proxy, listen
│   ├── socket.js             All Socket.IO event handlers
│   ├── routes/files.js       REST /api/files/*
│   └── utils/
│       ├── config.js         All env/config resolution
│       ├── db.js             SQLite singleton + schema
│       ├── board-state.js    In-memory Maps + DB sync + broadcasts
│       ├── element-registry.js  55 built-in + custom type registry
│       ├── element-instances.js Running element instance Map
│       ├── veil-client.js  VeilCLI REST + SSE streaming wrapper
│       ├── veil-ws.js      Persistent WS to VeilCLI /ws
│       ├── session-watcher.js   Message-count baseline tracker
│       ├── socket-io.js      getIO()/setIO() singleton
│       ├── file-utils.js     Path-safe file operations
│       └── elements/         55 built-in element definitions
│
├── nuxt-app/                 Frontend — Nuxt 3, TypeScript, SPA
│   ├── stores/               board.ts · ui.ts · chat.ts
│   ├── composables/          useSocket · useBoard · useCamera · useChat
│   │                         useVeil · useElementRegistry · useFileExplorer
│   ├── components/           canvas/ · elements/ · sidebar/ · chat/
│   └── .output/              Production build (served by Express in prod)
│
└── docs/                     Full reference documentation
```

---

## Built-in Element Types (55)

| Category | Types |
|---|---|
| CLI | `agent` `agent-instance` `chat-view` `task` `skill` `memory` `todo-list` `custom-tool` |
| Data | `text` `rich-text` `code-block` `json-object` `file-reference` `image` `image-local` `url-card` `web-snapshot` |
| Research | `source-collection` `research-note` `comparison-table` `fact-claim` `question` `web-search-query` |
| Docs | `document-draft` `outline` `section` `template` |
| Dev | `diff-patch` `error-log` `test-case` |
| Thinking | `idea` `pro-con-list` `decision` `assumption` `constraint` `goal` `blocker` |
| PM | `project` `milestone` `status-update` |
| Comm | `chat-room` `message` `feedback-request` `approval-gate` |
| Flow | `generator` `processor` `splitter` `merger` `filter` `queue` |
| Org | `collapsible-group` `annotation` `label-tag` `divider` `primitive` |

---

## Custom Elements

Drop a folder in `.veil-studio/elements/<type>/` containing:

```
element.json       — metadata (type, name, icon, defaultWidth/Height, …)
index.js           — server-side factory: createInstance(context) → { getViewData, getPorts, actions }
vue-component.js   — frontend Vue component (receives viewData, elementId props; emits action)
```

Click **Reload Custom Elements** in the palette sidebar — no server restart needed. Custom types with the same name as a built-in **override** the built-in completely.

---

## Documentation

| Document | Contents |
|---|---|
| [`docs/README.md`](docs/README.md) | Architecture deep-dive, data flow, key decisions |
| [`docs/Server.md`](docs/Server.md) | All server modules, DB schema, element system reference |
| [`docs/SocketIO.md`](docs/SocketIO.md) | Every Socket.IO event — payloads, handlers, end-to-end flows |
| [`docs/UI.md`](docs/UI.md) | Stores, composables, canvas components, chat components |

---

## Production Build

When installed via `npm`, the pre-built frontend is included in the package (`nuxt-app/.output/public/`). The server auto-detects it and serves it statically.

To rebuild the frontend from source (requires Node 20):

```bash
npm run build
# runs scripts/build-ui.js → cd nuxt-app && nuxt build
```

The server auto-detects whether `nuxt-app/.output/public/` exists — if yes, production mode; if no, dev mode (spawns Nuxt dev automatically).