The `legalwork-server` package: a filesystem-backed HTTP API that remote LegalWork clients talk to, independent of the desktop app. Ships as a compiled binary (no Bun at runtime), configured from `~/.config/legalwork/server.json` or flags (workspace, approval mode, host/port 8787). Documents the full endpoint surface — workspace config/events, plugin/skill/MCP/command CRUD, token management with owner/collaborator/viewer scopes, inbox/outbox artifact upload, JIT file sessions with batch read/write, and the opencode / opencode-router proxy routes — plus the manual-vs-auto approval flow and env toggles for inbox/outbox/sandbox. When integrating a client against the server, or wiring/securing a remote workspace — this is the API contract and its auth scopes.
LegalWork Server
Filesystem-backed API for LegalWork remote clients. This package provides the LegalWork server layer described in apps/app/pr/legalwork-server.md and is intentionally independent from the desktop app.
Quick start
npm install -g legalwork-server
legalwork-server --workspace /path/to/workspace --approval auto
legalwork-server ships as a compiled binary, so Bun is not required at runtime.
Or from source:
pnpm --filter legalwork-server dev -- \
--workspace /path/to/workspace \
--approval auto
The server logs the client token and host token on boot when they are auto-generated.
Add --verbose to print resolved config details on startup. Use --version to print the server version and exit.
Config file
Defaults to ~/.config/legalwork/server.json (override with LEGALWORK_SERVER_CONFIG or --config).
{
"host": "127.0.0.1",
"port": 8787,
"approval": { "mode": "manual", "timeoutMs": 30000 },
"workspaces": [
{
"path": "/Users/susan/Finance",
"name": "Finance",
"workspaceType": "local",
"baseUrl": "http://127.0.0.1:4096",
"directory": "/Users/susan/Finance"
}
],
"corsOrigins": ["http://localhost:5173"]
}
Environment variables
LEGALWORK_SERVER_CONFIGpath to config JSONLEGALWORK_HOST/LEGALWORK_PORTLEGALWORK_TOKENclient bearer tokenLEGALWORK_HOST_TOKENhost approval tokenLEGALWORK_APPROVAL_MODE(manual|auto)LEGALWORK_APPROVAL_TIMEOUT_MSLEGALWORK_WORKSPACES(JSON array or comma-separated list of paths)LEGALWORK_CORS_ORIGINS(comma-separated list or*)LEGALWORK_OPENCODE_BASE_URLLEGALWORK_OPENCODE_DIRECTORYLEGALWORK_OPENCODE_USERNAMELEGALWORK_OPENCODE_PASSWORD
Token management (scoped tokens):
LEGALWORK_TOKEN_STOREpath to token store JSON (default: alongsideserver.json)
File injection / artifacts:
LEGALWORK_INBOX_ENABLED(1|0)LEGALWORK_INBOX_MAX_BYTES(default: 50MB, capped)LEGALWORK_OUTBOX_ENABLED(1|0)
Sandbox advertisement (for capability discovery):
LEGALWORK_SANDBOX_ENABLED(1|0)LEGALWORK_SANDBOX_BACKEND(docker|container|none)
Endpoints
GET /healthGET /statusGET /capabilitiesGET /whoamiGET /workspacesGET /workspace/:id/configPATCH /workspace/:id/configGET /workspace/:id/eventsPOST /workspace/:id/engine/reloadGET /workspace/:id/pluginsPOST /workspace/:id/pluginsDELETE /workspace/:id/plugins/:nameGET /workspace/:id/skillsPOST /workspace/:id/skillsGET /workspace/:id/mcpPOST /workspace/:id/mcpDELETE /workspace/:id/mcp/:nameGET /workspace/:id/commandsPOST /workspace/:id/commandsDELETE /workspace/:id/commands/:nameGET /workspace/:id/auditGET /workspace/:id/exportPOST /workspace/:id/import/previewPOST /workspace/:id/import
Token management (host/owner auth):
GET /tokensPOST /tokens(body:{ "scope": "owner"|"collaborator"|"viewer", "label"?: string })DELETE /tokens/:id
Inbox/outbox:
POST /workspace/:id/inbox(multipart upload into.opencode/legalwork/inbox/)GET /workspace/:id/artifactsGET /workspace/:id/artifacts/:artifactIdPOST /workspace/:id/files/sessionsPOST /files/sessions/:sessionId/renewDELETE /files/sessions/:sessionIdGET /files/sessions/:sessionId/catalog/snapshotGET /files/sessions/:sessionId/catalog/eventsPOST /files/sessions/:sessionId/read-batchPOST /files/sessions/:sessionId/write-batchPOST /files/sessions/:sessionId/ops
Toy UI (static assets served by the server):
GET /uiGET /w/:id/uiGET /ui/assets/*
OpenCode proxy:
GET|POST|... /opencode/*GET|POST|... /w/:id/opencode/*
OpenCode Router proxy:
GET|POST|... /opencode-router/*GET|POST|... /w/:id/opencode-router/*
Auth policy:
GET /opencode-router/healthrequires client auth.- All other
/opencode-router/*endpoints require host/owner auth.
Approvals
All writes are gated by host approval.
Host APIs accept either:
X-LegalWork-Host-Token: <token>(legacy host token), orAuthorization: Bearer <token>where the token scope isowner.
Approvals endpoints:
GET /approvalsPOST /approvals/:idwith{ "reply": "allow" | "deny" }
Set LEGALWORK_APPROVAL_MODE=auto to auto-approve during local development.