{"id":45150899,"url":"https://github.com/daveangulo/twining-mcp","last_synced_at":"2026-04-25T01:02:53.288Z","repository":{"id":338934653,"uuid":"1159629987","full_name":"daveangulo/twining-mcp","owner":"daveangulo","description":"Agent coordination MCP server — shared blackboard, decision tracking, and context assembly","archived":false,"fork":false,"pushed_at":"2026-03-21T19:29:01.000Z","size":3017,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-22T03:22:23.305Z","etag":null,"topics":["agent-coordination","ai-agents","claude","claude-code","decision-tracking","knowledge-graph","mcp","model-context-protocol"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/twining-mcp","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/daveangulo.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-17T00:41:23.000Z","updated_at":"2026-03-21T19:29:04.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/daveangulo/twining-mcp","commit_stats":null,"previous_names":["daveangulo/twining-mcp"],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/daveangulo/twining-mcp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daveangulo%2Ftwining-mcp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daveangulo%2Ftwining-mcp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daveangulo%2Ftwining-mcp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daveangulo%2Ftwining-mcp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/daveangulo","download_url":"https://codeload.github.com/daveangulo/twining-mcp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daveangulo%2Ftwining-mcp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31479006,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-06T14:34:32.243Z","status":"ssl_error","status_checked_at":"2026-04-06T14:34:31.723Z","response_time":112,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agent-coordination","ai-agents","claude","claude-code","decision-tracking","knowledge-graph","mcp","model-context-protocol"],"created_at":"2026-02-20T03:01:35.723Z","updated_at":"2026-04-25T01:02:53.275Z","avatar_url":"https://github.com/daveangulo.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"assets/logo.png\" alt=\"Twining\" width=\"400\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eYour AI agents forget everything. Twining remembers.\u003c/strong\u003e\u003cbr\u003e\n  Persistent project memory for Claude Code and other MCP clients.\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://www.npmjs.com/package/twining-mcp\"\u003e\u003cimg src=\"https://img.shields.io/npm/v/twining-mcp\" alt=\"npm version\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/daveangulo/twining-mcp/actions/workflows/ci.yml\"\u003e\u003cimg src=\"https://github.com/daveangulo/twining-mcp/actions/workflows/ci.yml/badge.svg\" alt=\"CI\"\u003e\u003c/a\u003e\n  \u003ca href=\"LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/badge/license-MIT-blue\" alt=\"MIT License\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n---\n\n## The Problem\n\nYou spend two hours with Claude Code making architectural decisions. You choose PostgreSQL over MongoDB. You settle on JWT for auth. You flag a race condition in the payment module. Then the session ends.\n\nTomorrow you start a new session. Claude has no idea what happened. The decisions are gone. The warnings are gone. The rationale is gone. You re-explain everything — or worse, Claude silently contradicts yesterday's choices.\n\nThis gets worse with multiple agents. Agent A decides on REST. Agent B picks gRPC for the same service. Neither knows the other exists. You find out when the code doesn't compile.\n\n**Context windows are ephemeral. Your project's decisions shouldn't be.**\n\n## How Twining Fixes It\n\nTwining is an MCP server that gives your AI agents persistent project memory. Decisions survive context resets. New sessions start informed. Multi-agent work stays coordinated.\n\n```\n# Install in 10 seconds\n/plugin marketplace add daveangulo/twining-mcp\n/plugin install twining@twining-marketplace\n```\n\n**Record what you did — in natural language:**\n```\ntwining_record({\n  summary: \"Added Redis caching to UserService\",\n  decisions: [\"Chose Redis over Memcached — need persistence across restarts\"],\n  assumptions: [\"Read-heavy workload (10:1 ratio)\"],\n  scope: \"src/services/\"\n})\n```\nTwining parses your decisions into structured records — extracting rationale, rejected alternatives, and domain automatically. One tool call, no forms.\n\n**Start a new session. Get caught up instantly:**\n```\ntwining_assemble({ task: \"optimize the caching layer\", scope: \"src/services/\" })\n```\nTwining scores every decision, warning, and finding by relevance to your task, then fills a token budget in priority order. You get exactly the context you need — no firehose, no re-explaining.\n\n**Ask why things are the way they are:**\n```\ntwining_why({ scope: \"src/auth/middleware.ts\" })\n```\nReturns the full decision chain for any file: what was decided, when, why, what alternatives were rejected, and which commit implemented it.\n\n## Why Not Just Use CLAUDE.md?\n\nCLAUDE.md is static. You write it once and update it manually. It doesn't capture decisions *as they happen*, doesn't track rationale or alternatives, doesn't detect conflicts between agents, and can't selectively assemble context within a token budget.\n\nTwining is dynamic. Every `twining_decide` call records a structured decision. Every `twining_post` shares a finding or warning. Every `twining_assemble` scores relevance and delivers precisely what the current task needs. The `.twining/` directory is your project's living institutional memory.\n\n## Why Not an Orchestrator?\n\nOrchestrators (like agent swarms and hierarchical coordinators) route work by *assigning tasks*. Twining coordinates by *sharing state*. The difference matters:\n\n- **Orchestrators** hold coordination context in their own context window — a single point of failure that degrades as the window fills\n- **Twining's blackboard** persists coordination state outside any agent's window, surviving context resets without information loss\n\nAgents self-select into work by reading the blackboard. No central bottleneck. No relay that drops context. Every agent sees every other agent's decisions and warnings, directly.\n\n## Install\n\n### Plugin Install (Recommended)\n\n```bash\n# Add the marketplace (one-time)\n/plugin marketplace add daveangulo/twining-mcp\n\n# Install the plugin\n/plugin install twining@twining-marketplace\n```\n\nIncludes the MCP server, skills, lifecycle hooks, and pre-commit enforcement. Two gates: `twining_assemble` before working, `twining_record` before committing — hooks enforce both automatically.\n\n### Team Auto-Install\n\nCommit this to your repo's `.claude/settings.json` so every team member gets Twining on clone:\n\n```json\n{\n  \"extraKnownMarketplaces\": {\n    \"twining-marketplace\": {\n      \"source\": {\n        \"source\": \"github\",\n        \"repo\": \"daveangulo/twining-mcp\"\n      }\n    }\n  },\n  \"enabledPlugins\": {\n    \"twining@twining-marketplace\": true\n  }\n}\n```\n\nWhen team members trust the repository folder, Claude Code automatically installs the marketplace and plugin.\n\n### MCP-Only Install\n\nFor non-Claude-Code clients (Cursor, Windsurf, etc.):\n\n```bash\nclaude mcp add twining -- npx -y twining-mcp --project .\n```\n\nOr add to `.mcp.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"twining\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"twining-mcp\", \"--project\", \".\"]\n    }\n  }\n}\n```\n\nMCP server instructions are included automatically in the initialize response.\n\n### Upgrading from Manual Install\n\nIf you previously configured Twining manually, switch to the plugin:\n\n1. Remove manual MCP server: `claude mcp remove twining`\n2. Install plugin: `/plugin marketplace add daveangulo/twining-mcp` then `/plugin install twining@twining-marketplace`\n3. Clean up: remove Twining hooks from `.claude/settings.json`, remove `.claude/agents/twining-aware.md` if present, remove Twining sections from `CLAUDE.md` (skills handle this now)\n4. Keep: `.twining/` directory (all state preserved)\n5. Verify: `/twining:status`\n\n### Get the Most Out of It\n\nThe plugin handles agent instructions automatically via skills. For the MCP-only install path, add Twining instructions to your project's `CLAUDE.md` so agents use it automatically — see **[docs/CLAUDE_TEMPLATE.md](docs/CLAUDE_TEMPLATE.md)** for a ready-to-copy template.\n\n### Dashboard\n\nA web dashboard starts automatically at `http://localhost:24282` — browse decisions, blackboard entries, knowledge graph, and agent state. Configurable via `TWINING_DASHBOARD_PORT`.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"assets/dashboard-stats.png\" alt=\"Dashboard — Stats overview\" width=\"700\"\u003e\u003cbr\u003e\n  \u003cem\u003eStats overview: blackboard entries, decisions, graph entities, and activity breakdown\u003c/em\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"assets/dashboard-graph.png\" alt=\"Dashboard — Knowledge graph\" width=\"700\"\u003e\u003cbr\u003e\n  \u003cem\u003eInteractive knowledge graph: files, decisions, classes, and their relationships\u003c/em\u003e\n\u003c/p\u003e\n\n## What's Inside\n\n### Core Tools (always available)\n\nThese are the tools agents use in every session:\n\n| Tool | What It Does |\n|------|-------------|\n| `twining_assemble` | **Gate 1:** Build tailored context for a task — decisions, warnings, handoffs, within a token budget |\n| `twining_record` | **Gate 2:** Record what you did and any choices made — natural language in, structured decisions out |\n| `twining_post` | Share findings, warnings, needs, or status during work |\n| `twining_why` | Check what decisions constrain a file before modifying it |\n| `twining_housekeeping` | Periodic maintenance — archive, deduplicate, surface stale decisions (dry-run by default) |\n\n`twining_record` accepts natural language decisions like `\"Chose Redis over Memcached — need persistence\"` and automatically parses them into structured records with rationale, rejected alternatives, and inferred domain. It also accepts assumptions, constraints, affected files, and dependency chains — everything the decision store needs for high-fidelity context assembly.\n\n### Extended Tools (available with `full_surface: true`)\n\nFor advanced workflows — deep decision management, graph exploration, multi-agent coordination:\n\n| Category | Tools |\n|----------|-------|\n| **Decisions** | `twining_decide`, `twining_search_decisions`, `twining_reconsider`, `twining_link_commit`, `twining_trace`, `twining_override`, `twining_promote`, `twining_commits` |\n| **Blackboard** | `twining_read`, `twining_query`, `twining_recent`, `twining_dismiss` |\n| **Context** | `twining_summarize`, `twining_what_changed` |\n| **Graph** | `twining_add_entity`, `twining_add_relation`, `twining_neighbors`, `twining_graph_query`, `twining_prune_graph` |\n| **Coordination** | `twining_register`, `twining_agents`, `twining_discover`, `twining_delegate`, `twining_handoff`, `twining_acknowledge` |\n| **Lifecycle** | `twining_verify`, `twining_status`, `twining_archive`, `twining_export` |\n\nEnable with `.twining/config.yml`:\n```yaml\ntools:\n  full_surface: true\n```\n\n## How It Works\n\nAll state lives in `.twining/` as plain files — JSONL for the blackboard, JSON for decisions, graph, agents, and handoffs. Everything is `jq`-queryable, `grep`-able, and git-diffable. No database. No cloud. No accounts.\n\n**Architecture layers:**\n\n- **Storage** — File-backed stores with locking for concurrent access\n- **Engine** — Decision tracking, blackboard, graph traversal, context assembly with token budgeting, agent coordination\n- **Embeddings** — Local all-MiniLM-L6-v2 via `@huggingface/transformers`, lazy-loaded, with keyword fallback. The server never fails to start because of embedding issues.\n- **Dashboard** — Read-only web UI with cytoscape.js graph visualization and vis-timeline\n- **Tools** — MCP tool definitions validated with Zod, mapping 1:1 to the tool surface\n\nSee [TWINING-DESIGN-SPEC.md](TWINING-DESIGN-SPEC.md) for the full specification.\n\n## FAQ\n\n**Does Twining slow down Claude Code?**\nNo. It's a local MCP server — tool calls are local file reads/writes. Semantic search loads lazily on first use.\n\n**Can I use it with Cursor, Windsurf, or other MCP clients?**\nYes. Twining is a standard MCP server. Any MCP host can connect to it.\n\n**Where does my data go?**\nAll coordination state is local in `.twining/`. Tool call metrics are stored locally in `.twining/metrics.jsonl` (gitignored). Optional anonymous telemetry can be enabled — see [Analytics](#analytics) below.\n\n**Is Twining an agent orchestrator?**\nNo. It's a coordination state layer. It captures what agents decided and why, and makes that knowledge available to future agents. Use it alongside orchestrators, agent teams, or standalone sessions.\n\n## Analytics\n\nTwining includes a three-layer analytics system to help you understand the value it provides.\n\n### Insights Dashboard Tab\n\nThe web dashboard includes an **Insights** tab showing:\n\n- **Value Metrics** — Blind decision prevention rate, warning acknowledgment, test coverage via `tested_by` graph relations, commit traceability, decision lifecycle, knowledge graph stats, and agent coordination metrics\n- **Tool Usage** — Call counts, error rates, average/P95 latency per tool\n- **Error Breakdown** — Errors grouped by tool and error code\n\nAll value metrics are computed from existing `.twining/` data — no new data collection needed.\n\n### Tool Call Metrics\n\nEvery MCP tool call is automatically instrumented with timing and success/error tracking. Metrics are stored locally in `.twining/metrics.jsonl` (gitignored — operational data, not architectural).\n\nTo disable local metrics collection, set in `.twining/config.yml`:\n\n```yaml\nanalytics:\n  metrics:\n    enabled: false\n```\n\n### Opt-in Telemetry\n\nAnonymous aggregate usage data can optionally be sent to PostHog to help improve Twining. **Disabled by default.** To enable, add to `.twining/config.yml`:\n\n```yaml\nanalytics:\n  telemetry:\n    enabled: true\n```\n\nThat's it — the PostHog project key is built into the source code. If you run your own PostHog instance, you can override with `posthog_api_key` and `posthog_host`.\n\n**What is sent:** tool names, call durations, success/failure booleans, server version, OS, architecture.\n\n**What is never sent:** file paths, decision content, agent names, error messages, tool arguments, environment variables.\n\n**Privacy safeguards:**\n- `DO_NOT_TRACK=1` environment variable always overrides config\n- `CI=true` auto-disables telemetry\n- Identity is a SHA-256 hash of hostname + project root (never raw paths)\n- Network failures are silent — no retries\n- `posthog-node` is an optional dependency — graceful no-op if not installed\n\n## Development\n\n```bash\nnpm install       # Install dependencies\nnpm run build     # Build\nnpm test          # Run tests (800+ tests)\nnpm run test:watch\n```\n\nRequires Node.js \u003e= 18.\n\n### CI/CD\n\nTwo GitHub Actions workflows automate build verification and publishing:\n\n**CI** (`.github/workflows/ci.yml`) — runs on every PR and push to `main`:\n- Builds and tests across Node 18, 20, and 22\n- Cancels in-progress runs when a new push arrives on the same branch\n\n**Publish** (`.github/workflows/publish.yml`) — runs on `v*` tag push:\n- Builds with `POSTHOG_API_KEY` baked in for published packages\n- Runs the full test suite as defense-in-depth\n- Publishes to npm with `--provenance` for supply chain attestation\n- Creates a GitHub Release with auto-generated release notes\n- Supports manual trigger via `workflow_dispatch` with a dry-run option\n\n**To publish a new version:**\n\n```bash\nnpm version patch   # or minor, major\ngit push \u0026\u0026 git push --tags\n```\n\n**Required secrets** (configured in GitHub repo Settings \u003e Secrets):\n\n| Secret | Purpose |\n|--------|---------|\n| `NPM_TOKEN` | npm access token (granular, scoped to `twining-mcp`) |\n| `POSTHOG_API_KEY` | PostHog ingest key for published packages |\n\n## License\n\n[MIT](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdaveangulo%2Ftwining-mcp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdaveangulo%2Ftwining-mcp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdaveangulo%2Ftwining-mcp/lists"}