~/.canvas/electron/agents/<agent-name>/%APPDATA%/Canvas/electron/agents/<agent-name>/YYYY-MM-DDTHH-mm-ss-conversation.json# Clone the repository
git clone <repository-url>
cd canvas
# Install dependencies
npm install
# Development mode
npm run dev
# Build for production
npm run build
# Package the application
npm run package
npm run dev - Start both main and renderer in development modenpm run dev:main - Build and run main process onlynpm run dev:renderer - Start Vite dev server for renderernpm run build - Build both main and renderer for productionnpm run build:main - Build main process onlynpm run build:renderer - Build renderer onlynpm run lint - Run ESLint on all TypeScript filesnpm run type-check - Run TypeScript type checkingnpm run build
Tag and push (tag should match our versioning convention):
git tag v2.0.0-alpha.1
git push origin v2.0.0-alpha.1
GitHub Actions will build + create a Release with the installers.
npm run package
This creates platform-specific packages in the release/ directory:
Canvas UI can run scripts in response to server-side WebSocket events (context URL changes, tree mutations, document updates, etc.). Useful for triggering external tools like rclone mounts, notifications, or CI pipelines.
Setup: create executable scripts in ~/.canvas/hooks/ (~/Canvas/hooks/ on Windows) named after the event they handle:
# Create hooks directory
mkdir -p ~/.canvas/hooks
# Create a hook for context URL changes
cat > ~/.canvas/hooks/context.url.set << 'EOF'
#!/bin/bash
URL=$(cat | jq -r '.url')
# Note, stdin is a pipe, once processed its gone
# You can capture the raw stdin with stdin=$(cat)
echo "[$(date)] context url changed to: $URL"
EOF
chmod +x ~/.canvas/hooks/context.url.set
context.url.set, workspace.tree.path.inserted)chmod +x enables the hook, remove the flag to disable$1, JSON payload on stdin~/.canvas/logs/hooks.loghooks.enabled: false in ~/.canvas/config/canvas-ui.json to disable globallyAvailable events are listed in the WebSocket API docs.
AGPL-3.0-or-later - see LICENSE file for details.