Skip to content

Instantly share code, notes, and snippets.

@skylarbpayne
Created January 22, 2026 01:21
Show Gist options
  • Select an option

  • Save skylarbpayne/d1a3428eb568e4d77b7c1ff15ad8c381 to your computer and use it in GitHub Desktop.

Select an option

Save skylarbpayne/d1a3428eb568e4d77b7c1ff15ad8c381 to your computer and use it in GitHub Desktop.
Motion Agent Platform v0 Design Doc

Motion Agent Platform v0 Design Doc

Date: 2026-01-22 Author: Palmer (assisted by Skylar) Status: Draft


1. Overview

Internal agentic coding platform for Motion engineers. Enables parallel workstreams with CLI-based coding agents (starting with Claude Code), accessible via mobile-optimized web UI.

Goals

  • Enable 2-3 Motion engineers to work with AI coding agents simultaneously
  • Mobile-first UX for following conversations and quick approvals
  • Extensible to support multiple CLI agents (Claude Code, OpenCode, etc.)
  • Self-hosted on Beelink via Tailscale

Non-Goals (v0)

  • Cloud infrastructure (Beelink only for now)
  • Slack integration
  • Complex RBAC beyond Tailscale auth
  • Advanced multi-agent orchestration

2. Architecture

┌─────────────────────────────────────────────────────────────────┐
│                        BEELINK SERVER                           │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────────┐  │
│  │ Claude Code │  │ Claude Code │  │ Claude Code (extensible)│  │
│  │ Session 1   │  │ Session 2   │  │ Session N               │  │
│  │ Clone: repo1│  │ Clone: repo2│  │ Clone: repoN            │  │
│  └─────────────┘  └─────────────┘  └─────────────────────────┘  │
│         │                │                     │                │
│         └────────────────┴─────────────────────┘                │
│                           │                                      │
│                   ┌───────▼───────┐                             │
│                   │  API Server   │                             │
│                   │   (Node.js)   │                             │
│                   └───────┬───────┘                             │
│                           │                                      │
│              ┌────────────┴────────────┐                        │
│              │                         │                        │
│       ┌──────▼─────┐           ┌──────▼─────┐                  │
│       │   SQLite   │           │  Tailscale │                  │
│       │   Database │           │   Access   │                  │
│       └─────────────┘           └───────────┘                  │
└─────────────────────────────────────────────────────────────────┘
                              │
                              │ HTTPS (Tailscale Tailnet)
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│                      WEB CLIENT (Mobile-First)                   │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │ Dashboard │ Sessions │ Create Task │ Settings           │    │
│  └─────────────────────────────────────────────────────────┘    │
└─────────────────────────────────────────────────────────────────┘

Component Details

Beelink Server

  • Intel/AMD processor with 32GB+ RAM
  • Runs API server and Claude Code sessions
  • Connected to Motion tailnet

API Server

  • Node.js/Express or Fastify
  • Manages sessions, messages, diffs
  • Communicates with Claude Code via STDIN/STDOUT or MCP

SQLite Database

  • Simple, file-based, no external dependencies
  • Stores users, sessions, messages, tasks

Tailscale

  • Authentication (who can access)
  • Network connectivity (HTTPS to Beelink)

3. Agent Interface Contract

Claude Code CLI is the reference implementation. The interface should support extensibility.

Core Interface

interface CodingAgent {
  // Lifecycle
  start(sessionId: string, repoPath: string, task: string): Promise<void>;
  send(message: string): Promise<AgentResponse>;
  stop(): Promise<void>;
  
  // State
  isRunning(): boolean;
  getConversation(): Message[];
  getDiff(): DiffResult | null;
  
  // Events
  onMessage(callback: (msg: Message) => void): void;
  onDiff(callback: (diff: DiffResult) => void): void;
  onComplete(callback: () => void): void;
}

interface AgentResponse {
  message: string;
  hasDiff: boolean;
  diff?: DiffResult;
  isComplete: boolean;
}

interface DiffResult {
  files: FileDiff[];
  summary: string;
}

interface FileDiff {
  path: string;
  additions: number;
  deletions: number;
  patch: string; // Unified diff format
}

Claude Code Integration

# Start Claude Code in session mode
claude --session-dir /sessions/{sessionId} --task "{task}"

# Or use MCP protocol (preferred for extensibility)
claude --mcp-server /path/to/mcp.sock

Extensibility Pattern

// AgentFactory creates agents based on type
class AgentFactory {
  create(type: 'claude-code' | 'opencode' | 'custom', config: AgentConfig): CodingAgent {
    switch (type) {
      case 'claude-code':
        return new ClaudeCodeAgent(config);
      case 'opencode':
        return new OpenCodeAgent(config);
      default:
        return new CustomAgent(config);
    }
  }
}

4. API Endpoints

Authentication

Method Endpoint Description
GET /api/health Health check
POST /api/auth/login Tailscale OAuth callback

Sessions

Method Endpoint Description
GET /api/sessions List user's sessions
POST /api/sessions Create new session
GET /api/sessions/:id Get session details
DELETE /api/sessions/:id End session, cleanup

Messages

Method Endpoint Description
GET /api/sessions/:id/messages Get conversation history
POST /api/sessions/:id/messages Send follow-up message
GET /api/sessions/:id/diff Get current diff
POST /api/sessions/:id/approve Approve and create PR
POST /api/sessions/:id/reject Reject, optionally provide feedback

Repos

Method Endpoint Description
GET /api/repos List available repos
POST /api/repos/:owner/:name/clone Request clone (admin)

Users

Method Endpoint Description
GET /api/users/me Get current user
GET /api/users List users (admin only)

Request/Response Examples

Create Session:

POST /api/sessions
{
  "repoOwner": "motion",
  "repoName": "backend-api",
  "task": "Add user authentication endpoint",
  "agentType": "claude-code"
}

Response (201):
{
  "sessionId": "sess_abc123",
  "status": "starting",
  "repoUrl": "https://github.com/motion/backend-api"
}

Send Message:

POST /api/sessions/sess_abc123/messages
{
  "content": "Can you also add rate limiting?"
}

Response (200):
{
  "messageId": "msg_xyz789",
  "content": "Sure, I'll add rate limiting to the endpoint.",
  "timestamp": "2026-01-22T01:10:00Z"
}

Get Diff:

GET /api/sessions/sess_abc123/diff

Response (200):
{
  "files": [
    {
      "path": "src/auth.ts",
      "additions": 45,
      "deletions": 3,
      "patch": "--- a/src/auth.ts\n+++ b/src/auth.ts\n@@ ... @@"
    }
  ],
  "summary": "Added JWT authentication with 45 lines added, 3 deleted"
}

5. Data Model (SQLite Schema)

-- Users (synced from Tailscale or GitHub OAuth)
CREATE TABLE users (
  id TEXT PRIMARY KEY,
  email TEXT UNIQUE NOT NULL,
  name TEXT,
  avatar_url TEXT,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  last_login_at DATETIME
);

-- Sessions
CREATE TABLE sessions (
  id TEXT PRIMARY KEY,
  user_id TEXT NOT NULL,
  repo_owner TEXT NOT NULL,
  repo_name TEXT NOT NULL,
  repo_path TEXT NOT NULL,
  agent_type TEXT DEFAULT 'claude-code',
  task TEXT NOT NULL,
  status TEXT DEFAULT 'starting',
  -- status: starting, running, waiting_approval, completed, rejected, error
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  FOREIGN KEY (user_id) REFERENCES users(id)
);

-- Messages
CREATE TABLE messages (
  id TEXT PRIMARY KEY,
  session_id TEXT NOT NULL,
  role TEXT NOT NULL,
  -- role: user, agent, system
  content TEXT NOT NULL,
  timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
  FOREIGN KEY (session_id) REFERENCES sessions(id)
);

-- Diffs (current state of changes)
CREATE TABLE diffs (
  id TEXT PRIMARY KEY,
  session_id TEXT NOT NULL UNIQUE,
  files_json TEXT NOT NULL,
  -- JSON array of FileDiff objects
  summary TEXT,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  FOREIGN KEY (session_id) REFERENCES sessions(id)
);

-- Tasks (for tracking work)
CREATE TABLE tasks (
  id TEXT PRIMARY KEY,
  user_id TEXT NOT NULL,
  title TEXT NOT NULL,
  description TEXT,
  session_id TEXT,
  status TEXT DEFAULT 'pending',
  -- status: pending, in_progress, approved, rejected, merged
  github_pr_url TEXT,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  FOREIGN KEY (user_id) REFERENCES users(id),
  FOREIGN KEY (session_id) REFERENCES sessions(id)
);

-- Repos (available for cloning)
CREATE TABLE repos (
  id TEXT PRIMARY KEY,
  owner TEXT NOT NULL,
  name TEXT NOT NULL,
  clone_url TEXT NOT NULL,
  is_cloned BOOLEAN DEFAULT FALSE,
  clone_path TEXT,
  last_synced_at DATETIME,
  UNIQUE(owner, name)
);

-- Indexes for performance
CREATE INDEX idx_sessions_user ON sessions(user_id);
CREATE INDEX idx_sessions_status ON sessions(status);
CREATE INDEX idx_messages_session ON messages(session_id);
CREATE INDEX idx_tasks_user ON tasks(user_id);

6. Mobile-First UI Design

Design Principles

  1. Mobile defaults: Design for phone first, expand for desktop
  2. Thumb-friendly: Large tap targets, bottom navigation
  3. Quick actions: Approve/reject prominent on mobile
  4. Offline-capable: PWA with caching for mobile use
  5. Responsive: Fluid layouts, not separate mobile/desktop sites

Core Views

1. Dashboard (Mobile)

┌─────────────────────────────────┐
│  Motion Agent Platform      ⚙️ │
├─────────────────────────────────┤
│  Active Sessions                │
│  ┌───────────────────────────┐  │
│  │ 📝 Add auth endpoint      │  │
│  │ 🔄 Running - 2 messages   │  │
│  └───────────────────────────┘  │
│  ┌───────────────────────────┐  │
│  │ 🔍 Fix bug in payments    │  │
│  │ ⏳ Waiting for approval   │  │
│  └───────────────────────────┘  │
│                                 │
│  + New Task                     │
│  └─────────────────────────────┘ │
│  Recent Activity                │
│  • PR merged: Add user profile  │
│  • Rejected: Refactor UI        │
└─────────────────────────────────┘

2. Session View (Mobile - Primary View)

┌─────────────────────────────────┐
│  ← Back                    ⚙️  │
├─────────────────────────────────┤
│  📝 Add auth endpoint          │
│  ━━━━━━━━━━━━━━━━━━━━━━━━━━    │
│                                 │
│  🤖 Agent:                     │
│  I'll start by reading the     │
│  current auth module to        │
│  understand the structure.     │
│                                 │
│  ─────────────────────────     │
│  You:                          │
│  Can you also add rate         │
│  limiting?                     │
│                                 │
│  ─────────────────────────     │
│  🤖 Agent:                     │
│  Sure! I'll add rate limiting  │
│  to the authentication...      │
│                                 │
│  ━━━━━━━━━━━━━━━━━━━━━━━━━━    │
│  3 files changed               │
│  [View Diff]                   │
│                                 │
├─────────────────────────────────┤
│  [Message Input...]       Send │
└─────────────────────────────────┘

3. Diff View (Mobile)

┌─────────────────────────────────┐
│  ← Back          [Approve] [R] │
├─────────────────────────────────┐
│  3 files changed, +45/-3 lines │
│                                 │
│  src/auth.ts               +45 │
│  src/middleware/auth.js     +0 │
│  tests/auth.test.ts         +0 │
│                                 │
│  ─────────────────────────     │
│  src/auth.ts                     │
│  @@ -1,10 +1,15 @@              │
│   1  import {                    │
│   2    jwt,                      │
│   3    { JwtPayload }            │
│   4  } from 'jsonwebtoken';      │
│   5  +import { RateLimiter       │
│   6  +} from 'express-rate-      │
│   7  +limit';                    │
│   8                              │
│   9  interface User {            │
│  10    id: string;               │
│  ...                             │
│                                 │
├─────────────────────────────────┤
│  [Reject with feedback]         │
└─────────────────────────────────┘

4. Create Task (Mobile - Simplified)

┌─────────────────────────────────┐
│  ← Cancel                 Create│
├─────────────────────────────────┤
│  New Task                       │
│  ━━━━━━━━━━━━━━━━━━━━━━━━━━    │
│                                 │
│  Repository                     │
│  [backend-api            ▼]     │
│                                 │
│  Task Description               │
│  ┌───────────────────────────┐  │
│  │ Add rate limiting to all  │  │
│  │ authentication endpoints. │  │
│  │ Use Redis for storage.    │  │
│  └───────────────────────────┘  │
│                                 │
│  Agent                          │
│  ( Claude Code (default) )      │
│                                 │
│  [Start Task]                   │
└─────────────────────────────────┘

Desktop Enhancements

Feature Mobile Desktop
Conversation Threaded Split-pane with diff
Diff review Horizontal scroll Side-by-side
Create task Simplified form Full form + preview
Dashboard Stacked cards Grid + filters
Navigation Bottom nav Sidebar

Component Library

Tech Stack:

  • React + TypeScript
  • Tailwind CSS (mobile-first)
  • shadcn/ui components
  • TanStack Query for data fetching
  • PWA with Vite PWA plugin

Key Components:

  • SessionCard - Dashboard item
  • ConversationThread - Message list
  • DiffViewer - Code diff display
  • FileTree - Repo navigation
  • CreateTaskForm - Task creation
  • BottomNav - Mobile navigation

7. Security Considerations

Authentication

  • Tailscale OAuth for Motion tailnet users
  • Simple email-based access (allowlist)
  • No complex RBAC in v0

Session Isolation

  • Separate clone per session (prevents cross-contamination)
  • Read-only file system where possible
  • Timeout for idle sessions (4 hours default)

Network

  • HTTPS only (via Tailscale HTTPS)
  • No external internet access from agent sessions
  • Audit logging of all actions

Data

  • SQLite with file-level encryption optional
  • Daily backups to encrypted volume
  • No sensitive data in logs

8. Implementation Roadmap

Phase 1: Foundation (Week 1)

  • Set up Beelink server
  • Install Claude Code CLI
  • Basic API server (Node.js + Express)
  • SQLite database schema
  • Tailscale HTTPS setup

Phase 2: Core Features (Week 2)

  • Session creation/lifecycle
  • Claude Code integration (STDIN/STDOUT)
  • Message history
  • Basic dashboard UI
  • User auth via Tailscale

Phase 3: Code Review (Week 3)

  • Diff capture and storage
  • Diff viewer UI
  • Approve/Reject workflow
  • PR creation (GitHub API)

Phase 4: Mobile Polish (Week 4)

  • Mobile-first CSS
  • Push notifications (optional)
  • PWA manifest
  • Testing on mobile devices

Phase 5: Stretch Goals

  • Multiple agent support (OpenCode)
  • Slack integration
  • Auto-trigger from issues
  • Advanced RBAC

9. Open Questions

  1. Claude Code License: Can Motion use Claude Code CLI commercially?
  2. GitHub Integration: PAT or GitHub App for PR creation?
  3. Rate Limits: Claude Code API limits per day?
  4. Monitoring: How to track agent usage/effectiveness?

10. References

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment