diff --git a/.claude/commands/ticket.md b/.claude/commands/ticket.md index 4c632a0..253b351 100644 --- a/.claude/commands/ticket.md +++ b/.claude/commands/ticket.md @@ -1,23 +1,24 @@ --- -description: Work on a JIRA/Linear ticket end-to-end -allowed-tools: Read, Write, Edit, Glob, Grep, Bash(git:*), Bash(gh:*), Bash(npm:*), mcp__jira__*, mcp__github__*, mcp__linear__* +description: Work on a GitHub Issue end-to-end +allowed-tools: Read, Write, Edit, Glob, Grep, Bash(git:*), Bash(gh:*), Bash(npm:*), mcp__github__* --- -# Ticket Workflow +# GitHub Issue Workflow -Work on ticket: $ARGUMENTS +Work on issue: $ARGUMENTS ## Instructions -### 1. Read the Ticket +### 1. Read the Issue -First, fetch and understand the ticket: +First, fetch and understand the GitHub Issue: ``` -Use the JIRA/Linear MCP tools to: -- Get ticket details (title, description, acceptance criteria) -- Check linked tickets or epics -- Review any comments or attachments +Use the GitHub MCP tools or CLI to: +- Get issue details (title, description, labels) +- Check linked issues or milestones +- Review any comments +- Check acceptance criteria in the issue body ``` Summarize: @@ -35,7 +36,8 @@ Before coding: ### 3. Create a Branch ```bash -git checkout -b {initials}/{ticket-id}-{brief-description} +git checkout -b {initials}/{issue-number}-{brief-description} +# Example: git checkout -b jd/42-add-user-auth ``` ### 4. Implement the Changes @@ -44,37 +46,39 @@ git checkout -b {initials}/{ticket-id}-{brief-description} - Write tests first (TDD) - Make incremental commits -### 5. Update the Ticket +### 5. Update the Issue As you work: - Add comments with progress updates -- Update status (In Progress β†’ In Review) +- Update labels if needed (in-progress, needs-review) - Log any blockers or questions ### 6. Create PR and Link When ready: - Create PR with `gh pr create` -- Link the PR to the ticket -- Add ticket ID to PR title: `feat(PROJ-123): description` +- Reference the issue in the PR body: `Closes #` +- PR title format: `feat(#42): description` or `fix(#42): description` ### 7. If You Find a Bug If you discover an unrelated bug while working: -1. Create a new ticket with details -2. Link it to the current ticket if related +1. Create a new issue with details +2. Link it to the current issue if related 3. Note it in the PR description 4. Continue with original task ## Example Workflow ``` -Me: /ticket PROJ-123 +Me: /ticket 42 Claude: -1. Fetching PROJ-123 from JIRA... +1. Fetching Issue #42 from GitHub... Title: Add user profile avatar upload Description: Users should be able to upload a profile picture... + Labels: enhancement, frontend + Acceptance Criteria: - [ ] Upload button on profile page - [ ] Support JPG/PNG up to 5MB @@ -84,13 +88,32 @@ Claude: Found: src/screens/Profile/ProfileScreen.tsx Found: src/components/Avatar/Avatar.tsx -3. Creating branch: cw/PROJ-123-avatar-upload +3. Creating branch: cw/42-avatar-upload 4. [Implements feature with TDD approach] -5. Updating JIRA status to "In Review"... - Adding comment: "Implementation complete, PR ready for review" +5. Adding comment to Issue #42: "Implementation complete, PR ready for review" -6. Creating PR and linking to PROJ-123... - PR #456 created: feat(PROJ-123): add avatar upload to profile +6. Creating PR and linking to Issue #42... + PR #56 created: feat(#42): add avatar upload to profile + Body includes: Closes #42 +``` + +## GitHub Issue Commands Reference + +```bash +# View issue details +gh issue view 42 + +# List issues assigned to you +gh issue list --assignee @me + +# Add comment to issue +gh issue comment 42 --body "Progress update: ..." + +# Add label to issue +gh issue edit 42 --add-label "in-progress" + +# Create linked PR +gh pr create --title "feat(#42): description" --body "Closes #42" ``` diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..eac5190 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,97 @@ +{ + "name": "Claudia Development Container", + "image": "mcr.microsoft.com/devcontainers/typescript-node:1-20-bullseye", + "features": { + "ghcr.io/devcontainers/features/docker-in-docker:2": {}, + "ghcr.io/devcontainers/features/git:1": {}, + "ghcr.io/devcontainers/features/github-cli:1": {}, + "ghcr.io/devcontainers-contrib/features/curl-apt-get:1": {} + }, + "forwardPorts": [3000, 8080, 8081, 8384, 11434], + "portsAttributes": { + "3000": { + "label": "Application", + "onAutoForward": "notify" + }, + "8080": { + "label": "SearXNG", + "onAutoForward": "silent" + }, + "8081": { + "label": "SurrealDB", + "onAutoForward": "silent" + }, + "8384": { + "label": "Serena", + "onAutoForward": "silent" + }, + "11434": { + "label": "Ollama", + "onAutoForward": "silent" + } + }, + "postCreateCommand": "npm install || true && docker compose -f docker-compose.dev.yml up -d", + "postStartCommand": "docker compose -f docker-compose.dev.yml start", + "postAttachCommand": "echo 'πŸš€ Development environment ready!'", + "customizations": { + "vscode": { + "extensions": [ + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode", + "ms-vscode.vscode-typescript-next", + "GitHub.copilot", + "GitHub.copilot-chat", + "GitHub.vscode-pull-request-github", + "eamodio.gitlens", + "bradlc.vscode-tailwindcss", + "ZixuanChen.vitest-explorer", + "ms-azuretools.vscode-docker" + ], + "settings": { + "editor.formatOnSave": true, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.codeActionsOnSave": { + "source.fixAll.eslint": "explicit" + }, + "typescript.preferences.importModuleSpecifier": "relative", + "typescript.updateImportsOnFileMove.enabled": "always", + "[typescript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[typescriptreact]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[javascript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[json]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "github.copilot.enable": { + "*": true, + "yaml": true, + "markdown": true, + "plaintext": false + }, + "terminal.integrated.defaultProfile.linux": "bash" + } + }, + "codespaces": { + "openFiles": ["README.md", "CLAUDE.md"] + } + }, + "remoteEnv": { + "NODE_ENV": "development", + "OLLAMA_HOST": "http://localhost:11434", + "SEARXNG_HOST": "http://localhost:8080", + "SURREALDB_HOST": "http://localhost:8081" + }, + "containerEnv": { + "TZ": "UTC" + }, + "hostRequirements": { + "cpus": 4, + "memory": "8gb", + "storage": "32gb" + } +} diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..844d31b --- /dev/null +++ b/.env.example @@ -0,0 +1,38 @@ +# GitHub Token (required for GitHub MCP) +GITHUB_TOKEN=ghp_your-github-personal-access-token + +# Serena MCP Configuration +SERENA_HOST=http://localhost:8384 +SERENA_API_KEY=your-serena-api-key + +# Context7 MCP Configuration +CONTEXT7_API_KEY=your-context7-api-key + +# SurrealDB Configuration (Docker local) +SURREALDB_URL=http://localhost:8081 +SURREALDB_USER=root +SURREALDB_PASS=root +SURREALDB_NS=claudia +SURREALDB_DB=main +SURREALDB_ROOT_PASSWORD=root + +# SearXNG Configuration (Docker local) +SEARXNG_URL=http://localhost:8080 +SEARXNG_SECRET_KEY=generate-a-random-secret-key-here + +# Ollama Configuration (Docker local) +OLLAMA_HOST=http://localhost:11434 + +# Sentry Configuration (optional) +SENTRY_AUTH_TOKEN=your-sentry-auth-token +SENTRY_ORG=your-sentry-org + +# Slack Configuration (optional) +SLACK_BOT_TOKEN=xoxb-your-slack-bot-token +SLACK_TEAM_ID=T00000000 + +# Codecov (optional for CI) +CODECOV_TOKEN=your-codecov-token + +# Semgrep (optional for security scanning) +SEMGREP_APP_TOKEN=your-semgrep-token diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..cab3ac5 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,50 @@ +# GitHub Copilot Instructions + +## Project Context +This is a Claude Code project configuration showcase demonstrating best practices for AI-assisted development. + +## Code Style Guidelines +- Use TypeScript strict mode +- Prefer `interface` over `type` for object shapes +- Use `unknown` instead of `any` +- Write self-documenting code with meaningful names +- Follow the single responsibility principle + +## Patterns to Follow +- Use early returns to reduce nesting +- Prefer composition over inheritance +- Handle all error cases explicitly +- Always include loading, error, and empty states in UI +- Use factory functions for test mocks + +## Testing Conventions +- Write tests using Jest +- Follow TDD: write failing test first +- Use AAA pattern: Arrange, Act, Assert +- Mock factory pattern: `getMockUser(overrides)` + +## React Patterns +- Use functional components with hooks +- Prefer custom hooks for reusable logic +- Always handle loading and error states +- Use proper TypeScript generics for components + +## Git Conventions +- Branch naming: `{initials}/{issue-number}-{description}` +- Commit format: Conventional Commits (`feat:`, `fix:`, `docs:`) +- Reference issues in PR body: `Closes #` + +## MCP Servers Available +- GitHub: Issue tracking and repository management +- Serena: AI agent integration +- Context7: Context retrieval +- SurrealDB: Database operations +- SearXNG: Web search +- Ollama: Local LLM inference + +## Do Not +- Use `any` type +- Swallow errors silently +- Commit secrets or credentials +- Skip error handling +- Use outdated patterns diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..a35112d --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,45 @@ +version: 2 +updates: + # NPM dependencies + - package-ecosystem: "npm" + directory: "/" + schedule: + interval: "weekly" + day: "monday" + time: "09:00" + timezone: "UTC" + open-pull-requests-limit: 10 + commit-message: + prefix: "chore(deps)" + labels: + - "dependencies" + - "automated" + groups: + dev-dependencies: + dependency-type: "development" + update-types: + - "minor" + - "patch" + production-dependencies: + dependency-type: "production" + update-types: + - "patch" + + # GitHub Actions + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + day: "monday" + time: "09:00" + timezone: "UTC" + open-pull-requests-limit: 5 + commit-message: + prefix: "chore(ci)" + labels: + - "ci" + - "automated" + groups: + actions: + patterns: + - "*" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..426ea9e --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,115 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + pull-requests: write + checks: write + +jobs: + lint: + name: Lint & Format + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Run ESLint + run: npm run lint --if-present + + - name: Run Prettier check + run: npx prettier --check "**/*.{ts,tsx,js,jsx,json,md}" --ignore-path .gitignore + + typecheck: + name: TypeScript Check + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Run TypeScript compiler + run: npx tsc --noEmit + + test: + name: Test + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Run tests with coverage + run: npm test -- --coverage --watchAll=false + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v4 + with: + token: ${{ secrets.CODECOV_TOKEN }} + fail_ci_if_error: false + continue-on-error: true + + build: + name: Build + runs-on: ubuntu-latest + needs: [lint, typecheck, test] + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Check if build script exists + id: check-build + run: | + if npm run --silent build 2>&1 | grep -q "Missing script"; then + echo "has_build=false" >> $GITHUB_OUTPUT + else + echo "has_build=true" >> $GITHUB_OUTPUT + fi + continue-on-error: true + + - name: Build + if: steps.check-build.outputs.has_build == 'true' + run: npm run build diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..eff037e --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,46 @@ +name: CodeQL Analysis + +on: + push: + branches: [main] + pull_request: + branches: [main] + schedule: + # Run weekly on Wednesday at 3 AM UTC + - cron: '0 3 * * 3' + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + security-events: write + actions: read + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + language: ['javascript-typescript'] + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + queries: +security-extended,security-and-quality + + - name: Autobuild + uses: github/codeql-action/autobuild@v3 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: "/language:${{ matrix.language }}" diff --git a/.github/workflows/semgrep.yml b/.github/workflows/semgrep.yml new file mode 100644 index 0000000..599069c --- /dev/null +++ b/.github/workflows/semgrep.yml @@ -0,0 +1,40 @@ +name: Semgrep Security Scan + +on: + push: + branches: [main] + pull_request: + branches: [main] + schedule: + # Run weekly on Monday at 8 AM UTC + - cron: '0 8 * * 1' + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + security-events: write + +jobs: + semgrep: + name: Semgrep SAST Scan + runs-on: ubuntu-latest + container: + image: semgrep/semgrep + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Run Semgrep + run: semgrep ci --sarif --output=semgrep.sarif + env: + SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }} + + - name: Upload SARIF results + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: semgrep.sarif + if: always() diff --git a/.gitignore b/.gitignore index 2acd8a2..126789b 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ node_modules/ # Build output dist/ build/ +coverage/ # Environment .env @@ -25,3 +26,20 @@ Thumbs.db .claude/user-team-info.json .claude/tasks/ CLAUDE.local.md + +# Docker volumes (local data) +.docker-data/ + +# Logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Test artifacts +*.lcov + +# Temporary files +tmp/ +temp/ + diff --git a/.mcp.json b/.mcp.json index f7429ac..dd965a5 100644 --- a/.mcp.json +++ b/.mcp.json @@ -1,69 +1,80 @@ { "mcpServers": { - "jira": { + "github": { "type": "stdio", "command": "npx", - "args": ["-y", "@anthropic/mcp-jira"], + "args": ["-y", "@anthropic/mcp-github"], "env": { - "JIRA_HOST": "${JIRA_HOST}", - "JIRA_EMAIL": "${JIRA_EMAIL}", - "JIRA_API_TOKEN": "${JIRA_API_TOKEN}" + "GITHUB_TOKEN": "${GITHUB_TOKEN}" } }, - "github": { + "serena": { + "type": "stdio", + "command": "uvx", + "args": ["--from", "serena-agent", "serena", "--host", "${SERENA_HOST:-http://localhost:8384}"], + "env": { + "SERENA_API_KEY": "${SERENA_API_KEY}" + } + }, + + "context7": { "type": "stdio", "command": "npx", - "args": ["-y", "@anthropic/mcp-github"], + "args": ["-y", "@upstash/context7-mcp"], "env": { - "GITHUB_TOKEN": "${GITHUB_TOKEN}" + "CONTEXT7_API_KEY": "${CONTEXT7_API_KEY}" } }, - "linear": { + "surrealdb": { "type": "stdio", "command": "npx", - "args": ["-y", "@anthropic/mcp-linear"], + "args": ["-y", "surrealdb-mcp"], "env": { - "LINEAR_API_KEY": "${LINEAR_API_KEY}" + "SURREALDB_URL": "${SURREALDB_URL:-http://localhost:8081}", + "SURREALDB_USER": "${SURREALDB_USER:-root}", + "SURREALDB_PASS": "${SURREALDB_PASS:-root}", + "SURREALDB_NS": "${SURREALDB_NS:-claudia}", + "SURREALDB_DB": "${SURREALDB_DB:-main}" } }, - "sentry": { + "searxng": { "type": "stdio", "command": "npx", - "args": ["-y", "@anthropic/mcp-sentry"], + "args": ["-y", "@anthropic/mcp-web-search"], "env": { - "SENTRY_AUTH_TOKEN": "${SENTRY_AUTH_TOKEN}", - "SENTRY_ORG": "${SENTRY_ORG}" + "SEARXNG_URL": "${SEARXNG_URL:-http://localhost:8080}" } }, - "postgres": { + "ollama": { "type": "stdio", "command": "npx", - "args": ["-y", "@anthropic/mcp-postgres"], + "args": ["-y", "ollama-mcp"], "env": { - "DATABASE_URL": "${DATABASE_URL}" + "OLLAMA_HOST": "${OLLAMA_HOST:-http://localhost:11434}" } }, - "slack": { + "sentry": { "type": "stdio", "command": "npx", - "args": ["-y", "@anthropic/mcp-slack"], + "args": ["-y", "@anthropic/mcp-sentry"], "env": { - "SLACK_BOT_TOKEN": "${SLACK_BOT_TOKEN}", - "SLACK_TEAM_ID": "${SLACK_TEAM_ID}" + "SENTRY_AUTH_TOKEN": "${SENTRY_AUTH_TOKEN}", + "SENTRY_ORG": "${SENTRY_ORG}" } }, - "notion": { + "slack": { "type": "stdio", "command": "npx", - "args": ["-y", "@anthropic/mcp-notion"], + "args": ["-y", "@anthropic/mcp-slack"], "env": { - "NOTION_API_KEY": "${NOTION_API_KEY}" + "SLACK_BOT_TOKEN": "${SLACK_BOT_TOKEN}", + "SLACK_TEAM_ID": "${SLACK_TEAM_ID}" } }, diff --git a/README.md b/README.md index 43a3fad..a4eebef 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,55 @@ Once you've got Claude Code set up, you can point it at your codebase, have it learn your conventions, pull in best practices, and refine everything until it's basically operating like a super-powered teammate. **The real unlock is building a solid set of reusable "[skills](#skills---domain-knowledge)" plus a few "[agents](#agents---specialized-assistants)" for the stuff you do all the time.** +## πŸš€ Quick Start + +### Prerequisites +- Docker and Docker Compose +- Node.js 20+ +- GitHub CLI (`gh`) +- Claude Code CLI + +### Development Setup + +1. **Clone and start services:** + ```bash + git clone https://github.com/bjoernbethge/Claudia.git + cd Claudia + docker compose -f docker-compose.dev.yml up -d + ``` + +2. **Or use DevContainers (recommended):** + - Open in VS Code with Remote Containers extension + - Select "Reopen in Container" + - All services start automatically + +3. **Configure environment:** + ```bash + cp .env.example .env + # Edit .env with your API keys + ``` + +## πŸ—οΈ Architecture + +### Local Services (Docker) + +| Service | Port | Description | +|---------|------|-------------| +| **Ollama** | 11434 | Local LLM inference server | +| **SearXNG** | 8080 | Privacy-respecting metasearch | +| **SurrealDB** | 8081 | Multi-model database | + +### MCP Servers + +| Server | Purpose | +|--------|---------| +| **GitHub** | Issue tracking, PRs, repository management | +| **Serena** | AI agent integration and orchestration | +| **Context7** | Context retrieval and management | +| **SurrealDB** | Database operations via MCP | +| **SearXNG** | Web search via MCP | +| **Ollama** | Local LLM inference via MCP | + ### What This Looks Like in Practice **Custom UI Library?** We have a [skill that explains exactly how to use it](.claude/skills/core-components/SKILL.md). Same for [how we write tests](.claude/skills/testing-patterns/SKILL.md), [how we structure GraphQL](.claude/skills/graphql-schema/SKILL.md), and basically how we want everything done in our repo. So when Claude generates code, it already matches our patterns and standards out of the box. @@ -17,13 +66,18 @@ Once you've got Claude Code set up, you can point it at your codebase, have it l - [Weekly code quality](.github/workflows/scheduled-claude-code-quality.yml) - Reviews random directories and auto-fixes issues - [Biweekly dependency audit](.github/workflows/scheduled-claude-code-dependency-audit.yml) - Safe dependency updates with test verification +**Security Scanning?** Multiple layers of automated security: +- [Semgrep SAST](.github/workflows/semgrep.yml) - Static analysis on every PR +- [CodeQL Analysis](.github/workflows/codeql.yml) - GitHub's semantic code analysis +- [Dependabot](.github/dependabot.yml) - Automated dependency updates + **Intelligent Skill Suggestions?** We built a [skill evaluation system](#skill-evaluation-hooks) that analyzes every prompt and automatically suggests which skills Claude should activate based on keywords, file paths, and intent patterns. A ton of maintenance and quality work is just... automated. It runs ridiculously smoothly. -**JIRA/Linear Integration?** We connect Claude Code to our ticket system via [MCP servers](.mcp.json). Now Claude can read the ticket, understand the requirements, implement the feature, update the ticket status, and even create new tickets if it finds bugs along the way. The [`/ticket` command](.claude/commands/ticket.md) handles the entire workflowβ€”from reading acceptance criteria to linking the PR back to the ticket. +**GitHub Issue Integration?** We connect Claude Code to GitHub Issues via [MCP servers](.mcp.json). Now Claude can read the issue, understand the requirements, implement the feature, update the issue status, and even create new issues if it finds bugs along the way. The [`/ticket` command](.claude/commands/ticket.md) handles the entire workflowβ€”from reading acceptance criteria to linking the PR back to the issue. -We even use Claude Code for ticket triage. It reads the ticket, digs into the codebase, and leaves a comment with what it thinks should be done. So when an engineer picks it up, they're basically starting halfway through already. +We even use Claude Code for issue triage. It reads the issue, digs into the codebase, and leaves a comment with what it thinks should be done. So when an engineer picks it up, they're basically starting halfway through already. **There is so much low-hanging fruit here that it honestly blows my mind people aren't all over it.** @@ -235,7 +289,7 @@ The main configuration file for hooks, environment variables, and permissions. ### MCP Servers - External Integrations -MCP (Model Context Protocol) servers let Claude Code connect to external tools like JIRA, GitHub, Slack, databases, and more. This is how you enable workflows like "read a ticket, implement it, and update the ticket status." +MCP (Model Context Protocol) servers let Claude Code connect to external tools like GitHub Issues, databases, search engines, and AI services. This is how you enable workflows like "read an issue, implement it, and link the PR." **Location:** `.mcp.json` (project root, committed to git for team sharing) @@ -246,11 +300,11 @@ MCP (Model Context Protocol) servers let Claude Code connect to external tools l ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Claude Code │────▢│ MCP Server │────▢│ External API β”‚ -β”‚ │◀────│ (local bridge) │◀────│ (JIRA, GitHub) β”‚ +β”‚ │◀────│ (local bridge) │◀────│ (GitHub, etc.) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` -MCP servers run locally and provide Claude with tools to interact with external services. When you configure a JIRA MCP server, Claude gets tools like `jira_get_issue`, `jira_update_issue`, `jira_create_issue`, etc. +MCP servers run locally and provide Claude with tools to interact with external services. When you configure a GitHub MCP server, Claude gets tools like `github_get_issue`, `github_create_pr`, `github_add_comment`, etc. #### .mcp.json Format @@ -274,25 +328,23 @@ MCP servers run locally and provide Claude with tools to interact with external | Field | Required | Description | |-------|----------|-------------| | `type` | Yes | Server type: `stdio` (local process) or `http` (remote) | -| `command` | For stdio | Executable to run (e.g., `npx`, `python`) | +| `command` | For stdio | Executable to run (e.g., `npx`, `python`, `uvx`) | | `args` | No | Command-line arguments | | `env` | No | Environment variables (supports `${VAR}` expansion) | | `url` | For http | Remote server URL | | `headers` | For http | HTTP headers for authentication | -#### Example: JIRA Integration +#### Example: GitHub Issues Integration ```json { "mcpServers": { - "jira": { + "github": { "type": "stdio", "command": "npx", - "args": ["-y", "@anthropic/mcp-jira"], + "args": ["-y", "@anthropic/mcp-github"], "env": { - "JIRA_HOST": "${JIRA_HOST}", - "JIRA_EMAIL": "${JIRA_EMAIL}", - "JIRA_API_TOKEN": "${JIRA_API_TOKEN}" + "GITHUB_TOKEN": "${GITHUB_TOKEN}" } } } @@ -300,18 +352,18 @@ MCP servers run locally and provide Claude with tools to interact with external ``` **What this enables:** -- Read ticket details, acceptance criteria, and comments -- Update ticket status (To Do β†’ In Progress β†’ In Review) -- Add comments with progress updates -- Create new tickets for bugs found during development -- Link PRs to tickets +- Read issue details, labels, and comments +- Update issue labels and add comments +- Create new issues for bugs found during development +- Create PRs and link them to issues +- Manage milestones and projects **Example workflow with [`/ticket` command](.claude/commands/ticket.md):** ``` -You: /ticket PROJ-123 +You: /ticket 42 Claude: -1. Fetching PROJ-123 from JIRA... +1. Fetching Issue #42 from GitHub... "Add user profile avatar upload" 2. Reading acceptance criteria... @@ -322,57 +374,73 @@ Claude: 3. Searching codebase for related files... Found: src/screens/Profile/ProfileScreen.tsx -4. Creating branch: cw/PROJ-123-avatar-upload +4. Creating branch: cw/42-avatar-upload 5. [Implements feature...] -6. Updating JIRA status to "In Review" - Adding comment: "PR #456 ready for review" +6. Adding comment to Issue #42 + "PR #56 ready for review" -7. Creating PR linked to PROJ-123... +7. Creating PR linked to Issue #42... + Body includes: "Closes #42" ``` #### Common MCP Server Configurations -**Issue Tracking:** +**Issue Tracking & Code:** ```json { - "jira": { + "github": { "type": "stdio", "command": "npx", - "args": ["-y", "@anthropic/mcp-jira"], - "env": { - "JIRA_HOST": "${JIRA_HOST}", - "JIRA_EMAIL": "${JIRA_EMAIL}", - "JIRA_API_TOKEN": "${JIRA_API_TOKEN}" - } + "args": ["-y", "@anthropic/mcp-github"], + "env": { "GITHUB_TOKEN": "${GITHUB_TOKEN}" } + } +} +``` + +**AI Agent Integration:** +```json +{ + "serena": { + "type": "stdio", + "command": "uvx", + "args": ["--from", "serena-agent", "serena", "--host", "${SERENA_HOST:-http://localhost:8384}"], + "env": { "SERENA_API_KEY": "${SERENA_API_KEY}" } }, - "linear": { + "context7": { "type": "stdio", "command": "npx", - "args": ["-y", "@anthropic/mcp-linear"], - "env": { "LINEAR_API_KEY": "${LINEAR_API_KEY}" } + "args": ["-y", "@upstash/context7-mcp"], + "env": { "CONTEXT7_API_KEY": "${CONTEXT7_API_KEY}" } } } ``` -**Code & DevOps:** +**Local Services (Docker):** ```json { - "github": { + "surrealdb": { "type": "stdio", "command": "npx", - "args": ["-y", "@anthropic/mcp-github"], - "env": { "GITHUB_TOKEN": "${GITHUB_TOKEN}" } + "args": ["-y", "surrealdb-mcp"], + "env": { + "SURREALDB_URL": "${SURREALDB_URL:-http://localhost:8081}", + "SURREALDB_USER": "${SURREALDB_USER:-root}", + "SURREALDB_PASS": "${SURREALDB_PASS:-root}" + } }, - "sentry": { + "searxng": { "type": "stdio", "command": "npx", - "args": ["-y", "@anthropic/mcp-sentry"], - "env": { - "SENTRY_AUTH_TOKEN": "${SENTRY_AUTH_TOKEN}", - "SENTRY_ORG": "${SENTRY_ORG}" - } + "args": ["-y", "@anthropic/mcp-web-search"], + "env": { "SEARXNG_URL": "${SEARXNG_URL:-http://localhost:8080}" } + }, + "ollama": { + "type": "stdio", + "command": "npx", + "args": ["-y", "ollama-mcp"], + "env": { "OLLAMA_HOST": "${OLLAMA_HOST:-http://localhost:11434}" } } } ``` @@ -392,18 +460,6 @@ Claude: } ``` -**Databases:** -```json -{ - "postgres": { - "type": "stdio", - "command": "npx", - "args": ["-y", "@anthropic/mcp-postgres"], - "env": { "DATABASE_URL": "${DATABASE_URL}" } - } -} -``` - #### Environment Variables MCP configs support variable expansion: @@ -412,9 +468,9 @@ MCP configs support variable expansion: Set these in your shell profile or `.env` file (don't commit secrets!): ```bash -export JIRA_HOST="https://yourcompany.atlassian.net" -export JIRA_EMAIL="you@company.com" -export JIRA_API_TOKEN="your-api-token" +export GITHUB_TOKEN="ghp_your-github-token" +export SERENA_API_KEY="your-serena-key" +export CONTEXT7_API_KEY="your-context7-key" ``` #### Settings for MCP @@ -901,13 +957,17 @@ Commit everything except: | [CLAUDE.md](CLAUDE.md) | Example project memory file | | [.claude/settings.json](.claude/settings.json) | Full hooks configuration | | [.claude/settings.md](.claude/settings.md) | Human-readable hooks documentation | -| [.mcp.json](.mcp.json) | MCP server configuration (JIRA, GitHub, Slack, etc.) | +| [.mcp.json](.mcp.json) | MCP server configuration (GitHub, Serena, Context7, etc.) | +| **Development Environment** | | +| [.devcontainer/devcontainer.json](.devcontainer/devcontainer.json) | VS Code DevContainer configuration | +| [docker-compose.dev.yml](docker-compose.dev.yml) | Docker services (Ollama, SearXNG, SurrealDB) | +| [.github/copilot-instructions.md](.github/copilot-instructions.md) | GitHub Copilot configuration | | **Agents** | | | [.claude/agents/code-reviewer.md](.claude/agents/code-reviewer.md) | Comprehensive code review agent | | [.claude/agents/github-workflow.md](.claude/agents/github-workflow.md) | Git workflow agent | | **Commands** | | | [.claude/commands/onboard.md](.claude/commands/onboard.md) | Deep task exploration | -| [.claude/commands/ticket.md](.claude/commands/ticket.md) | **JIRA/Linear ticket workflow (read β†’ implement β†’ update)** | +| [.claude/commands/ticket.md](.claude/commands/ticket.md) | **GitHub Issue workflow (read β†’ implement β†’ PR)** | | [.claude/commands/pr-review.md](.claude/commands/pr-review.md) | PR review workflow | | [.claude/commands/pr-summary.md](.claude/commands/pr-summary.md) | Generate PR summary | | [.claude/commands/code-quality.md](.claude/commands/code-quality.md) | Quality checks | @@ -924,10 +984,14 @@ Commit everything except: | [.claude/skills/core-components/SKILL.md](.claude/skills/core-components/SKILL.md) | Design system, tokens | | [.claude/skills/formik-patterns/SKILL.md](.claude/skills/formik-patterns/SKILL.md) | Form handling, validation | | **GitHub Workflows** | | +| [.github/workflows/ci.yml](.github/workflows/ci.yml) | CI pipeline (lint, test, build) | +| [.github/workflows/semgrep.yml](.github/workflows/semgrep.yml) | Semgrep security scanning | +| [.github/workflows/codeql.yml](.github/workflows/codeql.yml) | CodeQL analysis | | [.github/workflows/pr-claude-code-review.yml](.github/workflows/pr-claude-code-review.yml) | Auto PR review | | [.github/workflows/scheduled-claude-code-docs-sync.yml](.github/workflows/scheduled-claude-code-docs-sync.yml) | Monthly docs sync | | [.github/workflows/scheduled-claude-code-quality.yml](.github/workflows/scheduled-claude-code-quality.yml) | Weekly quality review | | [.github/workflows/scheduled-claude-code-dependency-audit.yml](.github/workflows/scheduled-claude-code-dependency-audit.yml) | Biweekly dependency audit | +| [.github/dependabot.yml](.github/dependabot.yml) | Dependabot configuration | --- diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml new file mode 100644 index 0000000..02013f4 --- /dev/null +++ b/docker-compose.dev.yml @@ -0,0 +1,72 @@ +# Docker Compose for Development Services +# This file sets up all required services for local development + +services: + # Ollama - Local LLM inference server + ollama: + image: ollama/ollama:latest + container_name: claudia-ollama + ports: + - "11434:11434" + volumes: + - ollama-data:/root/.ollama + environment: + - OLLAMA_HOST=0.0.0.0 + restart: unless-stopped + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:11434/api/version"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 30s + + # SearXNG - Privacy-respecting metasearch engine + searxng: + image: searxng/searxng:latest + container_name: claudia-searxng + ports: + - "8080:8080" + volumes: + - searxng-data:/etc/searxng + environment: + - SEARXNG_BASE_URL=http://localhost:8080 + - SEARXNG_SECRET_KEY=${SEARXNG_SECRET_KEY:-changeme-generate-random-key} + restart: unless-stopped + healthcheck: + test: ["CMD", "wget", "--spider", "-q", "http://localhost:8080/healthz"] + interval: 30s + timeout: 10s + retries: 3 + + # SurrealDB - Multi-model database + surrealdb: + image: surrealdb/surrealdb:latest + container_name: claudia-surrealdb + ports: + - "8081:8000" + volumes: + - surrealdb-data:/data + command: start --user root --pass ${SURREALDB_ROOT_PASSWORD:-root} file:/data/database.db + restart: unless-stopped + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8000/health"] + interval: 30s + timeout: 10s + retries: 3 + + # Note: Ollama already provides an OpenAI-compatible API endpoint at /v1 + # This service is optional and can be used if you need additional proxy features + # To use Ollama's built-in OpenAI compatibility, just use http://localhost:11434/v1 + +volumes: + ollama-data: + driver: local + searxng-data: + driver: local + surrealdb-data: + driver: local + +networks: + default: + name: claudia-network + driver: bridge