{
  "markdown": "# limps\n\n**L**ocal **I**ntelligent **M**CP **P**lanning **S**erver — A document and planning layer for AI assistants. No subscriptions, no cloud. Point limps at **any folder** (local, synced, or in git). One shared source of truth across Claude, Cursor, Codex, and any MCP-compatible tool.\n\n[![npm](https://img.shields.io/npm/v/@sudosandwich/limps)](https://www.npmjs.com/package/@sudosandwich/limps)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n![Tests](https://img.shields.io/badge/Tests-1488%20passing-brightgreen)\n![Coverage](https://img.shields.io/badge/Coverage-%3E70%25-brightgreen)\n[![MCP Badge](https://lobehub.com/badge/mcp/paulbreuler-limps)](https://lobehub.com/mcp/paulbreuler-limps)\n\n![limps in action](https://github.com/paulbreuler/limps/blob/main/.github/assets/limps-a-lol-longer.gif?raw=true)\n\n## Table of Contents\n\n- [Quick Start](#quick-start)\n- [Features](#features)\n- [How I Use limps](#how-i-use-limps)\n- [Health & Automation](#health--automation)\n- [How You Can Use It](#how-you-can-use-it)\n- [Why limps?](#why-limps)\n- [Installation](#installation)\n- [Upgrading from v2](#upgrading-from-v2)\n- [Project Setup](#project-setup)\n- [Client Setup](#client-setup)\n- [Transport](#transport)\n- [Daemon Management](#daemon-management)\n- [CLI Commands](#cli-commands)\n- [Configuration](#configuration)\n- [Environment Variables](#environment-variables)\n- [Troubleshooting](#troubleshooting)\n- [MCP Tools](#mcp-tools)\n- [Skills & Commands](#skills--commands)\n- [Extensions](#extensions)\n- [Obsidian Compatibility](#obsidian-compatibility)\n- [Development](#development)\n- [Used in Production](#used-in-production)\n- [Creating a feature plan](#creating-a-feature-plan)\n- [Deep Dive](#deep-dive)\n- [What is MCP?](#what-is-mcp)\n- [License](#license)\n\n## Quick Start\n\n```bash\n# Install globally\nnpm install -g @sudosandwich/limps\n\n# Initialize in your project\ncd ~/Documents/my-planning-docs\nlimps init\n\n# Start the HTTP daemon\nlimps server start\n# → Daemon starts on http://127.0.0.1:4269/mcp\n# → PID file written to OS-standard location\n# → Ready for MCP client connections\n\n# Generate MCP client config\nlimps config print --client claude-code\n# Copy the output to your MCP client config file\n```\n\nThat's it. Your AI assistant now has access to your documents via HTTP transport. The folder can be anywhere—local, synced, or in a repo; limps does not require a git repository or a `plans/` directory.\n\n**Tip:** `limps server status` always includes system-wide daemon discovery. If a project config is found (or passed via `--config`), it also reconciles the configured project target against that global list.\n\n## Features\n\n- **Document CRUD + full-text search** across any folder of Markdown files\n- **Plan + agent workflows** with status tracking and task scoring\n- **Next-task suggestions** with score breakdowns and bias tuning\n- **Sandboxed document processing** via `process_doc(s)` helpers\n- **Multi-client support** for Cursor, Claude, Codex, and more\n- **Extensions** for domain-specific tooling (e.g., limps-headless)\n- **Knowledge graph** — Entity extraction, hybrid retrieval, conflict detection, and graph-based suggestions\n- **Health automation** — Staleness detection, code drift checks, status inference, and auto-fix proposals\n- **Advanced task scoring** — Dependency-aware prioritization with per-plan/agent weight overrides\n- **MCP Registry** — Published to the official MCP Registry (`registry.modelcontextprotocol.io`)\n\n### What to know before you start\n\n- **Local only** — Your data stays on disk (SQLite index + your files). No cloud, no subscription.\n- **Restart after changes** — If you change the indexed folder or config, restart the MCP server (or rely on the file watcher) so the index and tools reflect the current state.\n- **Daemon management** — The HTTP server runs as a background process. Use `limps server start`, `limps server stop`, and `limps server status` to manage the daemon lifecycle. PID files are stored in OS-standard directories for system-wide awareness.\n- **Sandboxed user code** — `process_doc` and `process_docs` run your JavaScript in a QuickJS sandbox with time and memory limits; no network or Node APIs.\n- **One optional network call** — `limps version --check` fetches from the npm registry to compare versions. All other commands (serve, init, list, search, create/update/delete docs, process_doc, etc.) do **not** contact the internet. Omit `version --check` if you want zero external calls.\n\n## How I Use limps\n\nI use `limps` as a local planning layer across multiple AI tools, focused on **create → read → update → closure** for plans and tasks. The MCP server points at whatever directory I want (not necessarily a git repo), so any client reads and updates the same source of truth.\n\nTypical flow:\n\n1. Point limps at a docs directory (any folder, local or synced).\n2. Use CLI + MCP tools to create plans/docs, read the current status, update tasks, and close work when done.\n3. Add the limps MCP entry to each client config so Cursor/Claude/Codex all see the same plans.\n\nCommands and tools I use most often:\n\n- **Create**: `limps init`, `create_plan`, `create_doc`\n- **Read**: `list_plans`, `list_agents`, `list_docs`, `search_docs`, `get_plan_status`\n- **Update**: `update_doc`, `update_task_status`, `manage_tags`\n- **Close**: `update_task_status` (e.g., `PASS`), `delete_doc` if needed\n- **Analyze**: `graph health`, `graph search`, `graph check`, `health check`\n\nFull lists are below in \"CLI Commands\" and \"MCP Tools.\"\n\n## How You Can Use It\n\n`limps` is designed to be generic and portable. Point it at **any folder** with Markdown files and use it from any MCP-compatible client. **No git repo required.** **Not limited to planning**—planning (plans, agents, task status) is one use case; the same layer gives you document CRUD, full-text search, and programmable processing on any indexed folder.\n\nCommon setups:\n\n- **Single project**: One docs folder for a product.\n- **Multi-project**: Each project gets its own `.limps/config.json`; pass `--config` to target a specific one.\n- **Shared team folder**: Put plans in a shared location and review changes like code.\n- **Local-first**: Keep everything on disk, no hosted service required.\n\nKey ideas:\n\n- **Any folder** — You choose the path; if there’s no `plans/` subdir, the whole directory is indexed. Use generic tools (`list_docs`, `search_docs`, `create_doc`, `update_doc`, `delete_doc`, `process_doc`, `process_docs`) or plan-specific ones (`create_plan`, `list_plans`, `list_agents`, `get_plan_status`, `update_task_status`, `get_next_task`).\n- **One source of truth** — MCP tools give structured access; multiple clients share the same docs.\n\n## Why limps?\n\n**The problem:** Each AI assistant maintains its own context. Planning documents, task status, and decisions get fragmented across Claude, Cursor, ChatGPT, and Copilot conversations.\n\n**The solution:** limps provides a standardized MCP interface that any tool can access. Your docs live in one place—a folder you choose. Use git (or any sync) if you want version control; limps is not tied to a repository.\n\n## Installation\n\n```bash\nnpm install -g @sudosandwich/limps\n```\n\n## Upgrading from v2\n\nv3 introduces major changes:\n\n### HTTP Transport (Breaking Change)\n\nv3 uses **HTTP transport exclusively**. stdio transport has been removed.\n\n**Migration steps:**\n\n1. **Start the HTTP daemon** for each project:\n   ```bash\n   limps server start --config /path/to/.limps/config.json\n   ```\n\n2. **Update MCP client configs** — Replace stdio configs with HTTP transport:\n   ```json\n   {\n     \"mcpServers\": {\n       \"limps-planning-myproject\": {\n         \"transport\": {\n           \"type\": \"http\",\n           \"url\": \"http://127.0.0.1:4269/mcp\"\n         }\n       }\n     }\n   }\n   ```\n   Use `limps config print` to generate the correct snippet.\n\n### Per-Project Configs (Breaking Change)\n\nv3 removes the centralized project registry. If you previously used `limps config add`, `config use`, or the `--project` flag:\n\n1. **Run `limps init`** in each project directory to create `.limps/config.json`.\n2. **Update MCP client configs** — Replace `--project <name>` with HTTP transport config (see above).\n3. **Remove environment variable** — `LIMPS_PROJECT` no longer exists. Use `MCP_PLANNING_CONFIG` to override config path.\n\n**Removed commands:** `config list`, `config use`, `config add`, `config remove`, `config set`, `config discover`, `config migrate`, `config sync-mcp`, `serve`.\n\n**Replaced by:** `limps init` + `limps server start` + `limps config print`.\n\n## Project Setup\n\n### Initialize a New Project\n\n```bash\ncd ~/Documents/my-planning-docs\nlimps init\n```\n\nThis creates `.limps/config.json` in the current directory and prints MCP client setup instructions.\n\nYou can also specify a path:\n\n```bash\nlimps init ~/Documents/my-planning-docs\n```\n\nIf the directory contains a `plans/` subdirectory, limps uses it. Otherwise, it indexes the entire directory.\n\n### Multiple Projects\n\nEach project has its own `.limps/config.json`. Use `--config` to target a specific project:\n\n```bash\nlimps plan list --config ~/docs/project-b/.limps/config.json\n```\n\n## Client Setup\n\nAfter running `limps init`, you need to add a limps entry to your MCP client's config file. Use `limps config print` to generate the correct snippet for your client, then paste it into the appropriate config file:\n\n```bash\nlimps config print --client cursor\nlimps config print --client claude-code\nlimps config print --client claude\n```\n\nThe output tells you exactly what JSON (or TOML) to add and where the config file lives.\n\n### Per-Client Examples\n\nAll clients connect to the HTTP daemon. Start the daemon first with `limps server start`, then configure your client.\n\n<details>\n<summary><b>Cursor</b></summary>\n\nAdd to `.cursor/mcp.json` in your project:\n\n```json\n{\n  \"mcpServers\": {\n    \"limps-planning-myproject\": {\n      \"transport\": {\n        \"type\": \"http\",\n        \"url\": \"http://127.0.0.1:4269/mcp\"\n      }\n    }\n  }\n}\n```\n\n</details>\n\n<details>\n<summary><b>Claude Code</b></summary>\n\nAdd to `.mcp.json` in your project root:\n\n```json\n{\n  \"mcpServers\": {\n    \"limps-planning-myproject\": {\n      \"transport\": {\n        \"type\": \"http\",\n        \"url\": \"http://127.0.0.1:4269/mcp\"\n      }\n    }\n  }\n}\n```\n\n</details>\n\n<details>\n<summary><b>Claude Desktop</b></summary>\n\nAdd to `~/Library/Application Support/Claude/claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"limps-planning-myproject\": {\n      \"transport\": {\n        \"type\": \"http\",\n        \"url\": \"http://127.0.0.1:4269/mcp\"\n      }\n    }\n  }\n}\n```\n\n</details>\n\n<details>\n<summary><b>OpenAI Codex</b></summary>\n\nAdd to `~/.codex/config.toml`:\n\n```toml\n[mcp_servers.limps-planning-myproject.transport]\ntype = \"http\"\nurl = \"http://127.0.0.1:4269/mcp\"\n```\n\n</details>\n\n<details>\n<summary><b>ChatGPT</b></summary>\n\nChatGPT requires a remote MCP server over HTTPS. Deploy limps behind an MCP-compatible HTTPS reverse proxy (nginx, Caddy, etc.) with authentication.\n\nIn ChatGPT → Settings → Connectors → Add custom connector:\n\n- **Server URL**: `https://your-domain.example/mcp`\n- **Authentication**: Configure as needed for your proxy\n\nPrint setup instructions:\n\n```bash\nlimps config print --client chatgpt\n```\n\n</details>\n\n## Transport\n\nlimps v3 uses **HTTP transport exclusively** via a persistent daemon. This allows multiple MCP clients to share a single server instance, avoiding file descriptor bloat from multiple stdio processes.\n\n### Start the HTTP daemon\n\n```bash\n# Start the daemon\nlimps server start\n\n# Check status (shows uptime, sessions, PID)\nlimps server status\n\n# Stop the daemon\nlimps server stop\n```\n\nThe daemon runs at `http://127.0.0.1:4269/mcp` by default. Use `limps config print` to generate the correct MCP client configuration:\n\n```bash\nlimps config print --client claude-code\n```\n\nSee [Daemon Management](#daemon-management) for detailed lifecycle documentation.\n\n### MCP Client Configuration\n\nAll clients use HTTP transport. Example config:\n\n```json\n{\n  \"mcpServers\": {\n    \"limps-planning-myproject\": {\n      \"transport\": {\n        \"type\": \"http\",\n        \"url\": \"http://127.0.0.1:4269/mcp\"\n      }\n    }\n  }\n}\n```\n\n### Server Config Options\n\nCustomize the HTTP server by adding a `\"server\"` section to your `config.json`:\n\n| Option             | Default                | Description                              |\n| ------------------ | ---------------------- | ---------------------------------------- |\n| `port`             | `4269`                 | HTTP listen port                         |\n| `host`             | `127.0.0.1`            | Bind address                             |\n| `maxSessions`      | `100`                  | Maximum concurrent MCP sessions          |\n| `sessionTimeoutMs` | `1800000`              | Session idle timeout in ms (30 min)      |\n| `corsOrigin`       | `\"\"` (none)            | CORS origin (`\"\"`, `\"*\"`, or a URL)      |\n| `maxBodySize`      | `10485760`             | Max request body in bytes (10 MB)        |\n| `rateLimit`        | `100 req/min`          | Rate limit per client IP                 |\n\nExample custom server config:\n\n```json\n{\n  \"server\": {\n    \"port\": 8080,\n    \"host\": \"0.0.0.0\"\n  }\n}\n```\n\n**Note:** PID files are stored in OS-standard application directories:\n- **macOS**: `~/Library/Application Support/limps/pids/`\n- **Linux**: `$XDG_DATA_HOME/limps/pids/` or `~/.local/share/limps/pids/`\n- **Windows**: `%APPDATA%/limps/pids/`\n\nThis enables `limps server status` to perform system-wide daemon discovery from any directory. When a limps config is found for the current directory (or passed via `--config`), the CLI also reports and reconciles that project's configured target.\n\n- **Remote clients**: Use an MCP-compatible HTTPS proxy for remote clients (e.g., ChatGPT).\n\n## Daemon Management\n\nlimps v3 uses a persistent HTTP daemon with system-wide awareness. PID files are stored in OS-standard directories, allowing you to manage and discover daemons from any directory on your system.\n\n### PID File Locations\n\nPID files are stored in platform-specific application data directories:\n\n**macOS:**\n```\n~/Library/Application Support/limps/pids/\n```\n\n**Linux:**\n```\n$XDG_DATA_HOME/limps/pids/\n# or if XDG_DATA_HOME is not set:\n~/.local/share/limps/pids/\n```\n\n**Windows:**\n```\n%APPDATA%/limps/pids/\n```\n\nEach PID file is named by port number (`limps-{port}.pid`) to enable system-wide discovery. Example PID file structure:\n\n```json\n{\n  \"pid\": 12345,\n  \"port\": 4269,\n  \"host\": \"127.0.0.1\",\n  \"startedAt\": \"2026-02-08T12:00:00.000Z\",\n  \"configPath\": \"/path/to/project/.limps/config.json\",\n  \"logPath\": \"/Users/you/Library/Application Support/limps/logs/limps-4269.log\"\n}\n```\n\nThis port-based naming allows `limps server status` to find all running daemons across different projects without needing a config file.\n\nDaemon logs are written to OS-standard application log directories:\n\n**macOS:**\n```\n~/Library/Application Support/limps/logs/\n```\n\n**Linux:**\n```\n$XDG_DATA_HOME/limps/logs/\n# or if XDG_DATA_HOME is not set:\n~/.local/share/limps/logs/\n```\n\n**Windows:**\n```\n%APPDATA%/limps/logs/\n```\n\nDaemon logs are intentionally operational-only: limps redacts uncaught exception/rejection payloads and does not persist raw AI prompt/response content.\nDaemon log files are append-only and are not auto-rotated; if you run long-lived daemons, rotate or truncate these files with your system tooling.\n\n### Starting the Daemon\n\n**Background mode (default):**\n\n```bash\nlimps server start\n# → Daemon starts on http://127.0.0.1:4269/mcp\n# → PID file written to OS-standard location\n# → Logs written to OS-standard log file (append mode)\n# → Process detaches and runs in background\n```\n\n**Foreground mode (debugging):**\n\n```bash\nlimps server start --foreground\n# → Runs in foreground (blocks terminal)\n# → Logs appear in stderr\n# → Useful for debugging startup issues\n# → Still creates PID file for discovery\n```\n\n**Custom port/host (via config):**\n\nConfigure `server.port` and `server.host` in your `.limps/config.json`:\n\n```json\n{\n  \"server\": {\n    \"port\": 8080,\n    \"host\": \"0.0.0.0\"\n  }\n}\n```\n\nThen start normally:\n\n```bash\nlimps server start\n# → Starts using server.port/server.host from config\n# → PID file: limps-8080.pid\n```\n\nThe `start` command performs health verification by polling the `/health` endpoint for up to 5 seconds, issuing repeated HTTP requests. Each individual health-check request has its own shorter timeout (for example, ~1000ms). If any request fails during this window, you'll see one of these error codes:\n\n- **TIMEOUT** — A single health-check HTTP request exceeded its per-request timeout (e.g., ~1000ms). The daemon may be slow to start or system resources may be constrained. Try `limps server start --foreground` to see logs.\n- **NETWORK_ERROR** — Cannot connect to daemon. Port may be blocked or already in use by another process.\n- **NON_200_STATUS** — Health endpoint returned a non-200 status code. Check daemon logs with foreground mode.\n- **INVALID_RESPONSE** — Health endpoint responded, but the response was invalid or could not be parsed as expected (for example, malformed or missing required fields).\n\n### Checking Daemon Status\n\n**With project config (reconciled with global discovery):**\n\n```bash\n# From within a project directory with .limps/config.json\nlimps server status\n# Project target:\n# limps server is running\n# PID: 12345 | 127.0.0.1:4269\n# Uptime: 2h 15m\n# Sessions: 3\n# Log: /Users/you/Library/Application Support/limps/logs/limps-4269.log\n# Project target is present in system-wide daemon discovery.\n# System-wide daemons:\n# 127.0.0.1:4269 (PID 12345) [project target]\n#   Uptime: 2h 15m | Sessions: 3\n#   Log: /Users/you/Library/Application Support/limps/logs/limps-4269.log\n\n# Or specify config explicitly\nlimps server status --config /path/to/.limps/config.json\n```\n\n**Without project config (global discovery only):**\n\n```bash\n# From a directory without a limps config\ncd /tmp\nlimps server status\n# Found 2 running daemons:\n# 127.0.0.1:4269 (PID 12345)\n#   Uptime: 2h 15m | Sessions: 3\n#   Log: /Users/you/Library/Application Support/limps/logs/limps-4269.log\n# 127.0.0.1:8080 (PID 67890)\n#   Uptime: 45m 30s | Sessions: 1\n#   Log: /Users/you/Library/Application Support/limps/logs/limps-8080.log\n```\n\nWhen `limps server status` cannot resolve a config file in the current directory (and no `--config` is provided), it reports global daemon discovery only. When a config is found, it reports both the configured project target and the global daemon list.\n\n### Stopping the Daemon\n\n```bash\n# From the project directory (where your .limps config lives):\nlimps server stop\n# → Gracefully shuts down daemon\n# → Closes all MCP sessions\n# → Stops file watchers\n# → Removes PID file\n# → Process exits\n\n# Or from any directory, by specifying the config explicitly:\nlimps server stop --config /path/to/.limps/config.json\n```\n\nThe `stop` command is project-specific and resolves the config to determine which daemon to stop. The daemon performs a graceful shutdown by:\n1. Closing all active MCP sessions\n2. Shutting down file watchers\n3. Removing the PID file\n4. Exiting the process\n\n### Port Conflicts\n\nIf you try to start a daemon on a port that's already in use, limps will detect the conflict and provide resolution guidance:\n\n```bash\nlimps server start\n# Error: Port 4269 is already in use.\n# Process using port: node (PID 12345)\n# Command: /usr/local/bin/node /usr/local/bin/limps server start\n#\n# To stop the process: kill 12345\n# Or use a different port: limps server start --port <port>\n```\n\nOn systems with `lsof` available (macOS, Linux), limps can identify which process is using the port and show its command line. If `lsof` is not available, you'll see a simpler error message suggesting a different port.\n\n### Foreground Mode\n\nUse foreground mode for debugging, Docker deployments, or CI/CD pipelines:\n\n```bash\nlimps server start --foreground\n```\n\n**Use cases:**\n- **Debugging** — See server logs in real-time to diagnose startup issues\n- **Docker** — Keep container alive with the daemon as the main process\n- **CI/CD** — Run tests against a limps daemon without background processes\n\n**Behavior differences from background mode:**\n- Logs to stderr instead of being silent\n- Blocks the terminal (press Ctrl+C to stop)\n- Still creates a PID file for discovery by other processes\n- Responds to SIGINT (Ctrl+C) and SIGTERM for graceful shutdown\n\n### Health Endpoint\n\nThe HTTP daemon exposes a `/health` endpoint for monitoring and health checks:\n\n```bash\ncurl http://127.0.0.1:4269/health\n```\n\n**Example response:**\n\n```json\n{\n  \"status\": \"ok\",\n  \"sessions\": 3,\n  \"uptime\": 8145,\n  \"pid\": 12345,\n  \"sessionTimeoutMs\": 1800000\n}\n```\n\n**HTTP status codes:**\n- **200** — Daemon is healthy and accepting connections\n- **429** — Rate limit exceeded (rate limiter may return this before the request reaches `/health`)\n\n### Session Management & Reconnection\n\nSessions automatically expire after 30 minutes of inactivity (configurable via `sessionTimeoutMs`). When a session expires, MCP clients receive a specific error response indicating they should reconnect.\n\n**Session Expiration Response:**\n\nWhen a session expires or is closed, subsequent requests with that session ID return:\n\n```json\n{\n  \"error\": \"Session expired\",\n  \"code\": \"SESSION_EXPIRED\",\n  \"message\": \"Session expired due to timeout. Please reconnect without session ID.\",\n  \"expiredAt\": \"2026-02-11T10:30:00.000Z\"\n}\n```\n\n**Headers:**\n- `X-Session-Expired: true`\n- `X-Session-Expired-Reason: timeout` (or `closed`, `deleted`)\n\n**MCP Client Reconnection Flow:**\n\nWhen receiving `SESSION_EXPIRED`, clients should:\n\n1. **Clear the stored session ID** — Remove the cached `mcp-session-id`\n2. **Create a new session** — Send POST to `/mcp` **without** the session ID header\n3. **Store the new session ID** — Save the new `mcp-session-id` from response headers\n4. **Retry the original request** — Resubmit with the new session ID\n\n**Configuration:**\n\nAdjust session timeout in `.limps/config.json`:\n\n```json\n{\n  \"server\": {\n    \"sessionTimeoutMs\": 3600000  // 1 hour (default: 1800000 = 30 min)\n  }\n}\n```\n\nSet to `0` to disable timeout (sessions persist until server restart).\n\n**Expired Session Tracking:**\n\nThe server tracks expired sessions for 24 hours to help clients distinguish between \"session expired\" vs \"session never existed\":\n- `SESSION_EXPIRED` — Session previously existed but timed out (client should reconnect)\n- `SESSION_NOT_FOUND` — Session ID was never valid (possible server restart or invalid ID)\n\nUse this endpoint for:\n- Monitoring daemon health in scripts or dashboards\n- Verifying daemon is running before connecting MCP clients\n- Automated health checks in orchestration tools (Kubernetes, Docker Compose)\n\n### Multiple Daemons\n\nYou can run multiple limps daemons on different ports for different projects by configuring different ports in each project's config:\n\n```bash\n# Project A with default port (4269)\ncd ~/projects/project-a\n# .limps/config.json has server.port: 4269 (or uses default)\nlimps server start\n# → Running on http://127.0.0.1:4269/mcp\n\n# Project B with custom port (8080)\ncd ~/projects/project-b\n# .limps/config.json has server.port: 8080\nlimps server start\n# → Running on http://127.0.0.1:8080/mcp\n```\n\nEach daemon has its own PID file:\n- `limps-4269.pid` — Project A\n- `limps-8080.pid` — Project B\n\nDiscover all running daemons (run from a directory without a limps config):\n\n```bash\ncd /tmp\nlimps server status\n# Found 2 running daemons:\n# 127.0.0.1:4269 (PID 12345)\n#   Uptime: 2h 15m | Sessions: 3\n# 127.0.0.1:8080 (PID 67890)\n#   Uptime: 45m 30s | Sessions: 1\n```\n\nEach MCP client can connect to different daemons by configuring different URLs in their config files.\n\n## CLI Commands\n\n### Recommended Grouped Commands\n\n```bash\nlimps plan list                              # List all plans with status\nlimps plan agents <plan>                     # List agents in a plan\nlimps plan status <plan>                     # Show plan progress summary\nlimps plan next <plan>                       # Get highest-priority available task\nlimps plan score --plan <plan> --agent <n>  # Score a single task\nlimps plan scores --plan <plan>              # Score all available tasks in a plan\nlimps docs list [path]                       # List files/directories\nlimps docs search <query>                    # Search indexed docs\nlimps docs process [path] --code \"<js>\"      # Process docs with JavaScript\nlimps server start                           # Start HTTP daemon\nlimps server status                          # Show daemon status\nlimps server stop                            # Stop HTTP daemon\n```\n\n### Project Management\n\n```bash\nlimps init [path]             # Initialize new project\nlimps config show             # Display current config\nlimps config print            # Print MCP client config snippets\nlimps completion zsh          # Generate Zsh tab-completion script\n```\n\n### Health & Automation\n\n```bash\nlimps health check              # Aggregate all health signals\nlimps health staleness [plan]   # Find stale plans/agents\nlimps health inference [plan]   # Suggest status updates\nlimps proposals [plan]           # List auto-fix proposals\nlimps proposals apply <id>       # Apply a proposal\nlimps proposals apply-safe       # Apply all safe proposals\n```\n\n### Knowledge Graph\n\n```bash\nlimps graph reindex              # Build/rebuild graph\nlimps graph health               # Graph stats and conflicts\nlimps graph search <query>       # Search entities\nlimps graph trace <entity>       # Trace relationships\nlimps graph entity <id>          # Entity details\nlimps graph overlap              # Find overlapping features\nlimps graph check [type]         # Run conflict detection\nlimps graph suggest <type>       # Graph-based suggestions\nlimps graph watch                # Watch and update incrementally\n```\n\n### Scoring & Repair\n\n```bash\nlimps plan scores --plan <plan>                # Score all agents in a plan\nlimps plan score --plan <plan> --agent <n>   # Score a single task\nlimps plan repair [--fix]                   # Check/fix agent frontmatter\n```\n\n## Configuration\n\nConfig lives at `.limps/config.json` in your project directory, created by `limps init`.\n\n### Config Options\n\n```json\n{\n  \"plansPath\": \"./plans\",\n  \"docsPaths\": [\".\"],\n  \"fileExtensions\": [\".md\"],\n  \"dataPath\": \".limps/data\",\n  \"extensions\": [\"@sudosandwich/limps-headless\"],\n  \"tools\": {\n    \"allowlist\": [\"list_docs\", \"search_docs\"]\n  },\n  \"scoring\": {\n    \"weights\": { \"dependency\": 40, \"priority\": 30, \"workload\": 30 },\n    \"biases\": {}\n  }\n}\n```\n\n| Option           | Description                                                |\n| ---------------- | ---------------------------------------------------------- |\n| `plansPath`      | Directory for structured plans (`NNNN-name/` with agents)  |\n| `docsPaths`      | Additional directories to index                            |\n| `fileExtensions` | File types to index (default: `.md`)                       |\n| `dataPath`       | SQLite database location                                   |\n| `tools`          | Tool allowlist/denylist filtering                          |\n| `extensions`     | Extension packages to load                                 |\n| `scoring`        | Task prioritization weights and biases                     |\n| `server`         | HTTP daemon settings (port, host, CORS, sessions, timeout) |\n| `graph`          | Knowledge graph settings (e.g., entity extraction options) |\n| `retrieval`      | Search recipe configuration for hybrid retrieval           |\n\n## Environment Variables\n\n| Variable               | Description                                                | Example                                           |\n| ---------------------- | ---------------------------------------------------------- | ------------------------------------------------- |\n| `MCP_PLANNING_CONFIG`  | Path to config file (overrides default discovery)          | `MCP_PLANNING_CONFIG=./my-config.json limps server bridge`|\n| `LIMPS_ALLOWED_TOOLS`  | Comma-separated allowlist; only these tools are registered | `LIMPS_ALLOWED_TOOLS=\"list_docs,search_docs\"`     |\n| `LIMPS_DISABLED_TOOLS` | Comma-separated denylist; tools to hide                    | `LIMPS_DISABLED_TOOLS=\"process_doc,process_docs\"` |\n\n**Precedence:** `config.tools` overrides env vars. If allowlist is set, denylist is ignored.\n\n## Troubleshooting\n\n### Daemon Won't Start\n\n**\"Port already in use\" error:**\n\nIf you see this error, another process is using the port:\n\n```bash\nlimps server start\n# Error: Port 4269 is already in use.\n# Process using port: node (PID 12345)\n```\n\n**Resolution:**\n1. **Kill the existing process**: `kill 12345`\n2. **Or use a different port**: `limps server start --port 8080`\n3. **Check if it's another limps daemon**: `limps server status` (if so, use `limps server stop` first)\n\n**\"Daemon may have failed to start\" error:**\n\nIf the daemon starts but doesn't respond to health checks:\n\n```bash\nlimps server start\n# Error: Daemon may have failed to start. Check logs or try: limps server start --foreground\n```\n\n**Resolution:**\n1. **Check daemon log path**: `limps server status` (or run foreground mode: `limps server start --foreground`)\n2. **Check for permission issues**: Ensure you have write access to the PID directory\n3. **Verify port is accessible**: Try `curl http://127.0.0.1:4269/health`\n4. **Enable debug logging**: `DEBUG=1 limps server start --foreground`\n\n**Permission issues with PID directory:**\n\nIf you can't create PID files:\n\n```bash\n# macOS\nls -la ~/Library/Application\\ Support/limps/pids/\n\n# Linux\nls -la ~/.local/share/limps/pids/\n\n# Windows\ndir %APPDATA%\\limps\\pids\n```\n\nEnsure the directory exists and you have write permissions. If not, create it manually:\n\n```bash\n# macOS\nmkdir -p ~/Library/Application\\ Support/limps/pids\n\n# Linux\nmkdir -p ~/.local/share/limps/pids\n\n# Windows\nmkdir %APPDATA%\\limps\\pids\n```\n\n### Health Check Failures\n\n**TIMEOUT error:**\n\nThe daemon did not respond within the configured timeout. Each health-check request has its own timeout (for example, 1000ms during the final `limps server start` check and 3000ms for `limps server status`), and during startup limps will poll for up to about 5 seconds before reporting \"Daemon may have failed to start\".\n\n**Common causes:**\n- System resource constraints (high CPU/memory usage)\n- Slow filesystem (especially for index initialization)\n- Large document corpus requiring time to index\n\n**Resolution:**\n1. Check system resources: `top` or Activity Monitor\n2. Wait a bit longer and retry: `limps server status`\n3. Run in foreground to see progress: `limps server start --foreground`\n\n**NETWORK_ERROR:**\n\nCannot establish connection to the daemon.\n\n**Common causes:**\n- Port is blocked by firewall\n- Daemon crashed after starting\n- Incorrect host/port configuration\n\n**Resolution:**\n1. Verify daemon is running: `limps server status`\n2. Check firewall settings for port 4269\n3. Try `curl http://127.0.0.1:4269/health` manually\n4. Check daemon logs: see `Log:` path in `limps server status` output\n\n### Stale PID Files\n\nlimps automatically cleans up stale PID files when:\n- Running `limps server status` (discovers and removes stale files)\n- Running `limps server start` (removes stale file for the target port)\n- The daemon shuts down gracefully with `limps server stop`\n\nIf you need to manually clean up PID files:\n\n```bash\n# macOS\nrm ~/Library/Application\\ Support/limps/pids/limps-*.pid\n\n# Linux\nrm ~/.local/share/limps/pids/limps-*.pid\n\n# Windows\ndel %APPDATA%\\limps\\pids\\limps-*.pid\n```\n\n**When to manually clean up:**\n- After a system crash or forced shutdown\n- If `limps server start` reports a daemon is running but it's not\n- Before uninstalling limps\n\n### Multiple Daemons Conflict\n\nIf you accidentally try to start a second daemon on the same port:\n\n```bash\nlimps server start\n# Error: limps daemon already running (PID 12345 on 127.0.0.1:4269). Run 'limps server stop' first.\n```\n\nThis is expected behavior — limps prevents multiple daemons on the same port using PID-based locking.\n\n**Resolution:**\n1. **Check all running daemons**: `limps server status`\n2. **Stop the existing daemon**: `limps server stop`\n3. **Or start on a different port**: `limps server start --port 8080`\n\n### Debugging Connection Issues\n\nIf MCP clients can't connect to the daemon, verify connectivity step by step:\n\n**1. Check daemon status:**\n\n```bash\nlimps server status\n# Should show daemon running with healthy status\n```\n\n**2. Verify health endpoint:**\n\n```bash\ncurl http://127.0.0.1:4269/health\n# Should return JSON with status \"ok\"\n```\n\n**3. Verify MCP endpoint:**\n\n```bash\ncurl -X POST http://127.0.0.1:4269/mcp \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"initialize\",\"params\":{\"protocolVersion\":\"2024-11-05\",\"capabilities\":{}}}'\n# Should return MCP initialize response\n```\n\n**4. Enable debug logging:**\n\n```bash\nDEBUG=1 limps server start --foreground\n# Watch for connection attempts and errors\n```\n\n**5. Check MCP client config:**\n\nEnsure the URL in your client config matches the daemon:\n\n```json\n{\n  \"mcpServers\": {\n    \"limps-planning-myproject\": {\n      \"transport\": {\n        \"type\": \"http\",\n        \"url\": \"http://127.0.0.1:4269/mcp\"\n      }\n    }\n  }\n}\n```\n\n### Config Resolution Issues\n\n**Problem: limps is using the wrong config file**\n\nIf `limps config path` shows a different config than expected, use the diagnostic command to understand why:\n\n```bash\nlimps config show-resolution\n```\n\nThis shows all three priority levels for config resolution:\n\n1. **CLI `--config` argument** (highest priority)\n2. **`MCP_PLANNING_CONFIG` environment variable** (second priority)\n3. **Local `.limps/config.json`** (searches up from cwd)\n\n**Common causes:**\n\n- **Environment variable set**: Check if `MCP_PLANNING_CONFIG` is set in your shell or IDE. This takes priority over local config files.\n  ```bash\n  # Check if set\n  echo $MCP_PLANNING_CONFIG\n  \n  # Unset if needed\n  unset MCP_PLANNING_CONFIG\n  ```\n\n- **Wrong working directory**: Config search starts from your current working directory. Make sure you're in the right directory when running limps commands.\n  ```bash\n  # Check current directory\n  pwd\n  \n  # Navigate to your project\n  cd /path/to/your/project\n  ```\n\n- **Missing `.limps/config.json`**: The config file must be in a `.limps` subdirectory, not at the project root.\n  ```bash\n  # Correct location\n  /path/to/project/.limps/config.json\n  \n  # Wrong - won't be found\n  /path/to/project/config.json\n  ```\n\n**Quick fixes:**\n\n```bash\n# Override with explicit path\nlimps plan list --config /path/to/project/.limps/config.json\n\n# Or set environment variable\nexport MCP_PLANNING_CONFIG=/path/to/project/.limps/config.json\n\n# Or initialize a new config in current directory\nlimps init\n```\n\n## MCP Tools\n\nlimps exposes MCP tools for AI assistants:\n\n| Category            | Tools                                                                                                                                         |\n| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Documents**       | `process_doc`, `process_docs`, `create_doc`, `update_doc`, `delete_doc`, `list_docs`, `search_docs`, `manage_tags`, `open_document_in_cursor` |\n| **Plans**           | `create_plan`, `list_plans`, `list_agents`, `get_plan_status`                                                                                 |\n| **Tasks**           | `get_next_task`, `update_task_status`, `configure_scoring`                                                                                    |\n| **Health**          | `check_staleness`, `check_drift`, `infer_status`, `get_proposals`, `apply_proposal`                                                           |\n| **Knowledge Graph** | `graph` (unified: health, search, trace, entity, overlap, reindex, check, suggest)                                                            |\n\n### Knowledge Graph\n\nThe knowledge graph builds a structured, queryable representation of your planning documents. It extracts 6 entity types (**plan**, **agent**, **feature**, **file**, **tag**, **concept**) and their relationships (ownership, dependency, modification, tagging, conceptual links). Use it to find conflicts, trace dependencies, and get graph-based suggestions.\n\n```bash\n# Build the graph from plan files\nlimps graph reindex\n\n# Check graph health and conflicts\nlimps graph health --json\n\n# Search entities\nlimps graph search \"auth\" --json\n\n# Trace relationships\nlimps graph trace plan:0042 --direction down\n\n# Detect conflicts (file contention, circular deps, stale WIP)\nlimps graph check --json\n\n# Get graph-based suggestions\nlimps graph suggest dependency-order\n```\n\nSee [Knowledge Graph Architecture](docs/knowledge-graph.md) and [CLI Reference](docs/cli-reference.md) for details.\n\n### Health & Automation\n\nlimps includes automated health checks that detect issues and suggest fixes:\n\n- **Staleness** — Flags plans/agents not updated within configurable thresholds\n- **Code drift** — Detects when agent frontmatter references files that no longer exist\n- **Status inference** — Suggests status changes based on dependency completion and body content\n- **Proposals** — Aggregates all suggestions into reviewable, apply-able fixes\n\n```bash\nlimps health check --json        # Run all checks\nlimps proposals apply-safe       # Auto-apply safe fixes\n```\n\n## Skills & Commands\n\nThis repo ships Claude Code slash commands in [`.claude/commands/`](/.claude/commands/) and a [Vercel Skills](https://github.com/vercel-labs/skills) skill in `skills/limps-planning`.\n\n**Claude Code commands** (available automatically when limps is your working directory):\n\n| Command                | Description                           |\n| ---------------------- | ------------------------------------- |\n| `/create-feature-plan` | Create a full TDD plan with agents    |\n| `/run-agent`           | Pick up and execute the next agent    |\n| `/close-feature-agent` | Mark an agent PASS and clean up       |\n| `/update-feature-plan` | Revise an existing plan               |\n| `/audit-plan`          | Audit a plan for completeness         |\n| `/list-feature-plans`  | List all plans with status            |\n| `/plan-list-agents`    | List agents in a plan                 |\n| `/plan-check-status`   | Check plan progress                   |\n| `/pr-create`           | Create a PR from the current branch   |\n| `/pr-check-and-fix`    | Fix CI failures and update PR         |\n| `/pr-comments`         | Review and respond to PR comments     |\n| `/review-branch`       | General code review of current branch |\n| `/review-mcp`          | Review code for MCP/LLM safety        |\n| `/attack-cli-mcp`      | Stress-test CLI + MCP for robustness  |\n\n**Vercel Skills** (for other AI IDEs):\n\nInstall the limps planning skill to get AI-powered guidance for plan creation, agent workflows, and task management:\n\n```bash\n# Install only the limps planning skill (recommended for consumers)\nnpx skills add https://github.com/sudosandwich/limps/tree/main/.claude/skills/limps-plan-operations\n\n# Or install all available skills\nnpx skills add sudosandwich/limps\n```\n\n**Available Skills:**\n\n| Skill | Description |\n|-------|-------------|\n| `limps-plan-operations` | Plan identification, artifact loading, distillation rules, and lifecycle guidance using limps MCP tools |\n| `mcp-code-review` | Security-focused code review for MCP servers and LLM safety |\n| `branch-code-review` | General code review for design, maintainability, and correctness |\n| `git-commit-best-practices` | Conventional commits and repository best practices |\n\nSee [`skills.yaml`](./skills.yaml) for the complete manifest of the `.claude/skills` packages installed via `npx skills add` above; the separate `skills/limps-planning/` package in this repo is a legacy distribution and new consumers should prefer the `.claude/skills` method.\n\n## Extensions\n\nExtensions add MCP tools and resources. Install from npm:\n\n```bash\nnpm install -g @sudosandwich/limps-headless\n```\n\nAdd to config:\n\n```json\n{\n  \"extensions\": [\"@sudosandwich/limps-headless\"],\n  \"limps-headless\": {\n    \"cacheDir\": \"~/Library/Application Support/limps-headless\"\n  }\n}\n```\n\n**Available extensions:**\n\n- `@sudosandwich/limps-headless` — Headless UI contract extraction, semantic analysis, and drift detection (Radix UI and Base UI migration).\n\n## Obsidian Integration\n\nThe `@sudosandwich/limps-obsidian-plugin` package provides deep Obsidian integration:\n\n- **Persistent MCP session** to the limps daemon with auto-reconnect, keepalive, and CLI fallback\n- **Document management** — create, update, delete plan documents from within Obsidian\n- **Task management** — get next task, update task status (GAP/WIP/PASS/BLOCKED)\n- **Search & proposals** — full-text search, proposal review, and auto-apply for safe fix types\n- **Health Hub** — sidebar view with daemon, graph, link, and MCP status\n- **Directed graph view** — interactive 2D/3D force graph with clickable nodes\n- **Scheduled health checks** — periodic staleness, drift, and conflict detection\n- **Vault automation** — auto-reindex when plan files change, event-driven refresh\n- **Editor diagnostics** — inline link validation\n- **Graph sync** to Obsidian surfaces (`.md`, `.canvas`, `.base`)\n\nFull YAML frontmatter support, tag management (frontmatter and inline `#tag`), and automatic exclusion of `.obsidian/`, `.git/`, `node_modules/`.\n\nSee [`packages/limps-obsidian-plugin/README.md`](packages/limps-obsidian-plugin/README.md) for setup instructions, commands, and settings reference.\n\n![Obsidian vault with limps plans](https://github.com/paulbreuler/limps/blob/main/.github/assets/obsidian-vault.png?raw=true)\n\n## Development\n\n```bash\ngit clone https://github.com/paulbreuler/limps.git\ncd limps\nnpm install\nnpm run build\nnpm test\n```\n\nThis is a monorepo with:\n\n- `packages/limps` — Core MCP server\n- `packages/limps-headless` — Headless UI extension (Radix/Base UI contract extraction and audit)\n\n## Used in Production\n\nlimps manages planning for [runi](https://github.com/paulbreuler/runi), using a separate folder (in this case a git repo) for plans.\n\n---\n\n## Creating a feature plan\n\nThe fastest way is the `/create-feature-plan` slash command (Claude Code) — it handles numbering, doc creation, and agent distillation automatically via MCP tools. See [`.claude/commands/create-feature-plan.md`](/.claude/commands/create-feature-plan.md) for the full spec.\n\nYou can also run the same steps manually with MCP tools:\n\n1. `list_plans` → determine next plan number\n2. `create_plan` → scaffold the plan directory\n3. `create_doc` → add plan, interfaces, README, and agent files\n4. `update_task_status` → track progress\n\nPlans follow this layout:\n\n```\nNNNN-descriptive-name/\n├── README.md\n├── NNNN-descriptive-name-plan.md\n├── interfaces.md\n└── agents/\n    ├── 000_agent_infrastructure.agent.md\n    ├── 001_agent_feature-a.agent.md\n    └── ...\n```\n\nNumbered prefixes keep plans and agents lexicographically ordered. `get_next_task` uses the agent number (plus dependency and workload scores) to suggest what to work on next.\n\n## Deep Dive\n\n<details>\n<summary><b>Plan Structure</b></summary>\n\n```\nplans/\n├── 0001-feature-name/\n│   ├── 0001-feature-name-plan.md    # Main plan with specs\n│   ├── interfaces.md                 # Interface contracts\n│   ├── README.md                     # Status index\n│   └── agents/                       # Task files\n│       ├── 000-setup.md\n│       ├── 001-implement.md\n│       └── 002-test.md\n└── 0002-another-feature/\n    └── ...\n```\n\nAgent files use frontmatter to track status:\n\n```yaml\n---\nstatus: GAP | WIP | PASS | BLOCKED\npersona: coder | reviewer | pm | customer\ndepends_on: [\"000-setup\"]\nfiles:\n  - src/components/Feature.tsx\n---\n```\n\n</details>\n\n<details>\n<summary><b>Task Scoring Algorithm</b></summary>\n\n`get_next_task` returns tasks scored by:\n\n| Component  | Max Points | Description                                     |\n| ---------- | ---------- | ----------------------------------------------- |\n| Dependency | 40         | All dependencies satisfied = 40, else 0         |\n| Priority   | 30         | Based on agent number (lower = higher priority) |\n| Workload   | 30         | Based on file count (fewer = higher score)      |\n\n**Biases** adjust final scores:\n\n```json\n{\n  \"scoring\": {\n    \"biases\": {\n      \"plans\": { \"0030-urgent-feature\": 20 },\n      \"personas\": { \"coder\": 5, \"reviewer\": -10 },\n      \"statuses\": { \"GAP\": 5, \"WIP\": -5 }\n    }\n  }\n}\n```\n\n</details>\n\n<details>\n<summary><b>RLM (Recursive Language Model) Support</b></summary>\n\n`process_doc` and `process_docs` execute JavaScript in a secure QuickJS sandbox. User-provided code is statically validated and cannot use `require`, `import`, `eval`, `fetch`, `XMLHttpRequest`, `WebSocket`, `process`, timers, or other host/network APIs—so it cannot make external calls or access the host.\n\n```typescript\nawait process_doc({\n  path: \"plans/0001-feature/plan.md\",\n  code: `\n    const features = extractFeatures(doc.content);\n    return features.filter(f => f.status === 'GAP');\n  `,\n});\n```\n\n**Available extractors:**\n\n- `extractSections()` — Markdown headings\n- `extractFrontmatter()` — YAML frontmatter\n- `extractFeatures()` — Plan features with status\n- `extractAgents()` — Agent metadata\n- `extractCodeBlocks()` — Fenced code blocks\n\n**LLM sub-queries** (opt-in):\n\n```typescript\nawait process_doc({\n  path: \"plans/0001/plan.md\",\n  code: \"extractFeatures(doc.content)\",\n  sub_query: \"Summarize each feature\",\n  allow_llm: true,\n  llm_policy: \"force\", // or 'auto' (skips small results)\n});\n```\n\n</details>\n\n<details>\n<summary><b>MCP Resources</b></summary>\n\nProgressive disclosure via resources:\n\n| Resource          | Description                  |\n| ----------------- | ---------------------------- |\n| `plans://index`   | List of all plans (minimal)  |\n| `plans://summary` | Plan summaries with key info |\n| `plans://full`    | Full plan documents          |\n| `decisions://log` | Decision log entries         |\n\n</details>\n\n<details>\n<summary><b>Example: Custom Cursor Commands</b></summary>\n\nCreate `.cursor/commands/run-agent.md`:\n\n```markdown\n# Run Agent\n\nStart work on the next available task.\n\n## Instructions\n\n1. Use `get_next_task` to find the highest-priority task\n2. Use `process_doc` to read the agent file\n3. Use `update_task_status` to mark it WIP\n4. Follow the agent's instructions\n```\n\nThis integrates with limps MCP tools for seamless task management.\n\n</details>\n\n---\n\n## What is MCP?\n\n**Model Context Protocol** is a standardized protocol for AI applications to connect to external systems. Originally from Anthropic (Nov 2024), now part of the Linux Foundation's Agentic AI Foundation.\n\n- [MCP Specification](https://modelcontextprotocol.io/)\n- [MCP Documentation](https://modelcontextprotocol.io/docs)\n\n## License\n\nMIT\n",
  "bytes": 47096,
  "sha": "683ef37e6e693e573e57f537b2e36886e15f491f402ebaa1052b282e575ff506",
  "repo_slug": "paulbreuler/limps",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_paulbreuler_limps_d355dd61/readme"
}