mirror of
https://github.com/multica-ai/multica.git
synced 2026-06-28 01:49:18 +02:00
Compare commits
1 Commits
codex/agen
...
agent/emac
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f5d8daf902 |
3
apps/docs/.gitignore
vendored
Normal file
3
apps/docs/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
.next/
|
||||
.source/
|
||||
node_modules/
|
||||
7
apps/docs/app/(home)/layout.tsx
Normal file
7
apps/docs/app/(home)/layout.tsx
Normal file
@@ -0,0 +1,7 @@
|
||||
import type { ReactNode } from "react";
|
||||
import { HomeLayout } from "fumadocs-ui/layouts/home";
|
||||
import { baseOptions } from "@/app/layout.config";
|
||||
|
||||
export default function Layout({ children }: { children: ReactNode }) {
|
||||
return <HomeLayout {...baseOptions}>{children}</HomeLayout>;
|
||||
}
|
||||
29
apps/docs/app/(home)/page.tsx
Normal file
29
apps/docs/app/(home)/page.tsx
Normal file
@@ -0,0 +1,29 @@
|
||||
import Link from "next/link";
|
||||
|
||||
export default function HomePage() {
|
||||
return (
|
||||
<main className="flex min-h-screen flex-col items-center justify-center gap-6 text-center px-4">
|
||||
<h1 className="text-4xl font-bold tracking-tight sm:text-5xl">
|
||||
Multica Documentation
|
||||
</h1>
|
||||
<p className="max-w-2xl text-lg text-fd-muted-foreground">
|
||||
The open-source managed agents platform. Turn coding agents into real
|
||||
teammates — assign tasks, track progress, compound skills.
|
||||
</p>
|
||||
<div className="flex gap-4">
|
||||
<Link
|
||||
href="/docs"
|
||||
className="inline-flex items-center rounded-md bg-fd-primary px-6 py-3 text-sm font-medium text-fd-primary-foreground transition-colors hover:bg-fd-primary/90"
|
||||
>
|
||||
Get Started
|
||||
</Link>
|
||||
<Link
|
||||
href="https://github.com/multica-ai/multica"
|
||||
className="inline-flex items-center rounded-md border border-fd-border px-6 py-3 text-sm font-medium transition-colors hover:bg-fd-accent"
|
||||
>
|
||||
GitHub
|
||||
</Link>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
4
apps/docs/app/api/search/route.ts
Normal file
4
apps/docs/app/api/search/route.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import { source } from "@/lib/source";
|
||||
import { createFromSource } from "fumadocs-core/search/server";
|
||||
|
||||
export const { GET } = createFromSource(source);
|
||||
47
apps/docs/app/docs/[[...slug]]/page.tsx
Normal file
47
apps/docs/app/docs/[[...slug]]/page.tsx
Normal file
@@ -0,0 +1,47 @@
|
||||
import { source } from "@/lib/source";
|
||||
import {
|
||||
DocsPage,
|
||||
DocsBody,
|
||||
DocsDescription,
|
||||
DocsTitle,
|
||||
} from "fumadocs-ui/page";
|
||||
import { notFound } from "next/navigation";
|
||||
import defaultMdxComponents from "fumadocs-ui/mdx";
|
||||
import type { Metadata } from "next";
|
||||
|
||||
export default async function Page(props: {
|
||||
params: Promise<{ slug?: string[] }>;
|
||||
}) {
|
||||
const params = await props.params;
|
||||
const page = source.getPage(params.slug);
|
||||
if (!page) notFound();
|
||||
|
||||
const MDX = page.data.body;
|
||||
|
||||
return (
|
||||
<DocsPage toc={page.data.toc}>
|
||||
<DocsTitle>{page.data.title}</DocsTitle>
|
||||
<DocsDescription>{page.data.description}</DocsDescription>
|
||||
<DocsBody>
|
||||
<MDX components={{ ...defaultMdxComponents }} />
|
||||
</DocsBody>
|
||||
</DocsPage>
|
||||
);
|
||||
}
|
||||
|
||||
export async function generateStaticParams() {
|
||||
return source.generateParams();
|
||||
}
|
||||
|
||||
export async function generateMetadata(props: {
|
||||
params: Promise<{ slug?: string[] }>;
|
||||
}): Promise<Metadata> {
|
||||
const params = await props.params;
|
||||
const page = source.getPage(params.slug);
|
||||
if (!page) notFound();
|
||||
|
||||
return {
|
||||
title: page.data.title,
|
||||
description: page.data.description,
|
||||
};
|
||||
}
|
||||
12
apps/docs/app/docs/layout.tsx
Normal file
12
apps/docs/app/docs/layout.tsx
Normal file
@@ -0,0 +1,12 @@
|
||||
import { DocsLayout } from "fumadocs-ui/layouts/docs";
|
||||
import type { ReactNode } from "react";
|
||||
import { baseOptions } from "@/app/layout.config";
|
||||
import { source } from "@/lib/source";
|
||||
|
||||
export default function Layout({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<DocsLayout tree={source.pageTree} {...baseOptions}>
|
||||
{children}
|
||||
</DocsLayout>
|
||||
);
|
||||
}
|
||||
3
apps/docs/app/global.css
Normal file
3
apps/docs/app/global.css
Normal file
@@ -0,0 +1,3 @@
|
||||
@import "tailwindcss";
|
||||
@import "fumadocs-ui/css/neutral.css";
|
||||
@import "fumadocs-ui/css/preset.css";
|
||||
25
apps/docs/app/layout.config.tsx
Normal file
25
apps/docs/app/layout.config.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
import type { BaseLayoutProps } from "fumadocs-ui/layouts/shared";
|
||||
import { BookOpen, Terminal, Rocket, Code } from "lucide-react";
|
||||
|
||||
export const baseOptions: BaseLayoutProps = {
|
||||
nav: {
|
||||
title: (
|
||||
<span className="font-semibold text-base">Multica Docs</span>
|
||||
),
|
||||
},
|
||||
links: [
|
||||
{
|
||||
text: "Documentation",
|
||||
url: "/docs",
|
||||
active: "nested-url",
|
||||
},
|
||||
{
|
||||
text: "GitHub",
|
||||
url: "https://github.com/multica-ai/multica",
|
||||
},
|
||||
{
|
||||
text: "Cloud",
|
||||
url: "https://multica.ai",
|
||||
},
|
||||
],
|
||||
};
|
||||
23
apps/docs/app/layout.tsx
Normal file
23
apps/docs/app/layout.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import "./global.css";
|
||||
import { RootProvider } from "fumadocs-ui/provider";
|
||||
import type { ReactNode } from "react";
|
||||
import type { Metadata } from "next";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: {
|
||||
template: "%s | Multica Docs",
|
||||
default: "Multica Docs",
|
||||
},
|
||||
description:
|
||||
"Documentation for Multica — the open-source managed agents platform.",
|
||||
};
|
||||
|
||||
export default function Layout({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<html lang="en" suppressHydrationWarning>
|
||||
<body>
|
||||
<RootProvider>{children}</RootProvider>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
90
apps/docs/content/docs/cli/installation.mdx
Normal file
90
apps/docs/content/docs/cli/installation.mdx
Normal file
@@ -0,0 +1,90 @@
|
||||
---
|
||||
title: CLI Installation
|
||||
description: Install the Multica CLI and start the agent daemon.
|
||||
---
|
||||
|
||||
## Installation
|
||||
|
||||
### Homebrew (macOS/Linux)
|
||||
|
||||
```bash
|
||||
brew tap multica-ai/tap
|
||||
brew install multica
|
||||
```
|
||||
|
||||
### Build from Source
|
||||
|
||||
```bash
|
||||
git clone https://github.com/multica-ai/multica.git
|
||||
cd multica
|
||||
make build
|
||||
cp server/bin/multica /usr/local/bin/multica
|
||||
```
|
||||
|
||||
### Download from GitHub Releases
|
||||
|
||||
If Homebrew is not available, download the binary directly:
|
||||
|
||||
```bash
|
||||
OS=$(uname -s | tr '[:upper:]' '[:lower:]') # "darwin" or "linux"
|
||||
ARCH=$(uname -m) # "x86_64" or "arm64"
|
||||
|
||||
# Normalize architecture name
|
||||
if [ "$ARCH" = "x86_64" ]; then
|
||||
ARCH="amd64"
|
||||
fi
|
||||
|
||||
# Get the latest release tag from GitHub
|
||||
LATEST=$(curl -sI https://github.com/multica-ai/multica/releases/latest \
|
||||
| grep -i '^location:' | sed 's/.*tag\///' | tr -d '\r\n')
|
||||
|
||||
# Download and extract
|
||||
curl -sL "https://github.com/multica-ai/multica/releases/download/${LATEST}/multica_${OS}_${ARCH}.tar.gz" \
|
||||
-o /tmp/multica.tar.gz
|
||||
tar -xzf /tmp/multica.tar.gz -C /tmp multica
|
||||
sudo mv /tmp/multica /usr/local/bin/multica
|
||||
rm /tmp/multica.tar.gz
|
||||
```
|
||||
|
||||
### Update
|
||||
|
||||
```bash
|
||||
multica update
|
||||
```
|
||||
|
||||
This auto-detects your installation method (Homebrew or manual) and upgrades accordingly.
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
# 1. Authenticate (opens browser for login)
|
||||
multica login
|
||||
|
||||
# 2. Start the agent daemon
|
||||
multica daemon start
|
||||
|
||||
# 3. Done — agents in your watched workspaces can now execute tasks on your machine
|
||||
```
|
||||
|
||||
`multica login` automatically discovers all workspaces you belong to and adds them to the daemon watch list.
|
||||
|
||||
## Verify
|
||||
|
||||
```bash
|
||||
multica daemon status
|
||||
```
|
||||
|
||||
Confirm:
|
||||
1. Status is `running`
|
||||
2. At least one agent is listed (e.g. `claude`, `codex`)
|
||||
3. At least one workspace is being watched
|
||||
|
||||
If the agents list is empty, install at least one AI agent CLI:
|
||||
- [Claude Code](https://docs.anthropic.com/en/docs/claude-code) (`claude`)
|
||||
- [Codex](https://github.com/openai/codex) (`codex`)
|
||||
|
||||
Then restart the daemon:
|
||||
|
||||
```bash
|
||||
multica daemon stop && multica daemon start
|
||||
```
|
||||
4
apps/docs/content/docs/cli/meta.json
Normal file
4
apps/docs/content/docs/cli/meta.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"title": "CLI & Daemon",
|
||||
"pages": ["installation", "reference"]
|
||||
}
|
||||
306
apps/docs/content/docs/cli/reference.mdx
Normal file
306
apps/docs/content/docs/cli/reference.mdx
Normal file
@@ -0,0 +1,306 @@
|
||||
---
|
||||
title: CLI Reference
|
||||
description: Complete command reference for the Multica CLI and agent daemon.
|
||||
---
|
||||
|
||||
The `multica` CLI connects your local machine to Multica. It handles authentication, workspace management, issue tracking, and runs the agent daemon that executes AI tasks locally.
|
||||
|
||||
## Authentication
|
||||
|
||||
### Browser Login
|
||||
|
||||
```bash
|
||||
multica login
|
||||
```
|
||||
|
||||
Opens your browser for OAuth authentication, creates a 90-day personal access token, and auto-configures your workspaces.
|
||||
|
||||
### Token Login
|
||||
|
||||
```bash
|
||||
multica login --token
|
||||
```
|
||||
|
||||
Authenticate by pasting a personal access token directly. Useful for headless environments.
|
||||
|
||||
### Check Status
|
||||
|
||||
```bash
|
||||
multica auth status
|
||||
```
|
||||
|
||||
Shows your current server, user, and token validity.
|
||||
|
||||
### Logout
|
||||
|
||||
```bash
|
||||
multica auth logout
|
||||
```
|
||||
|
||||
Removes the stored authentication token.
|
||||
|
||||
## Agent Daemon
|
||||
|
||||
The daemon is the local agent runtime. It detects available AI CLIs on your machine, registers them with the Multica server, and executes tasks when agents are assigned work.
|
||||
|
||||
### Start
|
||||
|
||||
```bash
|
||||
multica daemon start
|
||||
```
|
||||
|
||||
By default, the daemon runs in the background and logs to `~/.multica/daemon.log`.
|
||||
|
||||
To run in the foreground (useful for debugging):
|
||||
|
||||
```bash
|
||||
multica daemon start --foreground
|
||||
```
|
||||
|
||||
### Stop
|
||||
|
||||
```bash
|
||||
multica daemon stop
|
||||
```
|
||||
|
||||
### Status
|
||||
|
||||
```bash
|
||||
multica daemon status
|
||||
multica daemon status --output json
|
||||
```
|
||||
|
||||
Shows PID, uptime, detected agents, and watched workspaces.
|
||||
|
||||
### Logs
|
||||
|
||||
```bash
|
||||
multica daemon logs # Last 50 lines
|
||||
multica daemon logs -f # Follow (tail -f)
|
||||
multica daemon logs -n 100 # Last 100 lines
|
||||
```
|
||||
|
||||
### Supported Agents
|
||||
|
||||
The daemon auto-detects these AI CLIs on your PATH:
|
||||
|
||||
| CLI | Command | Description |
|
||||
|-----|---------|-------------|
|
||||
| [Claude Code](https://docs.anthropic.com/en/docs/claude-code) | `claude` | Anthropic's coding agent |
|
||||
| [Codex](https://github.com/openai/codex) | `codex` | OpenAI's coding agent |
|
||||
|
||||
You need at least one installed. The daemon registers each detected CLI as an available runtime.
|
||||
|
||||
### How It Works
|
||||
|
||||
1. On start, the daemon detects installed agent CLIs and registers a runtime for each agent in each watched workspace
|
||||
2. It polls the server at a configurable interval (default: 3s) for claimed tasks
|
||||
3. When a task arrives, it creates an isolated workspace directory, spawns the agent CLI, and streams results back
|
||||
4. Heartbeats are sent periodically (default: 15s) so the server knows the daemon is alive
|
||||
5. On shutdown, all runtimes are deregistered
|
||||
|
||||
### Configuration
|
||||
|
||||
Daemon behavior is configured via flags or environment variables:
|
||||
|
||||
| Setting | Flag | Env Variable | Default |
|
||||
|---------|------|--------------|---------|
|
||||
| Poll interval | `--poll-interval` | `MULTICA_DAEMON_POLL_INTERVAL` | `3s` |
|
||||
| Heartbeat interval | `--heartbeat-interval` | `MULTICA_DAEMON_HEARTBEAT_INTERVAL` | `15s` |
|
||||
| Agent timeout | `--agent-timeout` | `MULTICA_AGENT_TIMEOUT` | `2h` |
|
||||
| Max concurrent tasks | `--max-concurrent-tasks` | `MULTICA_DAEMON_MAX_CONCURRENT_TASKS` | `20` |
|
||||
| Daemon ID | `--daemon-id` | `MULTICA_DAEMON_ID` | hostname |
|
||||
| Device name | `--device-name` | `MULTICA_DAEMON_DEVICE_NAME` | hostname |
|
||||
| Runtime name | `--runtime-name` | `MULTICA_AGENT_RUNTIME_NAME` | `Local Agent` |
|
||||
| Workspaces root | — | `MULTICA_WORKSPACES_ROOT` | `~/multica_workspaces` |
|
||||
|
||||
Agent-specific overrides:
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `MULTICA_CLAUDE_PATH` | Custom path to the `claude` binary |
|
||||
| `MULTICA_CLAUDE_MODEL` | Override the Claude model used |
|
||||
| `MULTICA_CODEX_PATH` | Custom path to the `codex` binary |
|
||||
| `MULTICA_CODEX_MODEL` | Override the Codex model used |
|
||||
|
||||
### Self-Hosted Server
|
||||
|
||||
When connecting to a self-hosted Multica instance, point the CLI to your server before logging in:
|
||||
|
||||
```bash
|
||||
export MULTICA_APP_URL=https://app.example.com
|
||||
export MULTICA_SERVER_URL=wss://api.example.com/ws
|
||||
|
||||
multica login
|
||||
multica daemon start
|
||||
```
|
||||
|
||||
Or set them persistently:
|
||||
|
||||
```bash
|
||||
multica config set app_url https://app.example.com
|
||||
multica config set server_url wss://api.example.com/ws
|
||||
```
|
||||
|
||||
### Profiles
|
||||
|
||||
Profiles let you run multiple daemons on the same machine — for example, one for production and one for a staging server.
|
||||
|
||||
```bash
|
||||
# Start a daemon for the staging server
|
||||
multica --profile staging login
|
||||
multica --profile staging daemon start
|
||||
|
||||
# Default profile runs separately
|
||||
multica daemon start
|
||||
```
|
||||
|
||||
Each profile gets its own config directory (`~/.multica/profiles/<name>/`), daemon state, health port, and workspace root.
|
||||
|
||||
## Workspaces
|
||||
|
||||
### List Workspaces
|
||||
|
||||
```bash
|
||||
multica workspace list
|
||||
```
|
||||
|
||||
Watched workspaces are marked with `*`. The daemon only processes tasks for watched workspaces.
|
||||
|
||||
### Watch / Unwatch
|
||||
|
||||
```bash
|
||||
multica workspace watch <workspace-id>
|
||||
multica workspace unwatch <workspace-id>
|
||||
```
|
||||
|
||||
### Get Details
|
||||
|
||||
```bash
|
||||
multica workspace get <workspace-id>
|
||||
multica workspace get <workspace-id> --output json
|
||||
```
|
||||
|
||||
### List Members
|
||||
|
||||
```bash
|
||||
multica workspace members <workspace-id>
|
||||
```
|
||||
|
||||
## Issues
|
||||
|
||||
### List Issues
|
||||
|
||||
```bash
|
||||
multica issue list
|
||||
multica issue list --status in_progress
|
||||
multica issue list --priority urgent --assignee "Agent Name"
|
||||
multica issue list --limit 20 --output json
|
||||
```
|
||||
|
||||
Available filters: `--status`, `--priority`, `--assignee`, `--limit`.
|
||||
|
||||
### Get Issue
|
||||
|
||||
```bash
|
||||
multica issue get <id>
|
||||
multica issue get <id> --output json
|
||||
```
|
||||
|
||||
### Create Issue
|
||||
|
||||
```bash
|
||||
multica issue create --title "Fix login bug" --description "..." --priority high --assignee "Lambda"
|
||||
```
|
||||
|
||||
Flags: `--title` (required), `--description`, `--status`, `--priority`, `--assignee`, `--parent`, `--due-date`.
|
||||
|
||||
### Update Issue
|
||||
|
||||
```bash
|
||||
multica issue update <id> --title "New title" --priority urgent
|
||||
```
|
||||
|
||||
### Assign Issue
|
||||
|
||||
```bash
|
||||
multica issue assign <id> --to "Lambda"
|
||||
multica issue assign <id> --unassign
|
||||
```
|
||||
|
||||
### Change Status
|
||||
|
||||
```bash
|
||||
multica issue status <id> in_progress
|
||||
```
|
||||
|
||||
Valid statuses: `backlog`, `todo`, `in_progress`, `in_review`, `done`, `blocked`, `cancelled`.
|
||||
|
||||
### Comments
|
||||
|
||||
```bash
|
||||
# List comments
|
||||
multica issue comment list <issue-id>
|
||||
|
||||
# Add a comment
|
||||
multica issue comment add <issue-id> --content "Looks good, merging now"
|
||||
|
||||
# Reply to a specific comment
|
||||
multica issue comment add <issue-id> --parent <comment-id> --content "Thanks!"
|
||||
|
||||
# Delete a comment
|
||||
multica issue comment delete <comment-id>
|
||||
```
|
||||
|
||||
### Execution History
|
||||
|
||||
```bash
|
||||
# List all execution runs for an issue
|
||||
multica issue runs <issue-id>
|
||||
multica issue runs <issue-id> --output json
|
||||
|
||||
# View messages for a specific execution run
|
||||
multica issue run-messages <task-id>
|
||||
multica issue run-messages <task-id> --output json
|
||||
|
||||
# Incremental fetch (only messages after a given sequence number)
|
||||
multica issue run-messages <task-id> --since 42 --output json
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### View Config
|
||||
|
||||
```bash
|
||||
multica config show
|
||||
```
|
||||
|
||||
Shows config file path, server URL, app URL, and default workspace.
|
||||
|
||||
### Set Values
|
||||
|
||||
```bash
|
||||
multica config set server_url wss://api.example.com/ws
|
||||
multica config set app_url https://app.example.com
|
||||
multica config set workspace_id <workspace-id>
|
||||
```
|
||||
|
||||
## Other Commands
|
||||
|
||||
```bash
|
||||
multica version # Show CLI version and commit hash
|
||||
multica update # Update to latest version
|
||||
multica agent list # List agents in the current workspace
|
||||
```
|
||||
|
||||
## Output Formats
|
||||
|
||||
Most commands support `--output` with two formats:
|
||||
|
||||
- `table` — human-readable table (default for list commands)
|
||||
- `json` — structured JSON (useful for scripting and automation)
|
||||
|
||||
```bash
|
||||
multica issue list --output json
|
||||
multica daemon status --output json
|
||||
```
|
||||
75
apps/docs/content/docs/developers/architecture.mdx
Normal file
75
apps/docs/content/docs/developers/architecture.mdx
Normal file
@@ -0,0 +1,75 @@
|
||||
---
|
||||
title: Architecture
|
||||
description: Technical architecture of the Multica platform.
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Multica is a Go backend + monorepo frontend (pnpm workspaces + Turborepo) with shared packages.
|
||||
|
||||
```
|
||||
┌──────────────┐ ┌──────────────┐ ┌──────────────────┐
|
||||
│ Next.js │────>│ Go Backend │────>│ PostgreSQL │
|
||||
│ Frontend │<────│ (Chi + WS) │<────│ (pgvector) │
|
||||
└──────────────┘ └──────┬───────┘ └──────────────────┘
|
||||
│
|
||||
┌──────┴───────┐
|
||||
│ Agent Daemon │ (runs on your machine)
|
||||
│Claude/Codex/ │
|
||||
│OpenClaw/Code │
|
||||
└──────────────┘
|
||||
```
|
||||
|
||||
## Project Structure
|
||||
|
||||
| Directory | Purpose | Technology |
|
||||
|-----------|---------|------------|
|
||||
| `server/` | Go backend | Chi router, sqlc for DB, gorilla/websocket |
|
||||
| `apps/web/` | Next.js frontend | App Router |
|
||||
| `apps/desktop/` | Electron desktop app | electron-vite |
|
||||
| `apps/docs/` | Documentation site | Fumadocs |
|
||||
| `packages/core/` | Headless business logic | Zero react-dom, all-platform reuse |
|
||||
| `packages/ui/` | Atomic UI components | Zero business logic, shadcn-based |
|
||||
| `packages/views/` | Shared business pages | Zero next/\*, zero react-router imports |
|
||||
| `packages/tsconfig/` | Shared TypeScript config | — |
|
||||
| `packages/eslint-config/` | Shared ESLint config | — |
|
||||
|
||||
## Backend Structure
|
||||
|
||||
- **Entry points** (`cmd/`): `server` (HTTP API), `multica` (CLI + daemon), `migrate`
|
||||
- **Handlers** (`internal/handler/`): One file per domain (issue, comment, agent, auth, daemon)
|
||||
- **Real-time** (`internal/realtime/`): Hub manages WebSocket clients, server broadcasts events
|
||||
- **Auth** (`internal/auth/` + `internal/middleware/`): JWT (HS256), middleware sets `X-User-ID` and `X-User-Email` headers
|
||||
- **Task lifecycle** (`internal/service/task.go`): enqueue → claim → start → complete/fail
|
||||
- **Agent SDK** (`pkg/agent/`): Unified `Backend` interface for executing prompts via Claude Code or Codex
|
||||
- **Daemon** (`internal/daemon/`): Auto-detects CLIs, registers runtimes, polls for tasks
|
||||
- **Database**: PostgreSQL 17 with pgvector, sqlc generates code from SQL in `pkg/db/queries/`
|
||||
|
||||
## Frontend Architecture
|
||||
|
||||
### Internal Packages Pattern
|
||||
|
||||
All shared packages export raw `.ts`/`.tsx` files (no pre-compilation). The consuming app's bundler compiles them directly. This gives zero-config HMR and instant go-to-definition.
|
||||
|
||||
### Package Boundaries
|
||||
|
||||
- `packages/core/` — zero react-dom, zero localStorage, zero UI libs. All Zustand stores live here.
|
||||
- `packages/ui/` — pure UI components, zero business logic.
|
||||
- `packages/views/` — zero `next/*`, zero `react-router-dom`. Uses `NavigationAdapter` for routing.
|
||||
|
||||
### State Management
|
||||
|
||||
- **TanStack Query** owns all server state (issues, users, workspaces)
|
||||
- **Zustand** owns all client state (UI selections, filters, drafts)
|
||||
- **React Context** reserved for cross-cutting plumbing (`WorkspaceIdProvider`, `NavigationProvider`)
|
||||
|
||||
### Data Flow
|
||||
|
||||
```
|
||||
Browser → ApiClient (shared/api) → REST API (Chi handlers) → sqlc queries → PostgreSQL
|
||||
Browser ← WSClient (shared/api) ← WebSocket ← Hub.Broadcast() ← Handlers/TaskService
|
||||
```
|
||||
|
||||
## Multi-tenancy
|
||||
|
||||
All queries filter by `workspace_id`. Membership checks gate access. `X-Workspace-ID` header routes requests to the correct workspace.
|
||||
178
apps/docs/content/docs/developers/contributing.mdx
Normal file
178
apps/docs/content/docs/developers/contributing.mdx
Normal file
@@ -0,0 +1,178 @@
|
||||
---
|
||||
title: Contributing
|
||||
description: Local development workflow for contributors working on the Multica codebase.
|
||||
---
|
||||
|
||||
## Development Model
|
||||
|
||||
Local development uses one shared PostgreSQL container and one database per checkout.
|
||||
|
||||
- The main checkout usually uses `.env` and `POSTGRES_DB=multica`
|
||||
- Each Git worktree uses its own `.env.worktree`
|
||||
- Every checkout connects to the same PostgreSQL host: `localhost:5432`
|
||||
- Isolation happens at the database level, not by starting a separate Docker Compose project
|
||||
- Backend and frontend ports are still unique per worktree
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Node.js `v20+`
|
||||
- `pnpm` `v10.28+`
|
||||
- Go `v1.26+`
|
||||
- Docker
|
||||
|
||||
## First-Time Setup
|
||||
|
||||
### Main Checkout
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
make setup-main
|
||||
```
|
||||
|
||||
What `make setup-main` does:
|
||||
|
||||
- Installs JavaScript dependencies with `pnpm install`
|
||||
- Ensures the shared PostgreSQL container is running
|
||||
- Creates the application database if it does not exist
|
||||
- Runs all migrations against that database
|
||||
|
||||
Start the app:
|
||||
|
||||
```bash
|
||||
make start-main
|
||||
```
|
||||
|
||||
### Worktree
|
||||
|
||||
From the worktree directory:
|
||||
|
||||
```bash
|
||||
make worktree-env
|
||||
make setup-worktree
|
||||
```
|
||||
|
||||
Start the worktree app:
|
||||
|
||||
```bash
|
||||
make start-worktree
|
||||
```
|
||||
|
||||
## Daily Workflow
|
||||
|
||||
### Main Checkout
|
||||
|
||||
```bash
|
||||
make start-main
|
||||
make stop-main
|
||||
make check-main
|
||||
```
|
||||
|
||||
### Feature Worktree
|
||||
|
||||
```bash
|
||||
git worktree add ../multica-feature -b feat/my-change main
|
||||
cd ../multica-feature
|
||||
make worktree-env
|
||||
make setup-worktree
|
||||
make start-worktree
|
||||
```
|
||||
|
||||
Day-to-day:
|
||||
|
||||
```bash
|
||||
make start-worktree
|
||||
make stop-worktree
|
||||
make check-worktree
|
||||
```
|
||||
|
||||
## Running Main and Worktree Simultaneously
|
||||
|
||||
This is a first-class workflow. Both checkouts use the same PostgreSQL container but different databases and ports:
|
||||
|
||||
| | Main | Worktree |
|
||||
|---|---|---|
|
||||
| Database | `multica` | `multica_my_feature_702` |
|
||||
| Backend port | `8080` | generated (e.g. `18782`) |
|
||||
| Frontend port | `3000` | generated (e.g. `13702`) |
|
||||
|
||||
## Commands
|
||||
|
||||
```bash
|
||||
# Frontend (all commands go through Turborepo)
|
||||
pnpm install
|
||||
pnpm dev:web # Next.js dev server (port 3000)
|
||||
pnpm dev:desktop # Electron dev (electron-vite, HMR)
|
||||
pnpm build # Build all frontend apps
|
||||
pnpm typecheck # TypeScript check
|
||||
pnpm lint # ESLint
|
||||
pnpm test # TS tests (Vitest)
|
||||
|
||||
# Backend (Go)
|
||||
make dev # Run Go server (port 8080)
|
||||
make daemon # Run local daemon
|
||||
make build # Build server + CLI binaries
|
||||
make test # Go tests
|
||||
make sqlc # Regenerate sqlc code
|
||||
make migrate-up # Run database migrations
|
||||
make migrate-down # Rollback migrations
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
Run all local checks:
|
||||
|
||||
```bash
|
||||
make check
|
||||
```
|
||||
|
||||
This runs:
|
||||
|
||||
1. TypeScript typecheck
|
||||
2. TypeScript unit tests
|
||||
3. Go tests
|
||||
4. Playwright E2E tests
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Missing Env File
|
||||
|
||||
Create the expected env file:
|
||||
|
||||
```bash
|
||||
# Main checkout
|
||||
cp .env.example .env
|
||||
|
||||
# Worktree
|
||||
make worktree-env
|
||||
```
|
||||
|
||||
### Check Which Database a Checkout Uses
|
||||
|
||||
```bash
|
||||
cat .env # or .env.worktree
|
||||
```
|
||||
|
||||
Look for `POSTGRES_DB`, `DATABASE_URL`, `PORT`, `FRONTEND_PORT`.
|
||||
|
||||
### List All Local Databases
|
||||
|
||||
```bash
|
||||
docker compose exec -T postgres psql -U multica -d postgres \
|
||||
-At -c "select datname from pg_database order by datname;"
|
||||
```
|
||||
|
||||
### Destructive Reset
|
||||
|
||||
Stop PostgreSQL and keep local databases:
|
||||
|
||||
```bash
|
||||
make db-down
|
||||
```
|
||||
|
||||
Wipe all local PostgreSQL data:
|
||||
|
||||
```bash
|
||||
docker compose down -v
|
||||
```
|
||||
|
||||
> **Warning:** This deletes the shared Docker volume and all databases. After that you must run `make setup-main` or `make setup-worktree` again.
|
||||
4
apps/docs/content/docs/developers/meta.json
Normal file
4
apps/docs/content/docs/developers/meta.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"title": "Developers",
|
||||
"pages": ["contributing", "architecture"]
|
||||
}
|
||||
48
apps/docs/content/docs/getting-started/cloud-quickstart.mdx
Normal file
48
apps/docs/content/docs/getting-started/cloud-quickstart.mdx
Normal file
@@ -0,0 +1,48 @@
|
||||
---
|
||||
title: Cloud Quickstart
|
||||
description: Get started with Multica Cloud — no setup required.
|
||||
---
|
||||
|
||||
The fastest way to get started with Multica — no setup required.
|
||||
|
||||
## 1. Sign up
|
||||
|
||||
Go to [multica.ai](https://multica.ai) and create an account.
|
||||
|
||||
## 2. Install the CLI and start the daemon
|
||||
|
||||
Give this instruction to your AI agent (Claude Code, Codex, OpenClaw, OpenCode, etc.):
|
||||
|
||||
```
|
||||
Fetch https://github.com/multica-ai/multica/blob/main/CLI_INSTALL.md and follow the instructions to install Multica CLI, log in, and start the daemon on this machine.
|
||||
```
|
||||
|
||||
Or install manually:
|
||||
|
||||
```bash
|
||||
# Install
|
||||
brew tap multica-ai/tap
|
||||
brew install multica
|
||||
|
||||
# Authenticate and start
|
||||
multica login
|
||||
multica daemon start
|
||||
```
|
||||
|
||||
The daemon auto-detects available agent CLIs (`claude`, `codex`, `openclaw`, `opencode`) on your PATH. When an agent is assigned a task, the daemon creates an isolated environment, runs the agent, and reports results back.
|
||||
|
||||
## 3. Verify your runtime
|
||||
|
||||
Open your workspace in the Multica web app. Navigate to **Settings → Runtimes** — you should see your machine listed as an active **Runtime**.
|
||||
|
||||
> **What is a Runtime?** A Runtime is a compute environment that can execute agent tasks. It can be your local machine (via the daemon) or a cloud instance. Each runtime reports which agent CLIs are available, so Multica knows where to route work.
|
||||
|
||||
## 4. Create an agent
|
||||
|
||||
Go to **Settings → Agents** and click **New Agent**. Pick the runtime you just connected and choose a provider (Claude Code, Codex, OpenClaw, or OpenCode). Give your agent a name — this is how it will appear on the board, in comments, and in assignments.
|
||||
|
||||
## 5. Assign your first task
|
||||
|
||||
Create an issue from the board (or via `multica issue create`), then assign it to your new agent. The agent will automatically pick up the task, execute it on your runtime, and report progress — just like a human teammate.
|
||||
|
||||
That's it! Your agent is now part of the team.
|
||||
4
apps/docs/content/docs/getting-started/meta.json
Normal file
4
apps/docs/content/docs/getting-started/meta.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"title": "Getting Started",
|
||||
"pages": ["cloud-quickstart", "self-hosting"]
|
||||
}
|
||||
281
apps/docs/content/docs/getting-started/self-hosting.mdx
Normal file
281
apps/docs/content/docs/getting-started/self-hosting.mdx
Normal file
@@ -0,0 +1,281 @@
|
||||
---
|
||||
title: Self-Hosting Guide
|
||||
description: Deploy Multica on your own infrastructure.
|
||||
---
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
Multica has three components:
|
||||
|
||||
| Component | Description | Technology |
|
||||
|-----------|-------------|------------|
|
||||
| **Backend** | REST API + WebSocket server | Go (single binary) |
|
||||
| **Frontend** | Web application | Next.js 16 |
|
||||
| **Database** | Primary data store | PostgreSQL 17 with pgvector |
|
||||
|
||||
Additionally, each user who wants to run AI agents locally installs the **`multica` CLI** and runs the **agent daemon** on their own machine.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Docker and Docker Compose (recommended), or:
|
||||
- Go 1.26+ (to build from source)
|
||||
- Node.js 20+ and pnpm 10.28+ (to build the frontend)
|
||||
- PostgreSQL 17 with the pgvector extension
|
||||
|
||||
## Quick Start (Docker Compose)
|
||||
|
||||
```bash
|
||||
git clone https://github.com/multica-ai/multica.git
|
||||
cd multica
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
Edit `.env` with your production values (see [Configuration](#configuration) below), then:
|
||||
|
||||
```bash
|
||||
# Start PostgreSQL
|
||||
docker compose up -d
|
||||
|
||||
# Build the backend
|
||||
make build
|
||||
|
||||
# Run database migrations
|
||||
DATABASE_URL="your-database-url" ./server/bin/migrate up
|
||||
|
||||
# Start the backend server
|
||||
DATABASE_URL="your-database-url" PORT=8080 ./server/bin/server
|
||||
```
|
||||
|
||||
For the frontend:
|
||||
|
||||
```bash
|
||||
pnpm install
|
||||
pnpm build
|
||||
|
||||
# Start the frontend (production mode)
|
||||
cd apps/web
|
||||
REMOTE_API_URL=http://localhost:8080 pnpm start
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
All configuration is done via environment variables. Copy `.env.example` as a starting point.
|
||||
|
||||
### Required Variables
|
||||
|
||||
| Variable | Description | Example |
|
||||
|----------|-------------|---------|
|
||||
| `DATABASE_URL` | PostgreSQL connection string | `postgres://multica:multica@localhost:5432/multica?sslmode=disable` |
|
||||
| `JWT_SECRET` | **Must change from default.** Secret key for signing JWT tokens. Use a long random string. | `openssl rand -hex 32` |
|
||||
| `FRONTEND_ORIGIN` | URL where the frontend is served (used for CORS) | `https://app.example.com` |
|
||||
|
||||
### Email (Required for Authentication)
|
||||
|
||||
Multica uses email-based magic link authentication via [Resend](https://resend.com).
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `RESEND_API_KEY` | Your Resend API key |
|
||||
| `RESEND_FROM_EMAIL` | Sender email address (default: `noreply@multica.ai`) |
|
||||
|
||||
### Google OAuth (Optional)
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `GOOGLE_CLIENT_ID` | Google OAuth client ID |
|
||||
| `GOOGLE_CLIENT_SECRET` | Google OAuth client secret |
|
||||
| `GOOGLE_REDIRECT_URI` | OAuth callback URL (e.g. `https://app.example.com/auth/callback`) |
|
||||
|
||||
### File Storage (Optional)
|
||||
|
||||
For file uploads and attachments, configure S3 and CloudFront:
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `S3_BUCKET` | S3 bucket name |
|
||||
| `S3_REGION` | AWS region (default: `us-west-2`) |
|
||||
| `CLOUDFRONT_DOMAIN` | CloudFront distribution domain |
|
||||
| `CLOUDFRONT_KEY_PAIR_ID` | CloudFront key pair ID for signed URLs |
|
||||
| `CLOUDFRONT_PRIVATE_KEY` | CloudFront private key (PEM format) |
|
||||
| `COOKIE_DOMAIN` | Domain for CloudFront auth cookies |
|
||||
|
||||
### Server
|
||||
|
||||
| Variable | Default | Description |
|
||||
|----------|---------|-------------|
|
||||
| `PORT` | `8080` | Backend server port |
|
||||
| `FRONTEND_PORT` | `3000` | Frontend port |
|
||||
| `CORS_ALLOWED_ORIGINS` | Value of `FRONTEND_ORIGIN` | Comma-separated list of allowed origins |
|
||||
| `LOG_LEVEL` | `info` | Log level: `debug`, `info`, `warn`, `error` |
|
||||
|
||||
### CLI / Daemon
|
||||
|
||||
These are configured on each user's machine, not on the server:
|
||||
|
||||
| Variable | Default | Description |
|
||||
|----------|---------|-------------|
|
||||
| `MULTICA_SERVER_URL` | `ws://localhost:8080/ws` | WebSocket URL for daemon → server connection |
|
||||
| `MULTICA_APP_URL` | `http://localhost:3000` | Frontend URL for CLI login flow |
|
||||
| `MULTICA_DAEMON_POLL_INTERVAL` | `3s` | How often the daemon polls for tasks |
|
||||
| `MULTICA_DAEMON_HEARTBEAT_INTERVAL` | `15s` | Heartbeat frequency |
|
||||
|
||||
## Database Setup
|
||||
|
||||
Multica requires PostgreSQL 17 with the pgvector extension.
|
||||
|
||||
### Using the Included Docker Compose
|
||||
|
||||
```bash
|
||||
docker compose up -d postgres
|
||||
```
|
||||
|
||||
This starts a `pgvector/pgvector:pg17` container on port 5432 with default credentials (`multica`/`multica`).
|
||||
|
||||
### Using Your Own PostgreSQL
|
||||
|
||||
Ensure the pgvector extension is available:
|
||||
|
||||
```sql
|
||||
CREATE EXTENSION IF NOT EXISTS vector;
|
||||
```
|
||||
|
||||
### Running Migrations
|
||||
|
||||
Migrations must be run before starting the server:
|
||||
|
||||
```bash
|
||||
# Using the built binary
|
||||
./server/bin/migrate up
|
||||
|
||||
# Or from source
|
||||
cd server && go run ./cmd/migrate up
|
||||
```
|
||||
|
||||
## Reverse Proxy
|
||||
|
||||
In production, put a reverse proxy in front of both the backend and frontend to handle TLS and routing.
|
||||
|
||||
### Caddy (Recommended)
|
||||
|
||||
```
|
||||
app.example.com {
|
||||
reverse_proxy localhost:3000
|
||||
}
|
||||
|
||||
api.example.com {
|
||||
reverse_proxy localhost:8080
|
||||
}
|
||||
```
|
||||
|
||||
### Nginx
|
||||
|
||||
```nginx
|
||||
# Frontend
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name app.example.com;
|
||||
|
||||
ssl_certificate /path/to/cert.pem;
|
||||
ssl_certificate_key /path/to/key.pem;
|
||||
|
||||
location / {
|
||||
proxy_pass http://localhost:3000;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
}
|
||||
|
||||
# Backend API
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name api.example.com;
|
||||
|
||||
ssl_certificate /path/to/cert.pem;
|
||||
ssl_certificate_key /path/to/key.pem;
|
||||
|
||||
location / {
|
||||
proxy_pass http://localhost:8080;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
# WebSocket support
|
||||
location /ws {
|
||||
proxy_pass http://localhost:8080;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
proxy_read_timeout 86400;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
When using separate domains for frontend and backend, set these environment variables accordingly:
|
||||
|
||||
```bash
|
||||
# Backend
|
||||
FRONTEND_ORIGIN=https://app.example.com
|
||||
CORS_ALLOWED_ORIGINS=https://app.example.com
|
||||
|
||||
# Frontend
|
||||
REMOTE_API_URL=https://api.example.com
|
||||
NEXT_PUBLIC_API_URL=https://api.example.com
|
||||
NEXT_PUBLIC_WS_URL=wss://api.example.com/ws
|
||||
```
|
||||
|
||||
## Health Check
|
||||
|
||||
The backend exposes a health check endpoint:
|
||||
|
||||
```
|
||||
GET /health
|
||||
→ {"status":"ok"}
|
||||
```
|
||||
|
||||
Use this for load balancer health checks or monitoring.
|
||||
|
||||
## Setting Up the Agent Daemon
|
||||
|
||||
Each team member who wants to run AI agents locally needs to:
|
||||
|
||||
1. **Install the CLI**
|
||||
|
||||
```bash
|
||||
brew tap multica-ai/tap
|
||||
brew install multica-cli
|
||||
```
|
||||
|
||||
2. **Install an AI agent CLI** — at least one of:
|
||||
- [Claude Code](https://docs.anthropic.com/en/docs/claude-code) (`claude` on PATH)
|
||||
- [Codex](https://github.com/openai/codex) (`codex` on PATH)
|
||||
|
||||
3. **Authenticate and start**
|
||||
|
||||
```bash
|
||||
# Point CLI to your server
|
||||
export MULTICA_APP_URL=https://app.example.com
|
||||
export MULTICA_SERVER_URL=wss://api.example.com/ws
|
||||
|
||||
# Login (opens browser)
|
||||
multica login
|
||||
|
||||
# Start the daemon
|
||||
multica daemon start
|
||||
```
|
||||
|
||||
> **Note:** Use `https://` and `wss://` for production deployments behind a TLS-terminating reverse proxy. For local or development deployments without TLS, use `http://` and `ws://` instead.
|
||||
|
||||
The daemon auto-detects installed agent CLIs and registers itself with the server.
|
||||
|
||||
## Upgrading
|
||||
|
||||
1. Pull the latest code or image
|
||||
2. Run migrations: `./server/bin/migrate up`
|
||||
3. Restart the backend and frontend
|
||||
|
||||
Migrations are forward-only and safe to run on a live database. They are idempotent — running them multiple times has no effect.
|
||||
50
apps/docs/content/docs/guides/agents.mdx
Normal file
50
apps/docs/content/docs/guides/agents.mdx
Normal file
@@ -0,0 +1,50 @@
|
||||
---
|
||||
title: Agents
|
||||
description: How AI agents work in Multica — execution model, skills, and runtime guidelines.
|
||||
---
|
||||
|
||||
## Agents as Teammates
|
||||
|
||||
In Multica, agents are first-class citizens. They have profiles, show up on the board, post comments, create issues, and report blockers proactively.
|
||||
|
||||
Assignees are polymorphic — an issue can be assigned to a member or an agent. The `assignee_type` + `assignee_id` fields on issues distinguish between the two. Agents render with distinct styling (purple background, robot icon).
|
||||
|
||||
## Agent Execution Model
|
||||
|
||||
When an agent is assigned a task in Multica:
|
||||
|
||||
1. The daemon detects the task assignment
|
||||
2. It creates an isolated workspace directory
|
||||
3. It spawns the appropriate agent CLI (Claude Code, Codex, OpenClaw, or OpenCode)
|
||||
4. The agent executes autonomously, streaming progress back to Multica
|
||||
5. Results are reported — success, failure, or blockers
|
||||
|
||||
The full task lifecycle is: **enqueue → claim → start → complete/fail**.
|
||||
|
||||
Real-time progress is streamed via WebSocket so you can follow along in the Multica UI.
|
||||
|
||||
## Supported Agent Providers
|
||||
|
||||
| Provider | CLI Command | Description |
|
||||
|----------|-------------|-------------|
|
||||
| Claude Code | `claude` | Anthropic's coding agent |
|
||||
| Codex | `codex` | OpenAI's coding agent |
|
||||
| OpenClaw | `openclaw` | Open-source coding agent |
|
||||
| OpenCode | `opencode` | Open-source coding agent |
|
||||
|
||||
The daemon auto-detects which CLIs are available on your PATH and registers them as available runtimes.
|
||||
|
||||
## Reusable Skills
|
||||
|
||||
Every solution an agent creates can become a reusable skill for the whole team. Skills compound your team's capabilities over time:
|
||||
|
||||
- Deployments
|
||||
- Migrations
|
||||
- Code reviews
|
||||
- Common patterns
|
||||
|
||||
Skills are shared across the workspace, so any agent (or human) can leverage them.
|
||||
|
||||
## Multi-Workspace Support
|
||||
|
||||
Each workspace has its own set of agents, issues, and settings. The daemon can watch multiple workspaces simultaneously, routing tasks to the appropriate agent based on workspace configuration.
|
||||
4
apps/docs/content/docs/guides/meta.json
Normal file
4
apps/docs/content/docs/guides/meta.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"title": "Guides",
|
||||
"pages": ["quickstart", "agents"]
|
||||
}
|
||||
31
apps/docs/content/docs/guides/quickstart.mdx
Normal file
31
apps/docs/content/docs/guides/quickstart.mdx
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
title: Quickstart
|
||||
description: Assign your first task to an agent in under 5 minutes.
|
||||
---
|
||||
|
||||
Once you have the CLI installed (or signed up for [Multica Cloud](https://multica.ai)), follow these steps to assign your first task to an agent.
|
||||
|
||||
## 1. Log in and start the daemon
|
||||
|
||||
```bash
|
||||
multica login # Authenticate with your Multica account
|
||||
multica daemon start # Start the local agent runtime
|
||||
```
|
||||
|
||||
The daemon runs in the background and keeps your machine connected to Multica. It auto-detects agent CLIs (`claude`, `codex`, `openclaw`, `opencode`) available on your PATH.
|
||||
|
||||
## 2. Verify your runtime
|
||||
|
||||
Open your workspace in the Multica web app. Navigate to **Settings → Runtimes** — you should see your machine listed as an active **Runtime**.
|
||||
|
||||
> **What is a Runtime?** A Runtime is a compute environment that can execute agent tasks. It can be your local machine (via the daemon) or a cloud instance. Each runtime reports which agent CLIs are available, so Multica knows where to route work.
|
||||
|
||||
## 3. Create an agent
|
||||
|
||||
Go to **Settings → Agents** and click **New Agent**. Pick the runtime you just connected and choose a provider (Claude Code, Codex, OpenClaw, or OpenCode). Give your agent a name — this is how it will appear on the board, in comments, and in assignments.
|
||||
|
||||
## 4. Assign your first task
|
||||
|
||||
Create an issue from the board (or via `multica issue create`), then assign it to your new agent. The agent will automatically pick up the task, execute it on your runtime, and report progress — just like a human teammate.
|
||||
|
||||
That's it! Your agent is now part of the team.
|
||||
47
apps/docs/content/docs/index.mdx
Normal file
47
apps/docs/content/docs/index.mdx
Normal file
@@ -0,0 +1,47 @@
|
||||
---
|
||||
title: Introduction
|
||||
description: Multica — the open-source managed agents platform. Turn coding agents into real teammates.
|
||||
---
|
||||
|
||||
## What is Multica?
|
||||
|
||||
Multica turns coding agents into real teammates. Assign issues to an agent like you'd assign to a colleague — they'll pick up the work, write code, report blockers, and update statuses autonomously.
|
||||
|
||||
No more copy-pasting prompts. No more babysitting runs. Your agents show up on the board, participate in conversations, and compound reusable skills over time. Think of it as open-source infrastructure for managed agents — vendor-neutral, self-hosted, and designed for human + AI teams. Works with **Claude Code**, **Codex**, **OpenClaw**, and **OpenCode**.
|
||||
|
||||
## Features
|
||||
|
||||
- **Agents as Teammates** — assign to an agent like you'd assign to a colleague. They have profiles, show up on the board, post comments, create issues, and report blockers proactively.
|
||||
- **Autonomous Execution** — set it and forget it. Full task lifecycle management (enqueue, claim, start, complete/fail) with real-time progress streaming via WebSocket.
|
||||
- **Reusable Skills** — every solution becomes a reusable skill for the whole team. Deployments, migrations, code reviews — skills compound your team's capabilities over time.
|
||||
- **Unified Runtimes** — one dashboard for all your compute. Local daemons and cloud runtimes, auto-detection of available CLIs, real-time monitoring.
|
||||
- **Multi-Workspace** — organize work across teams with workspace-level isolation. Each workspace has its own agents, issues, and settings.
|
||||
|
||||
## Architecture
|
||||
|
||||
| Layer | Stack |
|
||||
|-------|-------|
|
||||
| Frontend | Next.js 16 (App Router) |
|
||||
| Backend | Go (Chi router, sqlc, gorilla/websocket) |
|
||||
| Database | PostgreSQL 17 with pgvector |
|
||||
| Agent Runtime | Local daemon executing Claude Code, Codex, OpenClaw, or OpenCode |
|
||||
|
||||
```
|
||||
┌──────────────┐ ┌──────────────┐ ┌──────────────────┐
|
||||
│ Next.js │────>│ Go Backend │────>│ PostgreSQL │
|
||||
│ Frontend │<────│ (Chi + WS) │<────│ (pgvector) │
|
||||
└──────────────┘ └──────┬───────┘ └──────────────────┘
|
||||
│
|
||||
┌──────┴───────┐
|
||||
│ Agent Daemon │ (runs on your machine)
|
||||
│Claude/Codex/ │
|
||||
│OpenClaw/Code │
|
||||
└──────────────┘
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [Cloud Quickstart](/docs/getting-started/cloud-quickstart)
|
||||
- [Self-Hosting](/docs/getting-started/self-hosting)
|
||||
- [CLI Installation](/docs/cli/installation)
|
||||
- [Contributing](/docs/developers/contributing)
|
||||
10
apps/docs/content/docs/meta.json
Normal file
10
apps/docs/content/docs/meta.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"title": "Documentation",
|
||||
"pages": [
|
||||
"index",
|
||||
"getting-started",
|
||||
"cli",
|
||||
"guides",
|
||||
"developers"
|
||||
]
|
||||
}
|
||||
7
apps/docs/lib/source.ts
Normal file
7
apps/docs/lib/source.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { docs } from "@/.source";
|
||||
import { loader } from "fumadocs-core/source";
|
||||
|
||||
export const source = loader({
|
||||
baseUrl: "/docs",
|
||||
source: docs.toFumadocsSource(),
|
||||
});
|
||||
6
apps/docs/next-env.d.ts
vendored
Normal file
6
apps/docs/next-env.d.ts
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
/// <reference types="next" />
|
||||
/// <reference types="next/image-types/global" />
|
||||
/// <reference path="./.next/types/routes.d.ts" />
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
||||
10
apps/docs/next.config.mjs
Normal file
10
apps/docs/next.config.mjs
Normal file
@@ -0,0 +1,10 @@
|
||||
import { createMDX } from "fumadocs-mdx/next";
|
||||
|
||||
const withMDX = createMDX();
|
||||
|
||||
/** @type {import('next').NextConfig} */
|
||||
const config = {
|
||||
reactStrictMode: true,
|
||||
};
|
||||
|
||||
export default withMDX(config);
|
||||
29
apps/docs/package.json
Normal file
29
apps/docs/package.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"name": "@multica/docs",
|
||||
"version": "0.2.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "next dev --port 4000",
|
||||
"build": "fumadocs-mdx && next build",
|
||||
"start": "next start",
|
||||
"typecheck": "fumadocs-mdx && tsc --noEmit",
|
||||
"postinstall": "fumadocs-mdx"
|
||||
},
|
||||
"dependencies": {
|
||||
"fumadocs-core": "^15.5.2",
|
||||
"fumadocs-mdx": "^12.0.3",
|
||||
"fumadocs-ui": "^15.5.2",
|
||||
"lucide-react": "catalog:",
|
||||
"next": "^15.3.3",
|
||||
"react": "catalog:",
|
||||
"react-dom": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/postcss": "catalog:",
|
||||
"@types/react": "catalog:",
|
||||
"@types/react-dom": "catalog:",
|
||||
"tailwindcss": "catalog:",
|
||||
"typescript": "catalog:"
|
||||
}
|
||||
}
|
||||
7
apps/docs/postcss.config.mjs
Normal file
7
apps/docs/postcss.config.mjs
Normal file
@@ -0,0 +1,7 @@
|
||||
const config = {
|
||||
plugins: {
|
||||
"@tailwindcss/postcss": {},
|
||||
},
|
||||
};
|
||||
|
||||
export default config;
|
||||
9
apps/docs/source.config.ts
Normal file
9
apps/docs/source.config.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { defineDocs, defineConfig } from "fumadocs-mdx/config";
|
||||
|
||||
export const docs = defineDocs({
|
||||
dir: "content/docs",
|
||||
});
|
||||
|
||||
export default defineConfig({
|
||||
mdxOptions: {},
|
||||
});
|
||||
48
apps/docs/tsconfig.json
Normal file
48
apps/docs/tsconfig.json
Normal file
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"lib": [
|
||||
"ESNext",
|
||||
"DOM",
|
||||
"DOM.Iterable"
|
||||
],
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"verbatimModuleSyntax": true,
|
||||
"isolatedModules": true,
|
||||
"declaration": false,
|
||||
"declarationMap": false,
|
||||
"sourceMap": true,
|
||||
"noUncheckedIndexedAccess": true,
|
||||
"resolveJsonModule": true,
|
||||
"jsx": "preserve",
|
||||
"plugins": [
|
||||
{
|
||||
"name": "next"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"./*"
|
||||
]
|
||||
},
|
||||
"noEmit": true,
|
||||
"allowJs": true,
|
||||
"incremental": true
|
||||
},
|
||||
"include": [
|
||||
"next-env.d.ts",
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
".next/types/**/*.ts",
|
||||
".next/dev/types/**/*.ts",
|
||||
".source/**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
1166
pnpm-lock.yaml
generated
1166
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user