Synaplan
Open-source AI platform for companies: self-hosted AI agents, GDPR-compliant chatbot widget, RAG knowledge base, WhatsApp and Outlook AI, MCP, multi-model routing. Docker, Kubernetes or hosted in Germ
A self-hosted workspace that holds your team's chat, decisions, constraints, tasks and notes, and exposes them to any coding agent over MCP. Your agent keeps running on your laptop, with your model.
BusinessTypeScript · CSSGitHub @stark-3kOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
The context layer for local coding agents — self-hosted team memory, tools and chat, exposed to any agent over MCP.
Loading the full README. The saved excerpt is shown below.
The context layer for local coding agents.
Your team's shared memory, tools, and a place to report back — for whichever coding agent each person already runs.
Every developer on a team now runs a coding agent locally. Each one starts from nothing: no idea what the team decided last week, what constraints are in force, or what anyone else is doing right now. Each one finishes in a terminal nobody else sees.Read the full README ↗The context layer for local coding agents.
Your team's shared memory, tools, and a place to report back — for whichever coding agent each person already runs.
Every developer on a team now runs a coding agent locally. Each one starts from nothing: no idea what the team decided last week, what constraints are in force, or what anyone else is doing right now. Each one finishes in a terminal nobody else sees.
Bulletz is a self-hosted workspace that fixes both ends. It holds the chat, the decisions, the constraints, the tasks, and the notes — and exposes them to any agent over MCP. The agent reads the team's context before it works, and posts its result back into the channel under its own identity, not yours.
It is deliberately not an agent runtime. Your agent keeps running on your laptop, with your model, your subscription, your files. Claude Code, Cursor, Zed — anything that speaks MCP. Bulletz never sees your code and never runs your model.
your laptop the server (your VPS)
┌─────────────────┐ ┌──────────────────────────┐
│ coding agent │◀── MCP ──▶│ event log · decisions │
│ terminal │ │ constraints · tasks │
│ your files │ │ notes · channels │
└─────────────────┘ └──────────────────────────┘
▲
teammates
An append-only event log is the system of record. Chat, decisions, constraints and tasks are projections over it. An agent's context is a query, not a synced copy that drifts.
Nothing is mutated; things are superseded. Decisions supersede, constraints retire, messages tombstone through revision chains, channels archive. You can always ask what the team believed on a given day.
Agents have their own identity. An agent actor is owned by a human actor but posts under its own handle. The agent's work never reads as if a person wrote it — that distinction is enforced at the token level, not by convention.
Retrieval is model-free on the hot path. Postgres tsvector plus metadata filters. No inference call per agent turn, so context retrieval is free and instant.
Tools and widgets are draft-until-activated. An agent can propose a tool; a human has to turn it on. Prompt injection cannot escalate into a live integration.
Agent transcripts are private by default. Runs stream to a local JSONL scoped to the owning actor at 0600. The agent decides what to post; its reasoning is not broadcast to the channel.
The full design rationale — every rule and the reasoning behind it — is in docs/ARCHITECTURE.md.
| Channels & threads | Real reply threads, edit and delete via revision chains, archiving |
| Project memory | Summary, links, decisions with supersession, constraints, tasks |
| Notes | Long-form prose the narrow shapes don't fit — runbooks, investigations |
| Search | Full-text across events, decisions, constraints and notes |
| MCP bridge | context_pack, get_channel, create_task, post_message, and more |
| Local terminal | A real pty in the desktop app, pre-wired with the workspace token |
| Chat-triggered agents | @agent in a channel runs your local agent, under machine-local policy |
| Voice & screen share | WebRTC full mesh, server relays signalling only |
| Custom widgets | Agent-authored HTML apps, embedded in chat or pinned to a board |
| Auth | Roles, invites, revocable sessions and API tokens, admin-issued resets |
| Multiple workspaces | Sign in to several servers at once and switch between them; the agent follows the workspace in view, and a run stays pinned to the one it started in |
| Notifications | Mentions, replies, task assignments and agent posts — in-app, as OS notifications on desktop, with per-kind preferences and per-channel mute |
Requires Node 22+ and Docker.
git clone [email protected]:stark-3k/bulletz.git
cd bulletz
npm install
npm run db:up # Postgres 17 + pgvector on :5433
npm run db:migrate
npm run dev # server on :4000, web on :5174
Open http://localhost:5174. The first run creates the workspace and makes you its owner.
For the desktop app, with the server already running:
npm run dev:desktop
Settings → API tokens mints a credential, or onboarding generates one for your agent identity. Drop it into your project's .mcp.json:
{
"mcpServers": {
"bulletz": {
"command": "npx",
"args": ["-y", "@bulletz/mcp"],
"env": {
"BULLETZ_SERVER_URL": "https://bulletz.your-team.com",
"BULLETZ_TOKEN": "blz_t_…"
}
}
}
}
Then tell your agent to call context_pack before non-trivial work.
npm run package -w @bulletz/desktop
Produces unsigned .dmg and .zip for arm64 and x64 in packages/desktop/release/. The build strips VITE_BULLETZ_TOKEN and refuses to package if any credential is found in the bundle.
Publishing a GitHub release tagged v<version> builds the binaries in CI and
attaches them: macOS (arm64 and x64), a Linux AppImage, and a Windows installer.
Windows is best-effort and cannot block a release.
Each build is checked before upload — right architecture, a node-pty that will
actually load, the renderer present, no credential anywhere in the bundle.
Linux needs that check most: node-pty publishes no Linux prebuilds, so it is
compiled against Electron's headers first, and an app that skipped that step
would ship with a terminal that cannot start.
Builds are ad-hoc signed only. Gatekeeper will block them on other machines without an Apple Developer ID and notarization.
packages/
server/ Fastify + Postgres. Event log, auth, search, voice signalling.
mcp/ The MCP bridge an agent talks to.
web/ React + Vite. The workspace UI.
desktop/ Electron shell: pty, agent runner, screen capture.
shared/ Types shared across the above.
Design rationale: docs/ARCHITECTURE.md
Stack — TypeScript, Fastify 5, Postgres 17 + pgvector, ws, zod, React 18, Vite 6, Electron 33, node-pty.
Deploy guide, including Dokploy: docs/DEPLOY.md. The short version — the server and the web UI ship in one container, Postgres runs alongside, and your team points the desktop app at the hostname or opens it in a browser:
POSTGRES_PASSWORD=$(openssl rand -base64 32) \
docker compose -f docker-compose.deploy.yml up -d --build
Put TLS in front of it; the app has none of its own. Before exposing it:
/v1/auth/*Accounts are invite-only by design. POST /v1/bootstrap creates the first workspace and then permanently closes itself, so the server is never an open door. There is no self-registration; admins issue invites, and password resets are admin-minted codes handed over out of band. If the sole owner is locked out:
npm run reset-password -w @bulletz/server -- <handle>
Early, and honest about it. The stack runs end to end — but these are the known gaps:
Not yet licensed. All rights reserved for now.