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