Claude Organizer
A "Jira" for Claude Code — your agent's project board, exposed over MCP.
Claude Organizer gives Claude Code a real project-management system — cards, sprints, comments and docs — as queryable state over MCP, instead of spec Markdown files that grow without bound and go stale. A clean Nuxt UI mirrors the same board for humans, in real time.
It ships as a Claude Code plugin (three skills + the MCP server), backed by a pnpm monorepo you run with Docker — one command delivers the skills and registers the MCP, no claude mcp add.
[!WARNING] Early stage — not yet stable. Claude Organizer is under active development and not production-stable yet. Right now we're focused on stabilizing the skills (the
plan/implementworkflow the agent runs), so their behavior and the tool surface may still change between versions. Expect breaking changes — so keep the plugin's auto-update off (toggle it under/plugin→ Marketplaces) and upgrade deliberately.
Why
A long-running coding agent has no memory between sessions. The usual fix — piling plans and decisions into ever-growing .md files — rots fast: the files drift from reality, contradict each other, and bloat the context window.
Claude Organizer flips that. What to do (the active sprint, cards, backlog, comments, decisions, docs) lives in a database the AI queries on demand through MCP tools, and edits as work progresses. The agent orients itself at the start of every session by reading the board — not by re-reading stale prose. You watch the same board, drag cards, and leave comments the agent reads back.
Highlights
- 🗂️ A real board — projects, sprints, stories and sub-tasks, blockers, tags, priorities. Drag-and-drop UI with live WebSocket updates.
- 🤖 Built for the agent — every entity is a typed MCP tool; prefixed IDs (
prj_,crd_,spr_…) tell the AI what it's holding at a glance. - 💬 Comments as the decision log — the agent records why on the card; you reply, it reads your unread comments back next session.
- 🔗 Commits attached to cards — each card keeps the diff that delivered it, captured outside the AI's context (no tokens spent reading patches).
- 📚 Docs that don't rot — architecture, ADRs and patterns live as project docs the agent reads before reinventing.
- 🔎 Search by meaning — cards, comments and docs are searchable with a hybrid of Postgres full-text and in-process embeddings (a multilingual model in-container, no external API), fused by rank (RRF).
Setup
Requires Node 24+, pnpm 9+, and Docker.
1. Bring up the stack
Postgres + migrations + API + UI + MCP, in one shot:
git clone https://github.com/fmilioni/claude-organizer.git
cd claude-organizer
cp .env.example .env
docker compose up -d --build
| Service | URL |
|---|---|
| Web UI | http://localhost:4401 |
| API | http://localhost:4400 |
| MCP (Streamable HTTP) | http://localhost:4402/mcp |
| Embedding service | http://localhost:4403 |
cp .env.example .env already ships working defaults for local Docker; the values worth knowing:
POSTGRES_USER=organizer
POSTGRES_PASSWORD=organizer
POSTGRES_DB=organizer
POSTGRES_PORT=5544 # host port (in-container is 5432)
API_PORT=4400
NUXT_PUBLIC_API_URL=http://127.0.0.1:4400
# MCP_HTTP_PORT=4402 # MCP port (Streamable HTTP at /mcp)
# MCP_PUBLIC_URL=http://127.0.0.1:4402 # public URL clients reach the MCP at
Migrations run automatically before the API and MCP start, and a one-shot backfill then (re)builds the semantic-search vectors for any content missing them — so upgrading is just docker compose up -d --build, no manual step. The embedding model loads in its own embedding service; the API and MCP call it over HTTP and fall back to lexical search if it's down. Postgres data persists under ./docker/data/postgres. Out of the box the board is open (no login) — see Authentication to turn sign-in on.
2. Install the plugin
The plugin delivers the skills and registers the MCP — no claude mcp add needed.
From a clone:
claude --plugin-dir plugins/claude-organizer
Or via the marketplace:
/plugin marketplace add fmilioni/claude-organizer
/plugin install claude-organizer@claude-organizer
The claude-organizer tools appear automatically, pointing at local Docker (http://localhost:4402/mcp). Local Docker needs nothing more; to reach another host, see the next section.
3. Configure the MCP for a remote host
Local Docker is the default — nothing to do: the bundled plugin already registers a claude-organizer server at http://localhost:4402/mcp.
Repoint the bundled entry with CO_MCP_URL. To make the primary board live on another machine — sharing one board across several computers — just export CO_MCP_URL before starting Claude Code; the plugin's claude-organizer server uses it instead of http://localhost:4402/mcp, keeping the same tool prefix. Reach it over a stable hostname (a Tailscale MagicDNS name like host.tailnet.ts.net, a LAN host, or a remote domain). Pair it with CO_API_URL (default http://127.0.0.1:4400) pointed at the same host — the diff-capture scripts (attach-commit / attach-worktree-diff) post to the API directly, so without it they'd hit the client machine's own localhost and fail:
export CO_MCP_URL=http://host.tailnet.ts.net:4402/mcp
export CO_API_URL=http://host.tailnet.ts.net:4400
Or register an additional named server. To run another board alongside the bundled one, register it as an additional server with a name other than claude-organizer (that one is the plugin's — reusing it clashes):
claude mcp add --transport http -s user claude-organizer-remote https://mcp.<domain>/mcp
Each server gets its own tool prefix (the bundled plugin board is mcp__plugin_claude-organizer_claude-organizer__*; this added one is mcp__claude-organizer-remote__*), OAuth session and projects; the skills pick the one whose project matches the repo and never mix them. -s user makes it available across all repos — to bind a single project to a specific server instead, scope it to the repo with -s project (a shared .mcp.json committed in the repo) or -s local (only you, only this repo).
Usage
You drive everything through one entry point — the main claude-organizer command — and it routes to plan / implement for you:
/claude-organizer:claude-organizer plan github authentication
/claude-organizer:claude-organizer implement task CO-123
/claude-organizer:claude-organizer run story CO-127 all at once
Pass it your intent in plain language (any language) and it picks the right skill. The three skills behind it:
| Skill | What it does | Triggers when… |
|---|---|---|
claude-organizer |
The entry point: what the board is, which skill to use, and binding the repo to its project (record projectId + auth flag in CLAUDE.md). |
you reference the board — "let's continue", "what's next?" |
plan |
Turn a fuzzy new demand into structured work (sprint → stories → tasks), get the design approved, then create the cards. | you describe something new to build, before it's broken down. |
implement |
Execute existing cards through their lifecycle (in_progress → implement → review → commit), single-card or a multi-card run (story/sprint) in two modes — review each card, or run the whole batch autonomously. Fires a fresh-subagent review before each card closes. |
you start/resume work on a specific card or ask to run a story/sprint — "work CO-42", "run the sprint". |
For a multi-card run, implement asks how to drive it: review each card (stop for your validation between cards) or run it all at once (execute the batch autonomously). In both modes it commits one-per-card on the git flow you agree, runs the review gate (and a story-level review when a story's last child finishes), and leaves each card in review for your final validation — it never merges on its own (no PR unless you ask). The review itself runs in a read-only reviewer subagent dispatched by implement.
Inbox
Got an idea mid-flight but don't want to plan it yet? Drop it in the inbox — a one-line demand captured without breaking it into cards. The agent reads pending inbox items when it orients and offers to plan them; the plan skill turns a demand into the right sprint/stories/tasks and marks it planned. It keeps raw intake out of the board until it's actually structured work.
Authentication
Auth is built on better-auth and is off by default — the open board above, no login, an open MCP the plugin connects to as-is. Turn it on from the first-boot setup on the login screen; the first account becomes the admin, and after that sign-in is required.
- Methods — email+password is the zero-config base; GitHub OAuth is optional and only appears when
GITHUB_CLIENT_ID/GITHUB_CLIENT_SECRETare set (callbackhttps://api.<domain>/api/auth/callback/github). No host is forced to register an OAuth app. - Access — users get roles and per-project access; admins manage who can see what.
- MCP — with auth on,
/mcpis an OAuth 2.1 resource server and the plugin obtains a bearer automatically (soCO_MCP_URLis still all you set). With auth off,/mcpis open, mirroring the open board.
Relevant env (see .env.example):
| Var | Purpose |
|---|---|
BETTER_AUTH_SECRET |
Signs sessions/tokens — required in production. |
BETTER_AUTH_URL |
Public URL of the API (where better-auth is mounted). |
AUTH_TRUSTED_ORIGINS |
Origins allowed to call auth (CSRF) — also the API's CORS allow-list. |
AUTH_COOKIE_DOMAIN |
Parent domain to share the session cookie across subdomains (remote only). |
GITHUB_CLIENT_ID / GITHUB_CLIENT_SECRET |
Enable GitHub sign-in. |
Local gotcha: the web (
:4401) and API (:4400) are different origins, and the session cookie isSameSite=Lax+ host-bound. Locally, reach both on the same host — use127.0.0.1, notlocalhost— or the cookie won't be sent. Behind the reverse proxy,AUTH_COOKIE_DOMAINremoves this constraint across the subdomains.
Remote deployment (reverse proxy)
A versioned overlay puts the three services behind one TLS edge (Caddy, ports 80/443), a subdomain each (app./api./mcp.<domain>):
cp .env.prod.example .env # set *_DOMAIN, ACME_EMAIL, BETTER_AUTH_SECRET, public URLs
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build
Point DNS for the three subdomains at the host; Caddy issues/renews TLS (ACME). Set NUXT_PUBLIC_API_URL=https://api.<domain> before building (it's baked into the SPA) and AUTH_COOKIE_DOMAIN=<domain> to share the session cookie. Details: deploy/Caddyfile, .env.prod.example.
Signing in from a terminal-only box (WSL, SSH, headless)
With auth on, Claude Code runs the OAuth flow by opening a browser and waiting on a local loopback callback (http://localhost:<random-port>/…). In a terminal-only environment that stalls — no browser opens (Claude Code prints the URL instead — open it yourself), and the loopback redirect must be able to reach back into the box (WSL2 forwards localhost by default; over SSH, forward the port with ssh -L <port>:localhost:<port> …). Keep one host throughout — don't mix localhost and 127.0.0.1, or the login won't stick.
The reliable escape hatch: auth is off by default and an open board needs no login at all. For a local/WSL dev box, leave auth off and skip the loopback flow entirely; turn auth on where a browser-reachable login exists — e.g. a remote deployment behind the reverse proxy, reached over normal https://. The loopback dance is Claude Code's MCP client plus your box's networking; Claude Organizer is a standard OAuth 2.1 resource server and can't shortcut it server-side.
Architecture
Claude Code ──HTTP──▶ MCP (:4402/mcp) ─┐
├─▶ core ──▶ Postgres 16
Browser (SPA) ──HTTP──▶ API (:4400) ───┘ (+ WebSocket /ws for real-time)
└─ core ──HTTP──▶ Embedding service (:4403) ──▶ model
A pnpm monorepo under packages/:
| Package | Role |
|---|---|
shared |
Shared TypeScript types. |
db |
Drizzle schema + migrations. |
core |
Zod-validated use-cases — the single source of truth. |
auth |
better-auth setup (email+password, GitHub, OAuth for the MCP). |
mcp |
The MCP server (Streamable HTTP). |
api |
Fastify REST + WebSocket. |
embedding-service |
Loads the embedding model once and serves it over HTTP (api/mcp are thin clients). |
web |
Nuxt 4 SPA (the UI talks only to the API, never the MCP). |
Prefixed nanoid IDs (prj_, crd_, spr_…) let the agent recognize an entity's type from the ID alone.
Development (without Docker)
pnpm install
pnpm db:up # Postgres on :5544
pnpm db:migrate
pnpm dev:api # :4400
pnpm dev:web # :4401
pnpm dev:mcp # :4402/mcp
pnpm dev:embedding # :4403 (semantic search; omit for lexical-only)
Also handy: pnpm typecheck, pnpm lint, pnpm test, and pnpm db:generate after schema changes.
License
MIT © Felipe Milioni
No comments yet
Be the first to share your take.