{"id":"f6504a49-7cde-4208-b753-02936b3d4c3b","slug":"techlead","kind":"mcp","name":"techlead","summary":"A tech lead MCP server intended to offer LLM agents guidance and guardrails for proper implementations.","owner":"jayehmke","repoUrl":"https://github.com/jayehmke/techlead","license":"MIT","licenseTier":"permissive","trust":"community","stars":2,"match":null,"fewStars":true,"format":"mcp","createdAt":"2025-12-17T12:19:06.000Z","addedAt":"2026-10-21T16:28:56.323Z","logoUrl":"https://avatars.githubusercontent.com/u/1394923?u=a62e0320e989c4f615f616710eddafe853529259&v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["cloud-infra"],"tags":[],"runtime":"go","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-22T21:34:02.772Z","sample":false,"url":"https://conduits.dev/tools/techlead","language":"Go","transports":["stdio"],"install":{},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"# Tech Lead\n\nAn AI supervisor for Claude Code. The tech lead reviews implementation plans before they reach you, catching over-engineering, scope creep, and unnecessary complexity.\n\n## The Problem\n\nClaude Code is capable but eager. Ask it to \"add logging\" and you might get a 6-file logging framework with interfaces, formatters, handlers, and configuration systems. By the time you see the plan, you're already parsing complexity.\n\n## The Solution\n\nThe tech lead sits between Claude Code (the implementer) and you. Every plan gets reviewed before you see it:\n\n```\n┌─────────────────────────────────────────────────────────────────┐\n│ You: \"Add request logging\"                                      │\n│                                                                 │\n│ Implementer drafts plan → Tech Lead reviews                     │\n│                                                                 │\n│ Tech Lead: \"Reject. 6 files for logging is over-engineering.    │\n│            Use slog directly. 2 files max.\"                     │\n│                                                                 │\n│ Implementer revises → Tech Lead reviews                         │\n│                                                                 │\n│ Tech Lead: \"Approve. Clean, minimal, uses stdlib.\"              │\n│                                                                 │\n│ You see: \"I'll add request logging with slog. One file:         │\n│          internal/middleware/logging.go\"                        │\n└─────────────────────────────────────────────────────────────────┘\n```\n\nYou only see vetted plans. The messy iterations happen before they reach you.\n\n## Features\n\n- **Plan Review** — Evaluates scope, complexity, and adherence to project standards\n- **Code Review** — Post-implementation review catches bugs, anti-patterns, and missing tests\n- **Knowledge Storage** — Learns from past decisions and reviews using vector embeddings\n- **Semantic Search** — Finds similar past reviews even with different terminology\n- **Project Standards** — Configurable thresholds for files, tests, and strictness\n- **MCP Integration** — Works as an MCP server for Claude Code\n- **Hook Enforcement** — Optional Claude hooks to enforce the workflow\n\n## Requirements\n\n- Go 1.21+\n- Docker (for Ollama)\n- Claude Code CLI\n\n## Quick Install\n\n```bash\ngit clone https://github.com/jasonehmke/techlead.git\ncd techlead\n./scripts/install.sh\n```\n\nThis script:\n- Builds and installs the `techlead` binary to `~/.local/bin`\n- Starts Ollama in Docker and pulls the embedding model\n- Configures the MCP server globally for all Claude Code projects\n\nAfter installation, the `consult_tech_lead` tool is available in every Claude Code session.\n\n## Manual Installation\n\nIf you prefer to set things up manually:\n\n```bash\n# Clone and build\ngit clone https://github.com/jasonehmke/techlead.git\ncd techlead\nmake build\n\n# Install to PATH\ncp bin/techlead ~/.local/bin/\n\n# Add MCP server globally\nclaude mcp add techlead ~/.local/bin/techlead mcp -s user\n```\n\n### Set Up Ollama\n\nThe tech lead uses Ollama for generating embeddings. This enables semantic search across past decisions and reviews.\n\n```bash\n# Install Ollama (macOS)\nbrew install ollama\n\n# Pull the embedding model\nollama pull nomic-embed-text\n\n# Start Ollama (runs in background)\nollama serve\n```\n\n## Quick Start\n\n### 1. Initialize a Project\n\n```bash\ncd your-project\ntechlead init\n```\n\nThis creates:\n```\n.techlead/\n├── config.yaml      # Project standards\n└── knowledge.db     # Vector database (created on first run)\n```\n\n### 2. Start the Tech Lead Server\n\n```bash\ntechlead\n```\n\nThe server starts on `http://localhost:8080` by default. Set `PORT` environment variable to change.\n\n### 3. Configure Claude Code\n\nIf you used the install script, the MCP server is already configured globally. Skip to step 4.\n\n**Global install (all projects):**\n\n```bash\nclaude mcp add techlead ~/.local/bin/techlead mcp -s user\n```\n\n**Project-only install:**\n\nAdd to your project's `.mcp.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"techlead\": {\n      \"command\": \"/path/to/techlead\",\n      \"args\": [\"mcp\"]\n    }\n  }\n}\n```\n\n**HTTP mode (for development/testing):**\n\n```json\n{\n  \"mcpServers\": {\n    \"techlead\": {\n      \"type\": \"http\",\n      \"url\": \"http://localhost:8080\"\n    }\n  }\n}\n```\n\n### 4. Add Implementer Instructions\n\nCopy `context/implementer.md` to your project's `CLAUDE.md` or append it to existing instructions. This tells Claude Code to consult the tech lead before showing you plans.\n\n## Configuration\n\nEdit `.techlead/config.yaml`:\n\n```yaml\nstandards:\n  require_linting: true\n  require_tests: true\n  max_files_per_task: 10\n\nreview:\n  # How hard to push: minimal, standard, strict, pedantic\n  strictness: standard\n\nknowledge:\n  embeddings:\n    endpoint: http://localhost:11434\n    model: nomic-embed-text\n```\n\n### Strictness Levels\n\n| Level | Behavior |\n|-------|----------|\n| `minimal` | Only catch egregious issues |\n| `standard` | Clear issues + obvious improvements (default) |\n| `strict` | Standard + questionable decisions |\n| `pedantic` | Maximum scrutiny, question everything |\n\n## API Reference\n\n### HTTP Endpoints\n\n#### Review a Plan\n\n```bash\nPOST /consult\n```\n\n```bash\ncurl -X POST http://localhost:8080/consult \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"task\": \"Add request logging\",\n    \"plan_summary\": \"Create middleware that logs requests using slog\",\n    \"files\": [\"internal/middleware/logging.go\", \"internal/middleware/logging_test.go\"],\n    \"rationale\": \"Simple middleware with tests\"\n  }'\n```\n\nResponse:\n```json\n{\n  \"decision\": \"approve\",\n  \"reason\": \"Clean, minimal approach. Uses stdlib slog, includes tests.\",\n  \"guidance\": \"\"\n}\n```\n\n#### Search Knowledge\n\n```bash\nPOST /knowledge/search\n```\n\n```bash\ncurl -X POST http://localhost:8080/knowledge/search \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"query\": \"logging and observability\", \"limit\": 5}'\n```\n\nReturns semantically similar decisions, learnings, and past reviews.\n\n#### Record a Decision\n\n```bash\nPOST /knowledge/decision\n```\n\n```bash\ncurl -X POST http://localhost:8080/knowledge/decision \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"content\": \"Use slog for all logging\",\n    \"context\": \"Stdlib is sufficient, no external dependencies needed\"\n  }'\n```\n\n#### Record a Learning\n\n```bash\nPOST /knowledge/learning\n```\n\n```bash\ncurl -X POST http://localhost:8080/knowledge/learning \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"pattern\": \"Implementer proposes 6+ files for simple task\",\n    \"response\": \"Reject. Scope to 2 files maximum.\",\n    \"severity\": \"high\"\n  }'\n```\n\n#### List All Decisions\n\n```bash\nGET /knowledge/decisions\n```\n\n#### List All Learnings\n\n```bash\nGET /knowledge/learnings\n```\n\n#### Review Code\n\n```bash\nPOST /review\n```\n\n```bash\ncurl -X POST http://localhost:8080/review \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"task\": \"Add user authentication\",\n    \"files\": {\n      \"internal/auth/handler.go\": \"package auth\\n\\nfunc Login(w http.ResponseWriter, r *http.Request) {\\n    // handler code\\n}\"\n    },\n    \"description\": \"Login endpoint with JWT tokens\"\n  }'\n```\n\nResponse:\n```json\n{\n  \"approved\": true,\n  \"summary\": \"Clean implementation with proper error handling\",\n  \"issues\": [],\n  \"praise\": \"Good use of stdlib http patterns\"\n}\n```\n\nIf issues are found:\n```json\n{\n  \"approved\": false,\n  \"summary\": \"Several issues need attention\",\n  \"issues\": [\n    \"SQL injection vulnerability in query construction\",\n    \"Error from db.Query is ignored\",\n    \"Missing nil check on user result\"\n  ],\n  \"praise\": \"\"\n}\n```\n\n#### Health Check\n\n```bash\nGET /health\n```\n\n## How It Works\n\n### Plan Review Flow\n\n1. Implementer (Claude Code) drafts a plan\n2. Implementer calls `consult_tech_lead` tool with the plan\n3. Tech lead searches knowledge base for similar past reviews\n4. Tech lead evaluates plan against standards and historical context\n5. Tech lead returns: approve, modify, or reject\n6. If not approved, implementer revises and tries again\n7. Approved plan is shown to user\n\n### Knowledge System\n\nThe tech lead learns from experience using vector embeddings:\n\n```\n\"Add logging framework\" → [0.12, -0.45, 0.78, ...]  (768 numbers)\n\"Create observability system\" → [0.11, -0.44, 0.76, ...]  (similar meaning = similar numbers)\n```\n\nWhen a new plan comes in:\n1. Embed the plan summary\n2. Search for similar past reviews\n3. Include relevant context in the evaluation\n4. Store the new review for future reference\n\nThis means rejecting a \"logging framework\" informs future reviews of \"monitoring systems\"—they're semantically related even without shared words.\n\n### Code Review Flow\n\nAfter implementation is complete:\n\n1. Implementer calls `review_code` tool with the code\n2. Tech lead reviews for bugs, anti-patterns, and quality issues\n3. Returns approval status with any issues found\n4. If issues exist, implementer fixes and re-reviews\n5. Clean code is presented to the user\n\nCode review is lighter than plan review—it approves \"good enough\" code and only flags real issues.\n\n## Hook Enforcement (Optional)\n\nBy default, the tech lead relies on instructions in `CLAUDE.md` to guide Claude Code. For stricter enforcement, you can add Claude hooks that block code changes until the tech lead approves.\n\n### How It Works\n\n1. **PreToolUse hook** blocks `Write`, `Edit`, and `MultiEdit` until `consult_tech_lead` returns approval\n2. **PostToolUse hook** tracks approval status and reminds about code review after implementation\n\n### Setup\n\nCreate the enforcement hook at `~/.claude/hooks/techlead-enforce.sh`:\n\n```bash\n#!/bin/bash\n# Blocks code changes until tech lead approval\n\nset -e\n\ninput=$(cat)\nsession_id=$(echo \"$input\" | jq -r '.session_id')\ntool_name=$(echo \"$input\" | jq -r '.tool_name')\n\nSTATE_DIR=\"/tmp/claude-techlead\"\nmkdir -p \"$STATE_DIR\"\nAPPROVAL_FILE=\"$STATE_DIR/approved-$session_id\"\n\n# Only enforce in projects with .techlead/ directory\ncheck_techlead_project() {\n    local dir=$(echo \"$input\" | jq -r '.cwd // \".\"')\n    [[ -d \"$dir/.techlead\" ]]\n}\n\nif ! check_techlead_project; then\n    exit 0\nfi\n\ncase \"$tool_name\" in\n    Write|Edit|MultiEdit)\n        # Allow config files without approval\n        file_path=$(echo \"$input\" | jq -r '.tool_input.file_path // \"\"')\n        case \"$file_path\" in\n            *.md|*.txt|*.json|*.yaml|*.yml|*.toml|*.env*)\n                exit 0\n                ;;\n        esac\n\n        # Check for approval\n        if [[ -f \"$APPROVAL_FILE\" ]] && [[ \"$(cat \"$APPROVAL_FILE\")\" == \"approved\" ]]; then\n            exit 0\n        fi\n\n        echo \"BLOCKED: Call consult_tech_lead first\" >&2\n        exit 2\n        ;;\nesac\n\nexit 0\n```\n\nCreate the tracker hook at `~/.claude/hooks/techlead-tracker.sh`:\n\n```bash\n#!/bin/bash\n# Tracks tech lead approval status\n\nset -e\n\ninput=$(cat)\nsession_id=$(echo \"$input\" | jq -r '.session_id')\ntool_name=$(echo \"$input\" | jq -r '.tool_name')\n\nSTATE_DIR=\"/tmp/claude-techlead\"\nmkdir -p \"$STATE_DIR\"\nAPPROVAL_FILE=\"$STATE_DIR/approved-$session_id\"\n\nif [[ \"$tool_name\" == \"mcp__techlead__consult_tech_lead\" ]]; then\n    tool_output=$(echo \"$input\" | jq -r '.tool_output // \"\"')\n    if echo \"$tool_output\" | grep -qi '\"decision\"[[:space:]]*:[[:space:]]*\"approve\"'; then\n        echo \"approved\" > \"$APPROVAL_FILE\"\n    fi\nfi\n\nexit 0\n```\n\nMake both executable:\n\n```bash\nchmod +x ~/.claude/hooks/techlead-enforce.sh\nchmod +x ~/.claude/hooks/techlead-tracker.sh\n```\n\nAdd to `~/.claude/settings.json`:\n\n```json\n{\n  \"hooks\": {\n    \"PreToolUse\": [\n      {\n        \"matcher\": \"Write|Edit|MultiEdit\",\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"/path/to/.claude/hooks/techlead-enforce.sh\"\n          }\n        ]\n      }\n    ],\n    \"PostToolUse\": [\n      {\n        \"matcher\": \"mcp__techlead__*|Write|Edit|MultiEdit\",\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"/path/to/.claude/hooks/techlead-tracker.sh\"\n          }\n        ]\n      }\n    ]\n  }\n}\n```\n\nReplace `/path/to/` with your actual home directory path.\n\n### What the Tech Lead Catches\n\n| Pattern | Response |\n|---------|----------|\n| Too many files | \"This should be 2 files, not 8\" |\n| Unnecessary abstractions | \"No interfaces needed here\" |\n| Scope creep | \"Park that for later, finish this task first\" |\n| New dependencies | \"Use stdlib, don't add external deps\" |\n| Over-engineering | \"This is a simple task, keep it simple\" |\n| Stdlib reimplementation | \"Use strings.Contains instead of custom helper\" |\n\n## Running Modes\n\n### HTTP Server (Default)\n\n```bash\ntechlead\n# or\ntechlead --port 9090\n```\n\nGood for development and testing. Use curl to interact directly.\n\n### MCP Server (stdio)\n\n```bash\ntechlead mcp\n```\n\nStandard MCP protocol over stdin/stdout. This is what Claude Code uses.\n\n## Development\n\n### Build\n\n```bash\nmake build\n```\n\n### Test\n\n```bash\nmake test\n```\n\nNote: Tests that require Ollama will be skipped if Ollama is not running.\n\n### Run with Hot Reload\n\n```bash\nmake dev\n```\n\nRequires [air](https://github.com/cosmtrek/air).\n\n## Project Structure\n\n```\ntechlead/\n├── cmd/techlead/\n│   ├── main.go              # Entry point\n│   └── templates/           # Default config templates\n├── internal/\n│   ├── config/              # Configuration loading\n│   ├── knowledge/           # Vector database and embeddings\n│   ├── mcp/                 # MCP and HTTP servers\n│   ├── plan/                # Plan schema\n│   └── techlead/            # Core review logic\n├── context/\n│   └── implementer.md       # Claude Code instructions\n└── .techlead/\n    └── config.yaml          # Project configuration\n```\n\n## Troubleshooting\n\n### \"embedder not available: ollama unavailable\"\n\nOllama is not running or the model is not installed.\n\n```bash\n# Start Ollama\nollama serve\n\n# Pull the model if not installed\nollama pull nomic-embed-text\n```\n\n### \"sqlite3_auto_extension is deprecated\" warning\n\nThis is a macOS warning, not an error. Apple deprecated this function in their bundled SQLite, but it still works. The warning can be safely ignored.\n\n### Tech lead not being consulted\n\n1. Check that `.mcp.json` is configured correctly\n2. Verify the implementer instructions are in your `CLAUDE.md`\n3. Restart Claude Code after configuration changes\n4. Check that the tech lead server is running\n\n### Tech lead only works in one project\n\nThe MCP server was likely added with local scope instead of user scope. Fix with:\n\n```bash\nclaude mcp remove techlead -s local\nclaude mcp add techlead ~/.local/bin/techlead mcp -s user\n```\n\n### Plans still seem over-engineered\n\nIncrease strictness in `.techlead/config.yaml`:\n\n```yaml\nreview:\n  strictness: strict  # or pedantic\n```\n\nRecord learnings for patterns you see:\n\n```bash\ncurl -X POST http://localhost:8080/knowledge/learning \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"pattern\": \"Creates interfaces for single implementations\",\n    \"response\": \"Reject. No interface until there are 2+ implementations.\",\n    \"severity\": \"high\"\n  }'\n```\n\n## License\n\nMIT\n"}