Maru

January 15, 2026 Β· View on GitHub

A research assistant built with Moru sandbox and Claude Agent SDK.

https://github.com/user-attachments/assets/7e99b82d-9f9f-4664-97f8-eedd833ed5f4

Features

πŸ€– Multi-Agent Sessions

Run multiple Claude in parallel. Each agent gets its own dedicated Linux VM.

πŸ’¬ Native Message Format

Renders Claude Code's native message format. Not restricted message subset of Claude Agent SDK.

⚑ Real-time Streaming

See tool executions, thinking, and results in real-time

πŸ”„ Session Resume

Agents maintain session history. Resume sessions anytime

πŸ’Ύ Workspace Persistence

Workspaces are saved to storage and restored on session resume. Files and Claude session persist across sessions.

πŸ“ File Explorer & Editor

Browse and view files in the agent's workspace. Download files that the agent writes or edits.

Detail

  • Claude Code stores each chat session locally as newline-delimited JSON.
  • I reverse-engineered those JSONL message formats and turned them into JSON Schemas for reuse (see agent-schemas)
  • When a user sends a message, we boot a fresh Moru VM with a clean workspace; if it’s a resume, we restore the previous workspace and session JSONL into the VM
  • Inside the VM, the agent reads the message from stdin and calls the Claude Agent SDK query() function.
  • The backend tails the session JSONL file for new records and streams them to the frontend in near real time.
  • When the run completes, we sync the workspace to Google Cloud Storage (GCS) so it can be restored next time.

Try It

Cloud: maru.moru.io - Maru is BYOK (Bring Your Own Key), but your API key is not saved on our server.

Self-hosted: Follow the setup instructions below.

Getting Started (Self-hosted)

Prerequisites

  • Node.js 22+
  • PostgreSQL
  • Moru API Key (for sandbox execution)
  • GitHub OAuth App (for authentication)

Installation

  1. Clone and install dependencies:
git clone https://github.com/moru-ai/maru.git
cd maru
npm install
  1. Set up environment files:
cp apps/server/.env.example apps/server/.env
cp apps/frontend/.env.example apps/frontend/.env
cp packages/db/.env.template packages/db/.env
  1. Configure environment variables:

packages/db/.env

DATABASE_URL="postgresql://postgres:@127.0.0.1:5432/maru_dev"
DIRECT_URL="postgresql://postgres:@127.0.0.1:5432/maru_dev"

apps/server/.env

# Database
DATABASE_URL="postgresql://postgres:@127.0.0.1:5432/maru_dev"

# GitHub OAuth
GITHUB_CLIENT_ID=your_github_client_id
GITHUB_CLIENT_SECRET=your_github_client_secret

# Moru Sandbox (required)
MORU_API_KEY=your_moru_api_key
MORU_TEMPLATE_ID=maru-agent
MORU_SANDBOX_TIMEOUT_MS=3600000

# GCS Storage (optional, for workspace persistence)
GCS_BUCKET_NAME=your-bucket-name
GCS_KEY_FILE=./gcs-key.json

apps/frontend/.env

NEXT_PUBLIC_SERVER_URL="http://localhost:4000"
BETTER_AUTH_SECRET=your_secret_here
GITHUB_CLIENT_ID=your_github_client_id
GITHUB_CLIENT_SECRET=your_github_client_secret
DATABASE_URL="postgresql://postgres:@127.0.0.1:5432/maru_dev"
  1. Set up the database:
# Create database
psql -U postgres -c "CREATE DATABASE maru_dev;"

# Generate Prisma client and push schema
npm run generate
npm run db:push
  1. Build the agent template:
cd apps/agent
cp .env.example .env
# Add your MORU_API_KEY to .env

# Build and register the template
.venv/bin/python template.py
  1. Start development servers:
npm run dev

Development Commands

# Start dev servers (frontend + backend)
npm run dev

# Type checking
npm run check-types

# Linting
npm run lint

# Database operations
npm run db:push        # Push schema changes
npm run generate       # Generate Prisma client
npm run db:studio      # Open Prisma Studio

Rebuilding the Agent Template

After modifying any files in apps/agent/ (including Dockerfile, src/, or INSTRUCTIONS.md), you must rebuild the template:

cd apps/agent
.venv/bin/python template.py

This builds a new Docker image and registers it with Moru. The next sandbox will use the updated template.

License

MIT License