Skip to content

SDS-Mode/trayce

Repository files navigation

trayce logo

trayce

A hand-drawn sketch pad for Claude Code sessions.

Draw in your browser. Pick a Claude Code session. Submit. Claude sees your sketch as a PNG alongside your prompt.

CI License: MIT Runtime: Bun Platforms

Press ✏️ → Send ✉️ → Claude reads the image.


Tip

Use a tablet with a stylus for natural sketching, or a mouse for quick wireframes. Each Claude session gets its own isolated canvas that persists across page reloads.


🎯 Why trayce?

Sketch a UI and ask Claude to implement it. Pin a screenshot — drop numbered annotations, submit, get per-pin replies. Draw a diagram and ask Claude to build the architecture. Iterate on a render — Claude can push images and annotations back to your canvas.

Text prompts struggle with spatial intent. A quick sketch communicates layout, hierarchy, and motion in a single frame — things that would take paragraphs to describe. Structured annotations close the loop in the other direction: Claude resolves your pins by ID, replies inline, and pushes its own annotations on rendered output for a real review cycle.

📑 Table of contents

🚀 Quick start

Runs on Linux, macOS, and WindowsBun is the only prerequisite.

# 1. Install
git clone https://github.com/SDS-Mode/trayce.git
cd trayce
bun install
bun run build:client

# 2. Start the server
bun run start
# → [trayce] Open: http://localhost:9740?token=abc123…

Open the printed URL in your browser. Then connect a Claude Code session:

# From any project directory
bun run /path/to/trayce/scripts/setup.ts --label my-project
claude --dangerously-load-development-channels server:trayce

Draw something · select the session from the dropdown · click Submit (or press Ctrl + Enter).


✨ Features

🖌️ Five pressure brushes

Pen · Pencil · Marker · Watercolor · Highlighter. Full support for pressure, size 1–200 px, opacity, flow, and smoothing.

🪟 Multi-layer canvas

Up to 20 layers with blend modes (multiply, screen, overlay, …), per-layer opacity & visibility. Paste, drop, or pick images as transform layers.

💾 Session-scoped canvases

Each Claude session gets its own canvas, persisted to IndexedDB. Tab locking prevents collisions between browser tabs.

📍 Structured annotations

Place pins, text, or callouts on the canvas as a parallel layer above your sketch. Each one is a typed, addressable object with a status lifecycle (openaddressed / rejected / needs-clarification). Claude reads them by stable ID via two MCP tools (resolve_annotations, push_annotations) so review work stays trackable, not OCR'd.

🔗 Multi-session support

Connect multiple Claude Code sessions simultaneously. Pick the target from a dropdown, draw once, submit. Claude can also push images back via push_image for visual review loops.

📡 Live session data

Four side-panel tabs: Response, Transcript (tool calls), Usage (tokens + cost), Annotations (status, replies, delete + inline edit). Theme accent threads through pins/callouts so they match the rest of the UI.

⌨️ Keyboard shortcuts

Action Key Action Key
🖊️ Pen B ✋ Pan Space + drag · or middle-mouse drag
✏️ Pencil N 🔍 Zoom Scroll wheel
🖍️ Marker M ↔️ Size [ / ]
🎨 Watercolor W ↶ Undo / ↷ Redo Ctrl + Z / Ctrl + Y
🖌️ Highlighter H 📤 Submit Ctrl + Enter
📍 Annotate mode A ⎋ Exit annotate Esc

While Annotate mode is active: T text · P pin · C callout. Brush shortcuts are suppressed so accidental keystrokes don't draw.


🔌 Setup

🟢 Automated (recommended)

bun run /path/to/trayce/scripts/setup.ts --label my-project

Cross-platform — works on Linux, macOS, and Windows. Writes the MCP config into your project's .mcp.json. POSIX bash equivalents exist in scripts/ with .sh suffixes, but the .ts versions are preferred and are what the bundled Claude Code plugin invokes.

Then start Claude with the channel flag:

claude --dangerously-load-development-channels server:trayce
Flag Effect
--label NAME Session label in the trayce dropdown (default: directory name)
--global Install to ~/.claude.json instead of project .mcp.json
--uninstall Remove trayce from MCP config

🔧 Manual

Add to .mcp.json in your project root (or ~/.claude.json for global):

{
  "mcpServers": {
    "trayce": {
      "command": "bun",
      "args": ["run", "/path/to/trayce/bridge/index.ts"],
      "env": {
        "TRAYCE_LABEL": "my-project"
      }
    }
  }
}

🛠️ Server management

bun run start                    # Start in foreground
bun run scripts/start.ts         # Start detached (reuses existing instance)
bun run scripts/stop.ts          # Stop detached server
bun run scripts/status.ts        # JSON status (running PID/URL or reason not running)
bun run dev                      # Development with hot reload

The server writes state to $TMPDIR/trayce/state.json (PID, port, token):

Platform Resolves to
🐧 Linux / 🍎 macOS /tmp/trayce/state.json
🪟 Windows %TEMP%\trayce\state.json

Bridges read this automatically — no manual token configuration needed. Restart failures and startup errors are captured in the sibling server.log.

🖼️ Canvas resolution

Choose from presets via the resolution dropdown:

  • 🖥️ 1920 × 1080 (1080p)
  • 🖥️ 2560 × 1440 (1440p)
  • 🖥️ 3840 × 2160 (4K)
  • 🟥 4096 × 4096 (square large)

Exports at full document resolution regardless of zoom level.

🎨 Theme & UI scaling

Click the gear icon (top-right) to pick a theme preset, accent color, font, and two independent scale sliders — text size and control size (80% – 150%, discrete 10% steps). Bigger panel text doesn't require a bloated toolbar; bigger tap targets don't require giant labels. Settings persist in localStorage. Annotation pins/callouts also follow the selected accent color.


⚙️ Environment variables

Copy .env.example.env for local overrides; the file ships with every supported var commented out at its default value.

Variable Default Description
🌐 TRAYCE_HOST 0.0.0.0 Bind address
🔢 TRAYCE_PORT 9740 Server port
🔑 TRAYCE_TOKEN (auto) Auth token (auto-generated if unset)
🚪 TRAYCE_NO_AUTH false Disable token authentication
📂 TRAYCE_SUBMISSIONS_DIR $TMPDIR/trayce/submissions PNG storage path
📄 TRAYCE_STATE_FILE $TMPDIR/trayce/state.json Server state file
🗂️ TRAYCE_CLIENT_DIR dist/client Where the client bundle lives (override for tests)
🏷️ TRAYCE_LABEL (directory name) Bridge-side: label shown in the session dropdown
📦 TRAYCE_CONTAINER (auto) 1 when running inside a container; auto-detected via /.dockerenv on Linux

Token priority: TRAYCE_NO_AUTH=true > TRAYCE_TOKEN > auto-generate.


📖 Go deeper

📚 Topic Description
🏗️ Architecture & data flow Three-process model, submission flow, WebSocket protocol
📦 Container deployment Running trayce in a container with podman / docker-compose
🔒 Security Token auth, rate limiting, CSP headers, size limits

🧪 Development

bun run dev                 # Server with --watch hot reload
bun run dev:client          # Client bundler in watch mode
bun test                    # Run all tests (bun's built-in test runner)
bun run typecheck           # tsc --noEmit
bun run check               # Biome lint + format

Note

Tests mirror source structure under tests/. Integration and e2e tests live alongside unit tests — including tests/e2e/client-boot.test.ts which runs on both Ubuntu and Windows CI runners.


📁 Project structure

trayce/
├── 🖥️  server/          Bun HTTP + WebSocket server
├── 🔌  bridge/          MCP Channel bridge (spawned per Claude session)
├── 🎨  client/          Browser canvas app (PixiJS + perfect-freehand)
│   ├── brushes/        Brush implementations (pen, pencil, marker, …)
│   └── tools/          Non-brush tools (image import, shapes, text, …)
├── 🔗  shared/          Protocol types, Zod schemas, cross-platform paths
├── 🧪  tests/           Bun test runner (mirrors source structure)
├── 📜  scripts/         Lifecycle scripts (.ts cross-platform + .sh POSIX)
└── 🧩  plugin/          Claude Code plugin with trayce skills

📦 Dependencies

Just three runtime dependencies — Bun provides HTTP, WebSocket, and file I/O natively.

📦 Package Purpose
pixi.js WebGL / WebGPU rendering and layer compositing
perfect-freehand Pressure-sensitive stroke outlines
@modelcontextprotocol/sdk MCP Channel protocol for the bridge

Plus zod for runtime validation at the WebSocket parse boundary.


📝 License

MIT © 2026 SDS-Mode

Built for Claude Code · Powered by Bun · Rendered with PixiJS

About

A hand-drawn sketch pad for Claude Code sessions. Draw in your browser, pick a session, submit — Claude sees your sketch as a PNG alongside your prompt.

Topics

Resources

License

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors