Project Daemon
Maintenance note: Update this file when the project daemon API, servers, conat integration, or data directory layout changes.
Package: packages/project Entry point: packages/project/project.ts
Role
Each CoCalc project runs its own Node.js daemon process. This daemon:
Executes shell commands and code on behalf of the user
Manages Jupyter kernels
Handles file operations (read, write, list, move, delete)
Participates in real-time collaborative editing via conat sync
Exposes an API via conat for the hub and frontend to call
Runs code formatters (Prettier, Black, Go, Rust, R, etc.)
Manages Sage worksheet sessions
Optionally provides SSH access
Startup Flags
Network Servers
The project daemon starts three network services:
1. Hub TCP Server
Port: Dynamic, stored in
$DATA/.smc/hub-server.portPurpose: Legacy messaging protocol with hub
Security: Hub initiates connection; authenticates with secret token
Location:
packages/project/servers/hub/Message types:
heartbeat,project_exec,jupyter_execute,read_file_from_project,write_file_to_project,send_signal, etc.
2. Browser WebSocket Server
Port: Dynamic, stored in
$DATA/.smc/browser-server.portTechnology: Primus WebSocket with multiplex + responder plugins
Base path:
/{project_id}/raw/Location:
packages/project/servers/browser/Services: Direct WebSocket API, sync filesystem, WebSocket SFTP
3. HTTP API Server (localhost only)
Port: Dynamic, stored in
$DATA/.smc/api-server.portLocation:
packages/project/http-api/server.tsEndpoints:
/api/v1/read-text-file,/api/v1/write-text-fileAuth: Bearer token or Basic auth with secret token
Rate limit: 150 requests/minute
Conat Integration
The project connects to conat using either an API key or project secret token + project ID (via cookies).
Subject Routing
The compute_server_id is 0 for regular projects.
API Registration
Type definitions: packages/conat/project/api/ Implementations: packages/project/conat/api/
System API Methods
The system service handles core project operations:
| Method | Purpose |
|---|---|
ping() | Health check |
test() | API key scope validation |
version() | Get API version |
exec(opts) | Execute shell command |
signal(signal, pid|pids) | Send signal to process |
listing(path, hidden) | Directory listing |
deleteFiles(paths) | Delete files |
moveFiles(paths, dest) | Move files |
renameFile(src, dest) | Rename file |
realpath(path) | Resolve symlinks |
canonicalPaths(paths[]) | Normalize paths |
readTextFileFromProject(path) | Read text file |
writeTextFileToProject(path, content) | Write text file |
configuration(aspect) | Project capabilities |
jupyterExecute(opts) | Execute notebook cells |
listJupyterKernels() | List running kernels |
stopJupyterKernel(pid) | Terminate kernel |
terminate(service) | Terminate a service |
Editor API Methods
The editor service handles file editing operations:
| Method | Purpose |
|---|---|
formatterString() | Code formatting |
jupyterStripNotebook() | Strip notebook output |
jupyterRunNotebook() | Run notebook |
jupyterNbconvert() | nbconvert integration |
jupyterKernelLogo() | Get kernel logo |
jupyterKernels() | Kernel metadata |
newFile() | Create new file |
createTerminalService() | Create terminal |
printSageWS() | Sage worksheet to PDF |
Project Package Structure
Data Directory
The project stores runtime data in $DATA/.smc/ (default ~/.smc/):
| File | Purpose |
|---|---|
hub-server.port | Hub TCP port |
browser-server.port | Browser HTTP port |
api-server.port | Internal API port |
secret_token | Authentication token |
info.json | Project metadata |
session-id.txt | Unique session ID |
start-timestamp.txt | When project started |
sage_server/ | Sage server logs/pids/ports |
Environment Variables
| Variable | Purpose |
|---|---|
COCALC_PROJECT_ID | Project UUID |
COCALC_USERNAME | Project username (derived from project_id) |
COMPUTE_SERVER_ID | Compute server ID (0 for regular projects) |
HOME | Home directory (required) |
DATA | Data directory (required) |
Logging
Always use the structured logger in project code:
Do NOT use console.log in project code.