Compare commits
83 Commits
v3.0.0
...
ad0e14d07f
| Author | SHA1 | Date | |
|---|---|---|---|
| ad0e14d07f | |||
| 7fd5fffedf | |||
| 0fe4f62a30 | |||
| 533810f018 | |||
| 2ee23a39d8 | |||
| 894c85bd54 | |||
| 01809a7367 | |||
| a20f1bfdf8 | |||
| 7879e07815 | |||
| eced0fbd07 | |||
| aa6d7f5866 | |||
| 3e5197779d | |||
| 9206931a3c | |||
| ff3be54f1c | |||
| 1b0f5f4973 | |||
| 8ed0d8f207 | |||
| 007b55916c | |||
| eeef35aa61 | |||
| be2d989899 | |||
| 306143882a | |||
| 0c07820b5a | |||
| d2ad90d5bb | |||
| 642dca7062 | |||
| faafced061 | |||
| c3df0f95e6 | |||
| f714957d83 | |||
| 40af243229 | |||
| 69b71fc7cf | |||
| 5ad207520a | |||
| 78d77c1e0a | |||
| 5cf43d5de2 | |||
| 51ef10633b | |||
| 83094598c5 | |||
| 5da29c8e35 | |||
| 4f3560d121 | |||
| d5e521a759 | |||
| b2c51251f3 | |||
| 71efa1aafa | |||
| aa3ff016e2 | |||
| 4557d2ce40 | |||
| d282a65fc6 | |||
| ad56700059 | |||
| df2f5ebb47 | |||
| feb86b059f | |||
| c23e84f965 | |||
| 195ca5c10c | |||
| 53f1b9662f | |||
| eeffb9e853 | |||
| 6c142a9710 | |||
| f781c6f7b1 | |||
| 8228c20d47 | |||
| 85953d8e1e | |||
| f8b6131bfc | |||
| cd3d4c69f0 | |||
| 7f6e0893dd | |||
| 39105688a5 | |||
| 2a6b3df8e1 | |||
| 0c2fc8c0d9 | |||
| b5144de0cf | |||
| 29c54279a9 | |||
| 178593f355 | |||
| a70df64cae | |||
| 2a2ac5f85e | |||
| e01ba74e84 | |||
| 565540d0ba | |||
| 394c91f8cf | |||
| 89bfd98d9f | |||
| 5c9dd8d6e0 | |||
| 374912b463 | |||
| debb91aa7e | |||
| 40860c172e | |||
| 50ebe83c0a | |||
| 7295345013 | |||
| a2502c708b | |||
| 4ede59e89a | |||
| 3017e4c097 | |||
| de7675a649 | |||
| aa7bb8f1a4 | |||
| 0a8af05f9c | |||
| 04322732bc | |||
| 09d82b310e | |||
| 50b45f4834 | |||
| 1c694b6469 |
@@ -1,27 +1,26 @@
|
||||
{
|
||||
"name": "lm-claude-plugins",
|
||||
"name": "leo-claude-mktplace",
|
||||
"owner": {
|
||||
"name": "Leo Miranda",
|
||||
"email": "leobmiranda@gmail.com"
|
||||
},
|
||||
"metadata": {
|
||||
"description": "Project management plugins with Gitea and NetBox integrations",
|
||||
"version": "3.0.0"
|
||||
"version": "3.1.0"
|
||||
},
|
||||
"plugins": [
|
||||
{
|
||||
"name": "projman",
|
||||
"version": "3.0.0",
|
||||
"version": "3.1.0",
|
||||
"description": "Sprint planning and project management with Gitea integration",
|
||||
"source": "./plugins/projman",
|
||||
"author": {
|
||||
"name": "Leo Miranda",
|
||||
"email": "leobmiranda@gmail.com"
|
||||
},
|
||||
"homepage": "https://gitea.hotserv.cloud/personal-projects/support-claude-mktplace/src/branch/main/plugins/projman/README.md",
|
||||
"repository": "https://gitea.hotserv.cloud/personal-projects/support-claude-mktplace.git",
|
||||
"mcpServers": ["gitea"],
|
||||
"integrationFile": "claude-md-integration.md",
|
||||
"homepage": "https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace/src/branch/main/plugins/projman/README.md",
|
||||
"repository": "https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace.git",
|
||||
"mcpServers": ["./.mcp.json"],
|
||||
"category": "development",
|
||||
"tags": ["sprint", "agile", "gitea", "project-management"],
|
||||
"license": "MIT"
|
||||
@@ -35,11 +34,9 @@
|
||||
"name": "Leo Miranda",
|
||||
"email": "leobmiranda@gmail.com"
|
||||
},
|
||||
"homepage": "https://gitea.hotserv.cloud/personal-projects/support-claude-mktplace/src/branch/main/plugins/doc-guardian/README.md",
|
||||
"repository": "https://gitea.hotserv.cloud/personal-projects/support-claude-mktplace.git",
|
||||
"mcpServers": [],
|
||||
"integrationFile": "claude-md-integration.md",
|
||||
"hooks": ["PostToolUse", "Stop"],
|
||||
"homepage": "https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace/src/branch/main/plugins/doc-guardian/README.md",
|
||||
"repository": "https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace.git",
|
||||
"hooks": ["./hooks/hooks.json"],
|
||||
"category": "productivity",
|
||||
"tags": ["documentation", "drift-detection", "sync"],
|
||||
"license": "MIT"
|
||||
@@ -53,11 +50,9 @@
|
||||
"name": "Leo Miranda",
|
||||
"email": "leobmiranda@gmail.com"
|
||||
},
|
||||
"homepage": "https://gitea.hotserv.cloud/personal-projects/support-claude-mktplace/src/branch/main/plugins/code-sentinel/README.md",
|
||||
"repository": "https://gitea.hotserv.cloud/personal-projects/support-claude-mktplace.git",
|
||||
"mcpServers": [],
|
||||
"integrationFile": "claude-md-integration.md",
|
||||
"hooks": ["PreToolUse"],
|
||||
"homepage": "https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace/src/branch/main/plugins/code-sentinel/README.md",
|
||||
"repository": "https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace.git",
|
||||
"hooks": ["./hooks/hooks.json"],
|
||||
"category": "security",
|
||||
"tags": ["security-scan", "refactoring", "vulnerabilities"],
|
||||
"license": "MIT"
|
||||
@@ -71,11 +66,9 @@
|
||||
"name": "Leo Miranda",
|
||||
"email": "leobmiranda@gmail.com"
|
||||
},
|
||||
"homepage": "https://gitea.hotserv.cloud/personal-projects/support-claude-mktplace/src/branch/main/plugins/project-hygiene/README.md",
|
||||
"repository": "https://gitea.hotserv.cloud/personal-projects/support-claude-mktplace.git",
|
||||
"mcpServers": [],
|
||||
"integrationFile": "claude-md-integration.md",
|
||||
"hooks": ["PostToolUse"],
|
||||
"homepage": "https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace/src/branch/main/plugins/project-hygiene/README.md",
|
||||
"repository": "https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace.git",
|
||||
"hooks": ["./hooks/hooks.json"],
|
||||
"category": "productivity",
|
||||
"tags": ["cleanup", "automation", "hygiene"],
|
||||
"license": "MIT"
|
||||
@@ -89,10 +82,9 @@
|
||||
"name": "Leo Miranda",
|
||||
"email": "leobmiranda@gmail.com"
|
||||
},
|
||||
"homepage": "https://gitea.hotserv.cloud/personal-projects/support-claude-mktplace/src/branch/main/plugins/cmdb-assistant/README.md",
|
||||
"repository": "https://gitea.hotserv.cloud/personal-projects/support-claude-mktplace.git",
|
||||
"mcpServers": ["netbox"],
|
||||
"integrationFile": "claude-md-integration.md",
|
||||
"homepage": "https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace/src/branch/main/plugins/cmdb-assistant/README.md",
|
||||
"repository": "https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace.git",
|
||||
"mcpServers": ["./.mcp.json"],
|
||||
"category": "infrastructure",
|
||||
"tags": ["cmdb", "netbox", "dcim", "ipam"],
|
||||
"license": "MIT"
|
||||
@@ -106,10 +98,8 @@
|
||||
"name": "Leo Miranda",
|
||||
"email": "leobmiranda@gmail.com"
|
||||
},
|
||||
"homepage": "https://gitea.hotserv.cloud/personal-projects/support-claude-mktplace/src/branch/main/plugins/claude-config-maintainer/README.md",
|
||||
"repository": "https://gitea.hotserv.cloud/personal-projects/support-claude-mktplace.git",
|
||||
"mcpServers": [],
|
||||
"integrationFile": "claude-md-integration.md",
|
||||
"homepage": "https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace/src/branch/main/plugins/claude-config-maintainer/README.md",
|
||||
"repository": "https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace.git",
|
||||
"category": "development",
|
||||
"tags": ["claude-md", "configuration", "optimization"],
|
||||
"license": "MIT"
|
||||
@@ -123,10 +113,8 @@
|
||||
"name": "Leo Miranda",
|
||||
"email": "leobmiranda@gmail.com"
|
||||
},
|
||||
"homepage": "https://gitea.hotserv.cloud/personal-projects/support-claude-mktplace/src/branch/main/plugins/clarity-assist/README.md",
|
||||
"repository": "https://gitea.hotserv.cloud/personal-projects/support-claude-mktplace.git",
|
||||
"mcpServers": [],
|
||||
"integrationFile": "claude-md-integration.md",
|
||||
"homepage": "https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace/src/branch/main/plugins/clarity-assist/README.md",
|
||||
"repository": "https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace.git",
|
||||
"category": "productivity",
|
||||
"tags": ["prompts", "requirements", "clarification", "nd-friendly"],
|
||||
"license": "MIT"
|
||||
@@ -140,10 +128,8 @@
|
||||
"name": "Leo Miranda",
|
||||
"email": "leobmiranda@gmail.com"
|
||||
},
|
||||
"homepage": "https://gitea.hotserv.cloud/personal-projects/support-claude-mktplace/src/branch/main/plugins/git-flow/README.md",
|
||||
"repository": "https://gitea.hotserv.cloud/personal-projects/support-claude-mktplace.git",
|
||||
"mcpServers": [],
|
||||
"integrationFile": "claude-md-integration.md",
|
||||
"homepage": "https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace/src/branch/main/plugins/git-flow/README.md",
|
||||
"repository": "https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace.git",
|
||||
"category": "development",
|
||||
"tags": ["git", "workflow", "commits", "branching"],
|
||||
"license": "MIT"
|
||||
@@ -157,24 +143,12 @@
|
||||
"name": "Leo Miranda",
|
||||
"email": "leobmiranda@gmail.com"
|
||||
},
|
||||
"homepage": "https://gitea.hotserv.cloud/personal-projects/support-claude-mktplace/src/branch/main/plugins/pr-review/README.md",
|
||||
"repository": "https://gitea.hotserv.cloud/personal-projects/support-claude-mktplace.git",
|
||||
"mcpServers": ["gitea"],
|
||||
"integrationFile": "claude-md-integration.md",
|
||||
"homepage": "https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace/src/branch/main/plugins/pr-review/README.md",
|
||||
"repository": "https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace.git",
|
||||
"mcpServers": ["./.mcp.json"],
|
||||
"category": "development",
|
||||
"tags": ["code-review", "pull-requests", "security", "quality"],
|
||||
"license": "MIT"
|
||||
}
|
||||
],
|
||||
"pluginDetection": {
|
||||
"mcpServerMapping": {
|
||||
"gitea": "projman",
|
||||
"netbox": "cmdb-assistant"
|
||||
},
|
||||
"hookMapping": {
|
||||
"PostToolUse:Write|Edit": "project-hygiene",
|
||||
"PostToolUse:Write|Edit|MultiEdit": "doc-guardian",
|
||||
"PreToolUse:Write|Edit|MultiEdit": "code-sentinel"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
66
CHANGELOG.md
66
CHANGELOG.md
@@ -1,9 +1,71 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to lm-claude-plugins will be documented in this file.
|
||||
All notable changes to the Leo Claude Marketplace will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||
|
||||
## [3.1.0] - 2026-01-21
|
||||
|
||||
### Added
|
||||
|
||||
#### Debug Workflow Commands (projman)
|
||||
- **`/debug-report`** - Run diagnostics in test projects, create structured issues in marketplace
|
||||
- Runs 5 diagnostic MCP tool tests with explicit repo parameter
|
||||
- Captures full project context (git remote, cwd, branch)
|
||||
- Generates structured issue with hypothesis and investigation steps
|
||||
- Creates issue in configured marketplace repository automatically
|
||||
|
||||
- **`/debug-review`** - Investigate diagnostic issues with human approval gates
|
||||
- Lists open diagnostic issues for triage
|
||||
- Maps errors to relevant code files using error-to-file mapping
|
||||
- MANDATORY: Reads relevant files before proposing any fix
|
||||
- Three approval gates: investigation summary, fix approach, PR creation
|
||||
- Creates feature branch, commits, and PR with proper linking
|
||||
|
||||
#### MCP Server Improvements
|
||||
- Dynamic label format detection in `suggest_labels`
|
||||
- Supports slash format (`Type/Bug`) and colon-space format (`Type: Bug`)
|
||||
- Fetches actual labels from repo and matches suggestions to real format
|
||||
- Handles Effort/Efforts singular/plural normalization
|
||||
|
||||
### Changed
|
||||
- **`/labels-sync`** completely rewritten with explicit execution steps
|
||||
- Step 1 now explicitly requires running `git remote get-url origin` via Bash
|
||||
- All MCP tool calls show required `repo` parameter
|
||||
- Added "DO NOT" section preventing common mistakes
|
||||
- Removed confusing "Label Reference" section that caused file creation prompts
|
||||
|
||||
### Fixed
|
||||
- MCP tools no longer fail with "Use 'owner/repo' format" error
|
||||
- Root cause: MCP server is sandboxed and cannot auto-detect project directory
|
||||
- Solution: Command documentation now instructs Claude to detect repo via Bash first
|
||||
|
||||
---
|
||||
|
||||
## [3.0.1] - 2026-01-21
|
||||
|
||||
### Added
|
||||
- `/project-init` command for quick project setup when system is already configured
|
||||
- `/project-sync` command to sync .env with git remote after repository move/rename
|
||||
- SessionStart hooks for automatic mismatch detection between git remote and .env
|
||||
- Interactive setup wizard (`/initial-setup`) redesigned to use Claude tools instead of bash script
|
||||
|
||||
### Changed
|
||||
- `GITEA_ORG` moved from system-level to project-level configuration (different projects may belong to different organizations)
|
||||
- Environment variables renamed to match MCP server expectations:
|
||||
- `GITEA_URL` → `GITEA_API_URL` (must include `/api/v1`)
|
||||
- `GITEA_TOKEN` → `GITEA_API_TOKEN`
|
||||
- `NETBOX_URL` → `NETBOX_API_URL` (must include `/api`)
|
||||
- `NETBOX_TOKEN` → `NETBOX_API_TOKEN`
|
||||
- Setup commands now validate repository via Gitea API before saving configuration
|
||||
- README.md simplified to show only wizard setup path (manual setup moved to CONFIGURATION.md)
|
||||
|
||||
### Fixed
|
||||
- API URL paths in curl commands (removed redundant `/api/v1` since it's now in the URL variable)
|
||||
- Documentation now correctly references environment variable names
|
||||
|
||||
---
|
||||
|
||||
## [3.0.0] - 2026-01-20
|
||||
|
||||
### Added
|
||||
@@ -45,7 +107,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||
- `docs/CONFIGURATION.md` - Centralized configuration guide for all plugins
|
||||
|
||||
### Changed
|
||||
- **BREAKING:** Marketplace renamed from `claude-code-marketplace` to `lm-claude-plugins`
|
||||
- **BREAKING:** Marketplace renamed from `claude-code-marketplace` to `leo-claude-mktplace`
|
||||
- **BREAKING:** MCP servers moved from plugin directories to shared `mcp-servers/` at repository root
|
||||
- All plugins now have `category`, `tags`, and `license` fields in marketplace.json
|
||||
- Plugin MCP dependencies now use symlinks to shared servers
|
||||
|
||||
103
CLAUDE.md
103
CLAUDE.md
@@ -4,11 +4,11 @@ This file provides guidance to Claude Code when working with code in this reposi
|
||||
|
||||
## Project Overview
|
||||
|
||||
**Repository:** lm-claude-plugins
|
||||
**Version:** 3.0.0
|
||||
**Repository:** leo-claude-mktplace
|
||||
**Version:** 3.0.1
|
||||
**Status:** Production Ready
|
||||
|
||||
A Claude Code plugin marketplace containing:
|
||||
A plugin marketplace for Claude Code containing:
|
||||
|
||||
| Plugin | Description | Version |
|
||||
|--------|-------------|---------|
|
||||
@@ -28,18 +28,27 @@ A Claude Code plugin marketplace containing:
|
||||
# Validate marketplace compliance
|
||||
./scripts/validate-marketplace.sh
|
||||
|
||||
# Run projman commands (in a target project with plugin installed)
|
||||
/sprint-plan # Start sprint planning
|
||||
/sprint-status # Check progress
|
||||
/review # Pre-close code quality review
|
||||
/test-check # Verify tests before close
|
||||
/sprint-close # Complete sprint
|
||||
# After updates
|
||||
./scripts/post-update.sh # Rebuild venvs, verify symlinks
|
||||
```
|
||||
|
||||
### Plugin Commands by Category
|
||||
|
||||
| Category | Commands |
|
||||
|----------|----------|
|
||||
| **Setup** | `/initial-setup`, `/project-init`, `/project-sync` |
|
||||
| **Sprint** | `/sprint-plan`, `/sprint-start`, `/sprint-status`, `/sprint-close` |
|
||||
| **Quality** | `/review`, `/test-check`, `/test-gen` |
|
||||
| **PR Review** | `/pr-review:initial-setup`, `/pr-review:project-init` |
|
||||
| **Docs** | `/doc-audit`, `/doc-sync` |
|
||||
| **Security** | `/security-scan`, `/refactor`, `/refactor-dry` |
|
||||
| **Config** | `/config-analyze`, `/config-optimize` |
|
||||
| **Debug** | `/debug-report`, `/debug-review` |
|
||||
|
||||
## Repository Structure
|
||||
|
||||
```
|
||||
lm-claude-plugins/
|
||||
leo-claude-mktplace/
|
||||
├── .claude-plugin/
|
||||
│ └── marketplace.json # Marketplace manifest
|
||||
├── mcp-servers/ # SHARED MCP servers (v3.0.0+)
|
||||
@@ -50,18 +59,20 @@ lm-claude-plugins/
|
||||
│ │ ├── .claude-plugin/plugin.json
|
||||
│ │ ├── .mcp.json
|
||||
│ │ ├── mcp-servers/gitea -> ../../../mcp-servers/gitea # SYMLINK
|
||||
│ │ ├── commands/ # 9 commands
|
||||
│ │ ├── commands/ # 12 commands (incl. setup)
|
||||
│ │ ├── hooks/ # SessionStart mismatch detection
|
||||
│ │ ├── agents/ # 4 agents
|
||||
│ │ └── skills/label-taxonomy/
|
||||
│ ├── git-flow/ # Git workflow automation (NEW v3.0.0)
|
||||
│ ├── git-flow/ # Git workflow automation
|
||||
│ │ ├── .claude-plugin/plugin.json
|
||||
│ │ ├── commands/ # 8 commands
|
||||
│ │ └── agents/
|
||||
│ ├── pr-review/ # Multi-agent PR review (NEW v3.0.0)
|
||||
│ ├── pr-review/ # Multi-agent PR review
|
||||
│ │ ├── .claude-plugin/plugin.json
|
||||
│ │ ├── .mcp.json
|
||||
│ │ ├── mcp-servers/gitea -> ../../../mcp-servers/gitea # SYMLINK
|
||||
│ │ ├── commands/ # 3 commands
|
||||
│ │ ├── commands/ # 6 commands (incl. setup)
|
||||
│ │ ├── hooks/ # SessionStart mismatch detection
|
||||
│ │ └── agents/ # 5 agents
|
||||
│ ├── clarity-assist/ # Prompt optimization (NEW v3.0.0)
|
||||
│ │ ├── .claude-plugin/plugin.json
|
||||
@@ -133,8 +144,10 @@ lm-claude-plugins/
|
||||
|
||||
| Level | Location | Purpose |
|
||||
|-------|----------|---------|
|
||||
| System | `~/.config/claude/gitea.env` | Credentials (GITEA_URL, GITEA_TOKEN, GITEA_ORG) |
|
||||
| Project | `.env` in project root | Repository specification (GITEA_REPO) |
|
||||
| System | `~/.config/claude/gitea.env` | Credentials (GITEA_API_URL, GITEA_API_TOKEN) |
|
||||
| Project | `.env` in project root | Repository specification (GITEA_ORG, GITEA_REPO) |
|
||||
|
||||
**Note:** `GITEA_ORG` is at project level since different projects may belong to different organizations.
|
||||
|
||||
### Branch-Aware Security
|
||||
|
||||
@@ -199,41 +212,47 @@ Stored in Gitea Wiki under `lessons-learned/sprints/`.
|
||||
| Document | Purpose |
|
||||
|----------|---------|
|
||||
| `docs/CANONICAL-PATHS.md` | **Single source of truth** for paths |
|
||||
| `docs/COMMANDS-CHEATSHEET.md` | All commands quick reference |
|
||||
| `docs/CONFIGURATION.md` | Centralized setup guide |
|
||||
| `docs/DEBUGGING-CHECKLIST.md` | Systematic troubleshooting guide |
|
||||
| `docs/UPDATING.md` | Update guide for the marketplace |
|
||||
| `plugins/projman/CONFIGURATION.md` | Quick reference (links to central) |
|
||||
| `plugins/projman/CONFIGURATION.md` | Projman quick reference (links to central) |
|
||||
| `plugins/projman/README.md` | Projman full documentation |
|
||||
|
||||
## Versioning and Changelog Rules
|
||||
## Installation Paths
|
||||
|
||||
### Version Display
|
||||
**The marketplace version is displayed ONLY in the main `README.md` title.**
|
||||
Understanding where files live is critical for debugging:
|
||||
|
||||
- Format: `# Claude Code Marketplace - vX.Y.Z`
|
||||
- Do NOT add version numbers to individual plugin documentation titles
|
||||
- Do NOT add version numbers to configuration guides
|
||||
- Do NOT add version numbers to CLAUDE.md or other docs
|
||||
| Context | Path | Purpose |
|
||||
|---------|------|---------|
|
||||
| **Source** | `~/claude-plugins-work/` | Development - edit here |
|
||||
| **Installed** | `~/.claude/plugins/marketplaces/leo-claude-mktplace/` | Runtime - Claude uses this |
|
||||
| **Cache** | `~/.claude/` | Plugin metadata and settings |
|
||||
|
||||
### Changelog Maintenance (MANDATORY)
|
||||
**`CHANGELOG.md` is the authoritative source for version history.**
|
||||
**Key insight:** Edits to source require reinstall/update to take effect at runtime.
|
||||
|
||||
When releasing a new version:
|
||||
1. Update main `README.md` title with new version
|
||||
2. Update `CHANGELOG.md` with:
|
||||
- Version number and date: `## [X.Y.Z] - YYYY-MM-DD`
|
||||
- **Added**: New features, commands, files
|
||||
- **Changed**: Modifications to existing functionality
|
||||
- **Fixed**: Bug fixes
|
||||
- **Removed**: Deleted features, files, deprecated items
|
||||
3. Update `marketplace.json` metadata version
|
||||
4. Update plugin `plugin.json` versions if plugin-specific changes
|
||||
## Debugging & Troubleshooting
|
||||
|
||||
### Version Format
|
||||
- Follow [Semantic Versioning](https://semver.org/): MAJOR.MINOR.PATCH
|
||||
- MAJOR: Breaking changes
|
||||
- MINOR: New features, backward compatible
|
||||
- PATCH: Bug fixes, minor improvements
|
||||
See `docs/DEBUGGING-CHECKLIST.md` for systematic troubleshooting.
|
||||
|
||||
**Common Issues:**
|
||||
| Symptom | Likely Cause | Fix |
|
||||
|---------|--------------|-----|
|
||||
| "X MCP servers failed" | Missing venv in installed path | `cd ~/.claude/plugins/marketplaces/leo-claude-mktplace && ./scripts/setup.sh` |
|
||||
| MCP tools not available | Symlink broken or venv missing | Run `/debug-report` to diagnose |
|
||||
| Changes not taking effect | Editing source, not installed | Reinstall plugin or edit installed path |
|
||||
|
||||
**Debug Commands:**
|
||||
- `/debug-report` - Run full diagnostics, create issue if needed
|
||||
- `/debug-review` - Investigate and propose fixes
|
||||
|
||||
## Versioning Rules
|
||||
|
||||
- Version displayed ONLY in main `README.md` title: `# Leo Claude Marketplace - vX.Y.Z`
|
||||
- `CHANGELOG.md` is authoritative for version history
|
||||
- Follow [SemVer](https://semver.org/): MAJOR.MINOR.PATCH
|
||||
- On release: Update README title → CHANGELOG → marketplace.json → plugin.json files
|
||||
|
||||
---
|
||||
|
||||
**Last Updated:** 2026-01-20
|
||||
**Last Updated:** 2026-01-22
|
||||
|
||||
114
README.md
114
README.md
@@ -1,4 +1,4 @@
|
||||
# Claude Code Marketplace - v3.0.0
|
||||
# Leo Claude Marketplace - v3.1.0
|
||||
|
||||
A collection of Claude Code plugins for project management, infrastructure automation, and development workflows.
|
||||
|
||||
@@ -19,7 +19,7 @@ AI-guided sprint planning with full Gitea integration. Transforms a proven 15-sp
|
||||
- Branch-aware security (development/staging/production)
|
||||
- Pre-sprint-close code quality review and test verification
|
||||
|
||||
**Commands:** `/sprint-plan`, `/sprint-start`, `/sprint-status`, `/sprint-close`, `/labels-sync`, `/initial-setup`, `/review`, `/test-check`, `/test-gen`
|
||||
**Commands:** `/sprint-plan`, `/sprint-start`, `/sprint-status`, `/sprint-close`, `/labels-sync`, `/initial-setup`, `/project-init`, `/project-sync`, `/review`, `/test-check`, `/test-gen`
|
||||
|
||||
#### [git-flow](./plugins/git-flow/README.md) *NEW in v3.0.0*
|
||||
**Git Workflow Automation**
|
||||
@@ -44,7 +44,7 @@ Comprehensive pull request review using specialized agents.
|
||||
- Actionable feedback with suggested fixes
|
||||
- Gitea integration for automated review submission
|
||||
|
||||
**Commands:** `/pr-review`, `/pr-summary`, `/pr-findings`
|
||||
**Commands:** `/pr-review`, `/pr-summary`, `/pr-findings`, `/initial-setup`, `/project-init`, `/project-sync`
|
||||
|
||||
#### [claude-config-maintainer](./plugins/claude-config-maintainer/README.md)
|
||||
**CLAUDE.md Optimization and Maintenance**
|
||||
@@ -94,7 +94,7 @@ Security vulnerability detection and code refactoring tools.
|
||||
|
||||
Full CRUD operations for network infrastructure management directly from Claude Code.
|
||||
|
||||
**Commands:** `/cmdb-search`, `/cmdb-device`, `/cmdb-ip`, `/cmdb-site`
|
||||
**Commands:** `/initial-setup`, `/cmdb-search`, `/cmdb-device`, `/cmdb-ip`, `/cmdb-site`
|
||||
|
||||
## MCP Servers
|
||||
|
||||
@@ -138,7 +138,7 @@ Comprehensive NetBox REST API integration for infrastructure management.
|
||||
|
||||
**Option 1 - CLI command (recommended):**
|
||||
```bash
|
||||
/plugin marketplace add https://gitea.hotserv.cloud/personal-projects/support-claude-mktplace.git
|
||||
/plugin marketplace add https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace.git
|
||||
```
|
||||
|
||||
**Option 2 - Settings file (for team distribution):**
|
||||
@@ -147,62 +147,86 @@ Add to `.claude/settings.json` in your target project:
|
||||
```json
|
||||
{
|
||||
"extraKnownMarketplaces": {
|
||||
"lm-claude-plugins": {
|
||||
"leo-claude-mktplace": {
|
||||
"source": {
|
||||
"source": "git",
|
||||
"url": "https://gitea.hotserv.cloud/personal-projects/support-claude-mktplace.git"
|
||||
"url": "https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace.git"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Configure MCP Server Dependencies
|
||||
### Run Interactive Setup
|
||||
|
||||
Install dependencies for shared MCP servers:
|
||||
After installing plugins, run the setup wizard:
|
||||
|
||||
```bash
|
||||
# Gitea MCP (for projman, pr-review)
|
||||
cd mcp-servers/gitea
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
deactivate
|
||||
|
||||
# NetBox MCP (for cmdb-assistant)
|
||||
cd ../netbox
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
deactivate
|
||||
```
|
||||
/initial-setup
|
||||
```
|
||||
|
||||
### Configure Credentials
|
||||
The wizard handles everything:
|
||||
- Sets up MCP server (Python venv + dependencies)
|
||||
- Creates system config (`~/.config/claude/gitea.env`)
|
||||
- Guides you through adding your API token
|
||||
- Detects and validates your repository via API
|
||||
- Creates project config (`.env`)
|
||||
|
||||
See [docs/CONFIGURATION.md](./docs/CONFIGURATION.md) for complete setup instructions.
|
||||
|
||||
**Quick start:**
|
||||
```bash
|
||||
mkdir -p ~/.config/claude
|
||||
|
||||
# Gitea credentials
|
||||
cat > ~/.config/claude/gitea.env << 'EOF'
|
||||
GITEA_URL=https://gitea.example.com
|
||||
GITEA_TOKEN=your_token
|
||||
GITEA_ORG=your_org
|
||||
EOF
|
||||
chmod 600 ~/.config/claude/gitea.env
|
||||
|
||||
# Project-level settings
|
||||
cat > .env << 'EOF'
|
||||
GITEA_REPO=your-repository-name
|
||||
EOF
|
||||
**For new projects** (when system is already configured):
|
||||
```
|
||||
/project-init
|
||||
```
|
||||
|
||||
**After moving a repository:**
|
||||
```
|
||||
/project-sync
|
||||
```
|
||||
|
||||
See [docs/CONFIGURATION.md](./docs/CONFIGURATION.md) for manual setup and advanced options.
|
||||
|
||||
## Verifying Plugin Installation
|
||||
|
||||
After installing plugins, the `/plugin` command may show `(no content)` - this is normal Claude Code behavior and doesn't indicate an error.
|
||||
|
||||
**To verify a plugin is installed correctly:**
|
||||
|
||||
1. **Check installed plugins list:**
|
||||
```
|
||||
/plugin list
|
||||
```
|
||||
Look for `✔ plugin-name · Installed`
|
||||
|
||||
2. **Test a plugin command directly:**
|
||||
```
|
||||
/git-flow:git-status
|
||||
/projman:sprint-status
|
||||
/clarity-assist:clarify
|
||||
```
|
||||
If the command executes and shows output, the plugin is working.
|
||||
|
||||
3. **Check for loading errors:**
|
||||
```
|
||||
/plugin list
|
||||
```
|
||||
Look for any `Plugin Loading Errors` section - this indicates manifest issues.
|
||||
|
||||
**Command format:** All plugin commands use the format `/plugin-name:command-name`
|
||||
|
||||
| Plugin | Test Command |
|
||||
|--------|--------------|
|
||||
| git-flow | `/git-flow:git-status` |
|
||||
| projman | `/projman:sprint-status` |
|
||||
| pr-review | `/pr-review:pr-summary` |
|
||||
| clarity-assist | `/clarity-assist:clarify` |
|
||||
| doc-guardian | `/doc-guardian:doc-audit` |
|
||||
| code-sentinel | `/code-sentinel:security-scan` |
|
||||
| claude-config-maintainer | `/claude-config-maintainer:config-analyze` |
|
||||
| cmdb-assistant | `/cmdb-assistant:cmdb-search` |
|
||||
|
||||
## Repository Structure
|
||||
|
||||
```
|
||||
lm-claude-plugins/
|
||||
leo-claude-mktplace/
|
||||
├── .claude-plugin/ # Marketplace manifest
|
||||
│ └── marketplace.json
|
||||
├── mcp-servers/ # SHARED MCP servers (v3.0.0+)
|
||||
@@ -230,6 +254,8 @@ lm-claude-plugins/
|
||||
|----------|-------------|
|
||||
| [CLAUDE.md](./CLAUDE.md) | Main project instructions |
|
||||
| [CONFIGURATION.md](./docs/CONFIGURATION.md) | Centralized setup guide |
|
||||
| [COMMANDS-CHEATSHEET.md](./docs/COMMANDS-CHEATSHEET.md) | All commands quick reference |
|
||||
| [UPDATING.md](./docs/UPDATING.md) | Update guide for the marketplace |
|
||||
| [CANONICAL-PATHS.md](./docs/CANONICAL-PATHS.md) | Authoritative path reference |
|
||||
| [CHANGELOG.md](./CHANGELOG.md) | Version history |
|
||||
|
||||
@@ -240,4 +266,4 @@ MIT License
|
||||
## Support
|
||||
|
||||
- **Issues**: Contact repository maintainer
|
||||
- **Repository**: `https://gitea.hotserv.cloud/personal-projects/support-claude-mktplace.git`
|
||||
- **Repository**: `https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace.git`
|
||||
|
||||
@@ -9,7 +9,7 @@ Last Updated: 2026-01-20 (v3.0.0)
|
||||
## Repository Root Structure
|
||||
|
||||
```
|
||||
lm-claude-plugins/
|
||||
leo-claude-mktplace/
|
||||
├── .claude/ # Claude Code local settings
|
||||
├── .claude-plugin/ # Marketplace manifest
|
||||
│ └── marketplace.json
|
||||
@@ -18,6 +18,7 @@ lm-claude-plugins/
|
||||
│ ├── architecture/ # Draw.io diagrams and specs
|
||||
│ ├── CANONICAL-PATHS.md # This file - single source of truth
|
||||
│ ├── CONFIGURATION.md # Centralized configuration guide
|
||||
│ ├── DEBUGGING-CHECKLIST.md # Systematic troubleshooting guide
|
||||
│ ├── UPDATING.md # Update guide
|
||||
│ └── workflows/ # Workflow documentation
|
||||
├── hooks/ # Shared hooks (if any)
|
||||
@@ -103,6 +104,10 @@ lm-claude-plugins/
|
||||
│ ├── skills/
|
||||
│ └── claude-md-integration.md
|
||||
├── scripts/ # Setup and maintenance scripts
|
||||
│ ├── setup.sh # Initial setup (create venvs, config templates)
|
||||
│ ├── post-update.sh # Post-update (rebuild venvs, verify symlinks)
|
||||
│ ├── check-venv.sh # Check if venvs exist (for hooks)
|
||||
│ └── validate-marketplace.sh # Marketplace compliance validation
|
||||
├── CLAUDE.md
|
||||
├── README.md
|
||||
├── LICENSE
|
||||
@@ -155,6 +160,8 @@ The symlink target is relative: `../../../mcp-servers/{server}`
|
||||
| This file | `docs/CANONICAL-PATHS.md` |
|
||||
| Update guide | `docs/UPDATING.md` |
|
||||
| Configuration guide | `docs/CONFIGURATION.md` |
|
||||
| Commands cheat sheet | `docs/COMMANDS-CHEATSHEET.md` |
|
||||
| Debugging checklist | `docs/DEBUGGING-CHECKLIST.md` |
|
||||
|
||||
---
|
||||
|
||||
@@ -231,7 +238,7 @@ plugins/pr-review/mcp-servers/gitea -> ../../../mcp-servers/gitea
|
||||
| 2026-01-20 | v3.0.0: MCP servers moved to root with symlinks | Claude Code |
|
||||
| 2026-01-20 | v3.0.0: Added clarity-assist, git-flow, pr-review plugins | Claude Code |
|
||||
| 2026-01-20 | v3.0.0: Added docs/CONFIGURATION.md | Claude Code |
|
||||
| 2026-01-20 | v3.0.0: Renamed marketplace to lm-claude-plugins | Claude Code |
|
||||
| 2026-01-20 | v3.0.0: Renamed marketplace to leo-claude-mktplace | Claude Code |
|
||||
| 2026-01-20 | Removed docs/references/ (obsolete planning docs) | Claude Code |
|
||||
| 2026-01-19 | Added claude-md-integration.md path pattern | Claude Code |
|
||||
| 2025-12-15 | Restructured: MCP servers bundled in plugins | Claude Code |
|
||||
|
||||
217
docs/COMMANDS-CHEATSHEET.md
Normal file
217
docs/COMMANDS-CHEATSHEET.md
Normal file
@@ -0,0 +1,217 @@
|
||||
# Plugin Commands Cheat Sheet
|
||||
|
||||
Quick reference for all commands in the Leo Claude Marketplace.
|
||||
|
||||
---
|
||||
|
||||
## Command Reference Table
|
||||
|
||||
| Plugin | Command | Auto | Manual | Description |
|
||||
|--------|---------|:----:|:------:|-------------|
|
||||
| **projman** | `/sprint-plan` | | X | Start sprint planning with AI-guided architecture analysis and issue creation |
|
||||
| **projman** | `/sprint-start` | | X | Begin sprint execution with dependency analysis and parallel task coordination |
|
||||
| **projman** | `/sprint-status` | | X | Check current sprint progress and identify blockers |
|
||||
| **projman** | `/review` | | X | Pre-sprint-close code quality review (debug artifacts, security, error handling) |
|
||||
| **projman** | `/test-check` | | X | Run tests and verify coverage before sprint close |
|
||||
| **projman** | `/sprint-close` | | X | Complete sprint and capture lessons learned to Gitea Wiki |
|
||||
| **projman** | `/labels-sync` | | X | Synchronize label taxonomy from Gitea |
|
||||
| **projman** | `/initial-setup` | | X | Full setup wizard: MCP server + system config + project config |
|
||||
| **projman** | `/project-init` | | X | Quick project setup (assumes system config exists) |
|
||||
| **projman** | `/project-sync` | | X | Sync config with git remote after repo move/rename |
|
||||
| **projman** | *SessionStart hook* | X | | Detects git remote vs .env mismatch, warns to run /project-sync |
|
||||
| **projman** | `/test-gen` | | X | Generate comprehensive tests for specified code |
|
||||
| **projman** | `/debug-report` | | X | Run diagnostics and create structured issue in marketplace |
|
||||
| **projman** | `/debug-review` | | X | Investigate diagnostic issues and propose fixes with approval gates |
|
||||
| **git-flow** | `/commit` | | X | Create commit with auto-generated conventional message |
|
||||
| **git-flow** | `/commit-push` | | X | Commit and push to remote in one operation |
|
||||
| **git-flow** | `/commit-merge` | | X | Commit current changes, then merge into target branch |
|
||||
| **git-flow** | `/commit-sync` | | X | Full sync: commit, push, and sync with upstream/base branch |
|
||||
| **git-flow** | `/branch-start` | | X | Create new feature/fix/chore branch with naming conventions |
|
||||
| **git-flow** | `/branch-cleanup` | | X | Remove merged branches locally and optionally on remote |
|
||||
| **git-flow** | `/git-status` | | X | Enhanced git status with recommendations |
|
||||
| **git-flow** | `/git-config` | | X | Configure git-flow settings for the project |
|
||||
| **pr-review** | `/initial-setup` | | X | Setup wizard for pr-review (shares Gitea MCP with projman) |
|
||||
| **pr-review** | `/project-init` | | X | Quick project setup for PR reviews |
|
||||
| **pr-review** | `/project-sync` | | X | Sync config with git remote after repo move/rename |
|
||||
| **pr-review** | *SessionStart hook* | X | | Detects git remote vs .env mismatch |
|
||||
| **pr-review** | `/pr-review` | | X | Full multi-agent PR review with confidence scoring |
|
||||
| **pr-review** | `/pr-summary` | | X | Quick summary of PR changes |
|
||||
| **pr-review** | `/pr-findings` | | X | List and filter review findings by category/severity |
|
||||
| **clarity-assist** | `/clarify` | | X | Full 4-D prompt optimization with ND accommodations |
|
||||
| **clarity-assist** | `/quick-clarify` | | X | Rapid single-pass clarification for simple requests |
|
||||
| **doc-guardian** | `/doc-audit` | | X | Full documentation audit - scans for doc drift |
|
||||
| **doc-guardian** | `/doc-sync` | | X | Synchronize pending documentation updates |
|
||||
| **doc-guardian** | *PostToolUse hook* | X | | Silently detects doc drift on Write/Edit |
|
||||
| **code-sentinel** | `/security-scan` | | X | Full security audit (SQL injection, XSS, secrets, etc.) |
|
||||
| **code-sentinel** | `/refactor` | | X | Apply refactoring patterns to improve code |
|
||||
| **code-sentinel** | `/refactor-dry` | | X | Preview refactoring without applying changes |
|
||||
| **code-sentinel** | *PreToolUse hook* | X | | Scans code before writing; blocks critical issues |
|
||||
| **claude-config-maintainer** | `/config-analyze` | | X | Analyze CLAUDE.md for optimization opportunities |
|
||||
| **claude-config-maintainer** | `/config-optimize` | | X | Optimize CLAUDE.md structure with preview/backup |
|
||||
| **claude-config-maintainer** | `/config-init` | | X | Initialize new CLAUDE.md for a project |
|
||||
| **cmdb-assistant** | `/initial-setup` | | X | Setup wizard for NetBox MCP server |
|
||||
| **cmdb-assistant** | `/cmdb-search` | | X | Search NetBox for devices, IPs, sites |
|
||||
| **cmdb-assistant** | `/cmdb-device` | | X | Manage network devices (create, view, update, delete) |
|
||||
| **cmdb-assistant** | `/cmdb-ip` | | X | Manage IP addresses and prefixes |
|
||||
| **cmdb-assistant** | `/cmdb-site` | | X | Manage sites, locations, racks, and regions |
|
||||
| **project-hygiene** | *PostToolUse hook* | X | | Removes temp files, warns about unexpected root files |
|
||||
|
||||
---
|
||||
|
||||
## Plugins by Category
|
||||
|
||||
| Category | Plugins | Primary Use |
|
||||
|----------|---------|-------------|
|
||||
| **Setup** | projman, pr-review, cmdb-assistant | `/initial-setup`, `/project-init` |
|
||||
| **Task Planning** | projman, clarity-assist | Sprint management, requirement clarification |
|
||||
| **Code Quality** | code-sentinel, pr-review | Security scanning, PR reviews |
|
||||
| **Documentation** | doc-guardian, claude-config-maintainer | Doc sync, CLAUDE.md maintenance |
|
||||
| **Git Operations** | git-flow | Commits, branches, workflow automation |
|
||||
| **Infrastructure** | cmdb-assistant | NetBox CMDB management |
|
||||
| **Maintenance** | project-hygiene | Automatic cleanup |
|
||||
|
||||
---
|
||||
|
||||
## Hook-Based Automation Summary
|
||||
|
||||
| Plugin | Hook Event | Behavior |
|
||||
|--------|------------|----------|
|
||||
| **projman** | SessionStart | Checks git remote vs .env; warns if mismatch detected |
|
||||
| **pr-review** | SessionStart | Checks git remote vs .env; warns if mismatch detected |
|
||||
| **doc-guardian** | PostToolUse (Write/Edit) | Silently tracks documentation drift |
|
||||
| **code-sentinel** | PreToolUse (Write/Edit) | Scans for security issues; blocks critical vulnerabilities |
|
||||
| **project-hygiene** | PostToolUse (Write/Edit) | Cleans temp files, warns about misplaced files |
|
||||
|
||||
---
|
||||
|
||||
## Dev Workflow Examples
|
||||
|
||||
### Example 1: Starting a New Feature Sprint
|
||||
|
||||
A typical workflow for planning and executing a feature sprint:
|
||||
|
||||
```
|
||||
1. /clarify # Clarify requirements if vague
|
||||
2. /sprint-plan # Plan the sprint with architecture analysis
|
||||
3. /labels-sync # Ensure labels are up-to-date
|
||||
4. /sprint-start # Begin execution with dependency ordering
|
||||
5. /branch-start feat/... # Create feature branch
|
||||
... implement features ...
|
||||
6. /commit # Commit with conventional message
|
||||
7. /sprint-status # Check progress mid-sprint
|
||||
8. /review # Pre-close quality review
|
||||
9. /test-check # Verify test coverage
|
||||
10. /sprint-close # Capture lessons learned
|
||||
```
|
||||
|
||||
### Example 2: Daily Development Cycle
|
||||
|
||||
Quick daily workflow with git-flow:
|
||||
|
||||
```
|
||||
1. /git-status # Check current state
|
||||
2. /branch-start fix/... # Start bugfix branch
|
||||
... make changes ...
|
||||
3. /commit # Auto-generate commit message
|
||||
4. /commit-push # Push to remote
|
||||
5. /branch-cleanup # Clean merged branches
|
||||
```
|
||||
|
||||
### Example 3: Pull Request Review Workflow
|
||||
|
||||
Reviewing a PR before merge:
|
||||
|
||||
```
|
||||
1. /pr-summary # Quick overview of changes
|
||||
2. /pr-review # Full multi-agent review
|
||||
3. /pr-findings # Filter findings by severity
|
||||
4. /security-scan # Deep security audit if needed
|
||||
```
|
||||
|
||||
### Example 4: Documentation Maintenance
|
||||
|
||||
Keeping docs in sync:
|
||||
|
||||
```
|
||||
1. /doc-audit # Scan for documentation drift
|
||||
2. /doc-sync # Apply pending updates
|
||||
3. /config-analyze # Check CLAUDE.md health
|
||||
4. /config-optimize # Optimize if needed
|
||||
```
|
||||
|
||||
### Example 5: Code Refactoring Session
|
||||
|
||||
Safe refactoring with preview:
|
||||
|
||||
```
|
||||
1. /refactor-dry # Preview opportunities
|
||||
2. /security-scan # Baseline security check
|
||||
3. /refactor # Apply improvements
|
||||
4. /test-check # Verify nothing broke
|
||||
5. /commit # Commit with descriptive message
|
||||
```
|
||||
|
||||
### Example 6: Infrastructure Documentation
|
||||
|
||||
Managing infrastructure with CMDB:
|
||||
|
||||
```
|
||||
1. /cmdb-search "server" # Find existing devices
|
||||
2. /cmdb-device view X # Check device details
|
||||
3. /cmdb-ip list # List available IPs
|
||||
4. /cmdb-site view Y # Check site info
|
||||
```
|
||||
|
||||
### Example 7: First-Time Setup (New Machine)
|
||||
|
||||
Setting up the marketplace for the first time:
|
||||
|
||||
```
|
||||
1. /initial-setup # Full setup: MCP + system config + project
|
||||
# → Follow prompts for Gitea URL, org
|
||||
# → Add token manually when prompted
|
||||
# → Confirm repository name
|
||||
2. # Restart Claude Code session
|
||||
3. /labels-sync # Sync Gitea labels
|
||||
4. /sprint-plan # Plan first sprint
|
||||
```
|
||||
|
||||
### Example 8: New Project Setup (System Already Configured)
|
||||
|
||||
Adding a new project when system config exists:
|
||||
|
||||
```
|
||||
1. /project-init # Quick project setup
|
||||
# → Confirms detected repo name
|
||||
# → Creates .env
|
||||
2. /labels-sync # Sync Gitea labels
|
||||
3. /sprint-plan # Plan first sprint
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Quick Tips
|
||||
|
||||
- **Hooks run automatically** - doc-guardian and code-sentinel protect you without manual invocation
|
||||
- **Use `/commit` over `git commit`** - generates better commit messages following conventions
|
||||
- **Run `/review` before `/sprint-close`** - catches issues before closing the sprint
|
||||
- **Use `/clarify` for vague requests** - especially helpful for complex requirements
|
||||
- **`/refactor-dry` is safe** - always preview before applying refactoring changes
|
||||
|
||||
---
|
||||
|
||||
## MCP Server Requirements
|
||||
|
||||
Some plugins require MCP server connectivity:
|
||||
|
||||
| Plugin | MCP Server | Purpose |
|
||||
|--------|------------|---------|
|
||||
| projman | Gitea | Issues, PRs, wiki, labels, milestones |
|
||||
| pr-review | Gitea | PR operations and reviews |
|
||||
| cmdb-assistant | NetBox | Infrastructure CMDB |
|
||||
|
||||
Ensure credentials are configured in `~/.config/claude/gitea.env` or `~/.config/claude/netbox.env`.
|
||||
|
||||
---
|
||||
|
||||
*Last Updated: 2026-01-22*
|
||||
@@ -1,105 +1,341 @@
|
||||
# Configuration Guide
|
||||
|
||||
Centralized configuration documentation for all plugins and MCP servers in the lm-claude-plugins marketplace.
|
||||
Centralized configuration documentation for all plugins and MCP servers in the Leo Claude Marketplace.
|
||||
|
||||
## Overview
|
||||
---
|
||||
|
||||
## Quick Start
|
||||
|
||||
**After installing the marketplace and plugins via Claude Code:**
|
||||
|
||||
```
|
||||
/initial-setup
|
||||
```
|
||||
|
||||
The interactive wizard handles everything except manually adding your API tokens.
|
||||
|
||||
---
|
||||
|
||||
## Setup Flow Diagram
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||
│ FIRST TIME SETUP │
|
||||
│ (once per machine) │
|
||||
└─────────────────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
/initial-setup
|
||||
│
|
||||
┌──────────────────────────────┼──────────────────────────────┐
|
||||
▼ ▼ ▼
|
||||
┌─────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||
│ PHASE 1 │ │ PHASE 2 │ │ PHASE 3 │
|
||||
│ Automated │───────────▶│ Automated │───────────▶│ Interactive │
|
||||
│ │ │ │ │ │
|
||||
│ • Check │ │ • Find MCP path │ │ • Ask Gitea URL │
|
||||
│ Python │ │ • Create venv │ │ • Ask Org name │
|
||||
│ version │ │ • Install deps │ │ • Create config │
|
||||
└─────────────┘ └─────────────────┘ └─────────────────┘
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────┐
|
||||
│ PHASE 4 │
|
||||
│ USER ACTION │
|
||||
│ │
|
||||
│ Edit config file to add │
|
||||
│ API token (for security) │
|
||||
│ │
|
||||
│ nano ~/.config/claude/ │
|
||||
│ gitea.env │
|
||||
└───────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────────────────┬──────────────────────────────┐
|
||||
▼ ▼ ▼
|
||||
┌─────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||
│ PHASE 5 │ │ PHASE 6 │ │ PHASE 7 │
|
||||
│ Interactive │ │ Automated │ │ Automated │
|
||||
│ │ │ │ │ │
|
||||
│ • Confirm │ │ • Create .env │ │ • Test API │
|
||||
│ repo name │ │ • Check │ │ • Show summary │
|
||||
│ from git │ │ .gitignore │ │ • Restart note │
|
||||
└─────────────┘ └─────────────────┘ └─────────────────┘
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────┐
|
||||
│ RESTART SESSION │
|
||||
│ │
|
||||
│ MCP tools available │
|
||||
│ after restart │
|
||||
└───────────────────────────┘
|
||||
|
||||
|
||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||
│ NEW PROJECT SETUP │
|
||||
│ (once per project) │
|
||||
└─────────────────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
┌───────────────┴───────────────┐
|
||||
▼ ▼
|
||||
/project-init /initial-setup
|
||||
(direct path) (smart detection)
|
||||
│ │
|
||||
│ ┌──────────┴──────────┐
|
||||
│ ▼ ▼
|
||||
│ "Quick setup" "Full setup"
|
||||
│ (skips to (re-runs
|
||||
│ project config) everything)
|
||||
│ │ │
|
||||
└────────────────────┴─────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────┐
|
||||
│ PROJECT CONFIG │
|
||||
│ │
|
||||
│ • Detect repo from │
|
||||
│ git remote │
|
||||
│ • Confirm with user │
|
||||
│ • Create .env │
|
||||
│ • Check .gitignore │
|
||||
└─────────────────────┘
|
||||
│
|
||||
▼
|
||||
Done!
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## What Runs Automatically vs User Interaction
|
||||
|
||||
### `/initial-setup` - Full Setup
|
||||
|
||||
| Phase | Type | What Happens |
|
||||
|-------|------|--------------|
|
||||
| **1. Environment Check** | Automated | Verifies Python 3.10+ is installed |
|
||||
| **2. MCP Server Setup** | Automated | Finds plugin path, creates venv, installs dependencies |
|
||||
| **3. System Config Creation** | Interactive | Asks for Gitea URL and organization name |
|
||||
| **4. Token Entry** | **User Action** | User manually edits config file to add API token |
|
||||
| **5. Project Detection** | Interactive | Shows detected repo name, asks for confirmation |
|
||||
| **6. Project Config** | Automated | Creates `.env` file, checks `.gitignore` |
|
||||
| **7. Validation** | Automated | Tests API connectivity, shows summary |
|
||||
|
||||
### `/project-init` - Quick Project Setup
|
||||
|
||||
| Phase | Type | What Happens |
|
||||
|-------|------|--------------|
|
||||
| **1. Pre-flight Check** | Automated | Verifies system config exists |
|
||||
| **2. Project Detection** | Interactive | Shows detected repo name, asks for confirmation |
|
||||
| **3. Project Config** | Automated | Creates/updates `.env` file |
|
||||
| **4. Gitignore Check** | Interactive | Asks to add `.env` to `.gitignore` if missing |
|
||||
|
||||
---
|
||||
|
||||
## Three Commands for Different Scenarios
|
||||
|
||||
| Command | When to Use | What It Does |
|
||||
|---------|-------------|--------------|
|
||||
| `/initial-setup` | First time on a machine | Full setup: MCP server + system config + project config |
|
||||
| `/project-init` | Starting a new project | Quick setup: project config only (assumes system is ready) |
|
||||
| `/project-sync` | After repo move/rename | Updates .env to match current git remote |
|
||||
|
||||
**Typical workflow:**
|
||||
1. Install plugin → run `/initial-setup` (once per machine)
|
||||
2. Start new project → run `/project-init` (once per project)
|
||||
3. Repository moved? → run `/project-sync` (updates config)
|
||||
|
||||
**Smart features:**
|
||||
- `/initial-setup` detects existing system config and offers quick project setup
|
||||
- All commands validate org/repo via Gitea API before saving (auto-fills if verified)
|
||||
- SessionStart hook automatically detects git remote vs .env mismatches
|
||||
|
||||
---
|
||||
|
||||
## Configuration Architecture
|
||||
|
||||
This marketplace uses a **hybrid configuration** approach:
|
||||
- **System-level:** Credentials and service configuration (stored once per machine)
|
||||
- **Project-level:** Repository-specific settings (stored per project)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ SYSTEM-LEVEL (once per machine) │
|
||||
│ ~/.config/claude/ │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ gitea.env │ GITEA_API_URL, GITEA_API_TOKEN │
|
||||
│ netbox.env │ NETBOX_API_URL, NETBOX_API_TOKEN │
|
||||
│ git-flow.env │ GIT_WORKFLOW_STYLE, GIT_DEFAULT_BASE, etc. │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
│ Shared across all projects
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ PROJECT-LEVEL (once per project) │
|
||||
│ <project-root>/.env │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ GITEA_ORG │ Organization for this project │
|
||||
│ GITEA_REPO │ Repository name for this project │
|
||||
│ GIT_WORKFLOW_STYLE │ (optional) Override system default │
|
||||
│ PR_REVIEW_* │ (optional) PR review settings │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Benefits:**
|
||||
- Single token per service (update once, use everywhere)
|
||||
- Easy multi-project setup (just add `.env` per project)
|
||||
- Security (tokens never committed to git)
|
||||
- Project isolation (each project has its own scope)
|
||||
- Easy multi-project setup (just run `/project-init` in each project)
|
||||
- Security (tokens never committed to git, never typed into AI chat)
|
||||
- Project isolation (each project can override defaults)
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before configuring any plugin:
|
||||
Before running `/initial-setup`:
|
||||
|
||||
1. **Python 3.10+** installed
|
||||
```bash
|
||||
python3 --version # Should be 3.10.0 or higher
|
||||
```
|
||||
|
||||
2. **Git repository** initialized
|
||||
2. **Git repository** initialized (for project setup)
|
||||
```bash
|
||||
git status # Should show initialized repository
|
||||
```
|
||||
|
||||
3. **Claude Code** installed and working
|
||||
3. **Claude Code** installed and working with the marketplace
|
||||
|
||||
---
|
||||
|
||||
## System-Level Configuration
|
||||
## Setup Methods
|
||||
|
||||
Configuration files stored in `~/.config/claude/`:
|
||||
### Method 1: Interactive Wizard (Recommended)
|
||||
|
||||
Run the setup wizard in Claude Code:
|
||||
|
||||
```
|
||||
/initial-setup
|
||||
```
|
||||
|
||||
The wizard will guide you through each step interactively.
|
||||
|
||||
**Note:** After first-time setup, you'll need to restart your Claude Code session for MCP tools to become available.
|
||||
|
||||
### Method 2: Manual Setup
|
||||
|
||||
If you prefer to set up manually or need to troubleshoot:
|
||||
|
||||
#### Step 1: MCP Server Setup
|
||||
|
||||
```bash
|
||||
# Navigate to marketplace directory
|
||||
cd /path/to/leo-claude-mktplace
|
||||
|
||||
# Set up Gitea MCP server
|
||||
cd mcp-servers/gitea
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
deactivate
|
||||
|
||||
# (Optional) Set up NetBox MCP server
|
||||
cd ../netbox
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
deactivate
|
||||
```
|
||||
|
||||
#### Step 2: System Configuration
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.config/claude
|
||||
```
|
||||
|
||||
### Gitea Configuration
|
||||
|
||||
Required by: `projman`, `pr-review`
|
||||
|
||||
```bash
|
||||
# Gitea configuration (credentials only)
|
||||
cat > ~/.config/claude/gitea.env << 'EOF'
|
||||
# Gitea API Configuration
|
||||
GITEA_URL=https://gitea.example.com
|
||||
GITEA_TOKEN=your_gitea_token_here
|
||||
GITEA_ORG=your_organization
|
||||
GITEA_API_URL=https://gitea.example.com
|
||||
GITEA_API_TOKEN=your_token_here
|
||||
EOF
|
||||
|
||||
# Secure the file
|
||||
chmod 600 ~/.config/claude/gitea.env
|
||||
```
|
||||
|
||||
**Variables:**
|
||||
#### Step 3: Project Configuration
|
||||
|
||||
In each project root:
|
||||
|
||||
```bash
|
||||
cat > .env << 'EOF'
|
||||
GITEA_ORG=your-organization
|
||||
GITEA_REPO=your-repo-name
|
||||
EOF
|
||||
```
|
||||
|
||||
Add `.env` to `.gitignore` if not already there.
|
||||
|
||||
### Method 3: Automation Script (CI/Scripting)
|
||||
|
||||
For automated setups or CI environments:
|
||||
|
||||
```bash
|
||||
cd /path/to/leo-claude-mktplace
|
||||
./scripts/setup.sh
|
||||
```
|
||||
|
||||
This script is useful for CI/CD pipelines and bulk provisioning.
|
||||
|
||||
---
|
||||
|
||||
## Configuration Reference
|
||||
|
||||
### System-Level Files
|
||||
|
||||
Located in `~/.config/claude/`:
|
||||
|
||||
| File | Required By | Purpose |
|
||||
|------|-------------|---------|
|
||||
| `gitea.env` | projman, pr-review | Gitea API credentials |
|
||||
| `netbox.env` | cmdb-assistant | NetBox API credentials |
|
||||
| `git-flow.env` | git-flow | Default git workflow settings |
|
||||
|
||||
### Gitea Configuration
|
||||
|
||||
```bash
|
||||
# ~/.config/claude/gitea.env
|
||||
GITEA_API_URL=https://gitea.example.com/api/v1
|
||||
GITEA_API_TOKEN=your_gitea_token_here
|
||||
```
|
||||
|
||||
| Variable | Description | Example |
|
||||
|----------|-------------|---------|
|
||||
| `GITEA_URL` | Gitea base URL (no `/api/v1`) | `https://gitea.example.com` |
|
||||
| `GITEA_TOKEN` | Personal access token | `glpat-xxx...` |
|
||||
| `GITEA_ORG` | Organization name | `bandit` |
|
||||
| `GITEA_API_URL` | Gitea API endpoint (with `/api/v1`) | `https://gitea.example.com/api/v1` |
|
||||
| `GITEA_API_TOKEN` | Personal access token | `abc123...` |
|
||||
|
||||
**Generating Gitea Token:**
|
||||
**Note:** `GITEA_ORG` is configured at the project level (see below) since different projects may belong to different organizations.
|
||||
|
||||
**Generating a Gitea Token:**
|
||||
1. Log into Gitea → **User Icon** → **Settings**
|
||||
2. **Applications** tab → **Manage Access Tokens**
|
||||
3. **Generate New Token** with permissions:
|
||||
- `repo` (all sub-permissions)
|
||||
- `read:org`
|
||||
- `read:user`
|
||||
- `write:repo` (for wiki)
|
||||
- `write:repo` (for wiki access)
|
||||
4. Copy token immediately (shown only once)
|
||||
|
||||
### NetBox Configuration
|
||||
|
||||
Required by: `cmdb-assistant`
|
||||
|
||||
```bash
|
||||
cat > ~/.config/claude/netbox.env << 'EOF'
|
||||
# NetBox API Configuration
|
||||
NETBOX_URL=https://netbox.example.com
|
||||
NETBOX_TOKEN=your_netbox_token_here
|
||||
EOF
|
||||
|
||||
chmod 600 ~/.config/claude/netbox.env
|
||||
# ~/.config/claude/netbox.env
|
||||
NETBOX_API_URL=https://netbox.example.com
|
||||
NETBOX_API_TOKEN=your_netbox_token_here
|
||||
```
|
||||
|
||||
**Variables:**
|
||||
| Variable | Description | Example |
|
||||
|----------|-------------|---------|
|
||||
| `NETBOX_URL` | NetBox base URL | `https://netbox.example.com` |
|
||||
| `NETBOX_TOKEN` | API token | `abc123...` |
|
||||
| `NETBOX_API_URL` | NetBox base URL | `https://netbox.example.com` |
|
||||
| `NETBOX_API_TOKEN` | API token | `abc123...` |
|
||||
|
||||
### Git-Flow Configuration
|
||||
|
||||
Optional system defaults for: `git-flow`
|
||||
|
||||
```bash
|
||||
cat > ~/.config/claude/git-flow.env << 'EOF'
|
||||
# Git-Flow Default Configuration
|
||||
# ~/.config/claude/git-flow.env
|
||||
GIT_WORKFLOW_STYLE=feature-branch
|
||||
GIT_DEFAULT_BASE=development
|
||||
GIT_AUTO_DELETE_MERGED=true
|
||||
@@ -107,170 +343,110 @@ GIT_AUTO_PUSH=false
|
||||
GIT_PROTECTED_BRANCHES=main,master,development,staging,production
|
||||
GIT_COMMIT_STYLE=conventional
|
||||
GIT_CO_AUTHOR=true
|
||||
EOF
|
||||
```
|
||||
|
||||
| Variable | Default | Description |
|
||||
|----------|---------|-------------|
|
||||
| `GIT_WORKFLOW_STYLE` | `feature-branch` | Branching strategy |
|
||||
| `GIT_DEFAULT_BASE` | `development` | Default base branch |
|
||||
| `GIT_AUTO_DELETE_MERGED` | `true` | Delete merged branches |
|
||||
| `GIT_AUTO_PUSH` | `false` | Auto-push after commit |
|
||||
| `GIT_PROTECTED_BRANCHES` | `main,master,...` | Protected branches |
|
||||
| `GIT_COMMIT_STYLE` | `conventional` | Commit message style |
|
||||
| `GIT_CO_AUTHOR` | `true` | Include Claude co-author |
|
||||
|
||||
---
|
||||
|
||||
## Project-Level Configuration
|
||||
|
||||
Create `.env` in each project root:
|
||||
|
||||
### Gitea Repository (projman, pr-review)
|
||||
|
||||
```bash
|
||||
# .env in project root
|
||||
# Required for projman, pr-review
|
||||
GITEA_ORG=your-organization
|
||||
GITEA_REPO=your-repo-name
|
||||
```
|
||||
|
||||
### Git-Flow (project overrides)
|
||||
|
||||
```bash
|
||||
# .env in project root
|
||||
# Optional: Override git-flow defaults
|
||||
GIT_WORKFLOW_STYLE=pr-required
|
||||
GIT_DEFAULT_BASE=main
|
||||
```
|
||||
|
||||
### PR Review
|
||||
|
||||
```bash
|
||||
# .env in project root
|
||||
# Optional: PR review settings
|
||||
PR_REVIEW_CONFIDENCE_THRESHOLD=0.5
|
||||
PR_REVIEW_AUTO_SUBMIT=false
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## MCP Server Installation
|
||||
|
||||
MCP servers are located at repository root: `mcp-servers/`
|
||||
|
||||
### Gitea MCP Server
|
||||
|
||||
```bash
|
||||
cd mcp-servers/gitea
|
||||
|
||||
# Create virtual environment
|
||||
python3 -m venv .venv
|
||||
|
||||
# Activate
|
||||
source .venv/bin/activate
|
||||
|
||||
# Install dependencies
|
||||
pip install -r requirements.txt
|
||||
|
||||
# Verify
|
||||
python -c "from mcp_server import server; print('OK')"
|
||||
|
||||
deactivate
|
||||
```
|
||||
|
||||
### NetBox MCP Server
|
||||
|
||||
```bash
|
||||
cd mcp-servers/netbox
|
||||
|
||||
# Create virtual environment
|
||||
python3 -m venv .venv
|
||||
|
||||
# Activate
|
||||
source .venv/bin/activate
|
||||
|
||||
# Install dependencies
|
||||
pip install -r requirements.txt
|
||||
|
||||
# Verify
|
||||
python -c "from mcp_server import server; print('OK')"
|
||||
|
||||
deactivate
|
||||
```
|
||||
| Variable | Required | Description |
|
||||
|----------|----------|-------------|
|
||||
| `GITEA_ORG` | Yes | Gitea organization for this project |
|
||||
| `GITEA_REPO` | Yes | Repository name (must match Gitea exactly) |
|
||||
| `GIT_WORKFLOW_STYLE` | No | Override system default |
|
||||
| `PR_REVIEW_*` | No | PR review settings |
|
||||
|
||||
---
|
||||
|
||||
## Plugin Configuration Reference
|
||||
## Plugin Configuration Summary
|
||||
|
||||
### projman
|
||||
|
||||
| Level | Variable | Default | Description |
|
||||
|-------|----------|---------|-------------|
|
||||
| System | `GITEA_URL` | (required) | Gitea API base URL |
|
||||
| System | `GITEA_TOKEN` | (required) | API token |
|
||||
| System | `GITEA_ORG` | (required) | Organization name |
|
||||
| Project | `GITEA_REPO` | (required) | Repository name |
|
||||
|
||||
**Commands:** `/sprint-plan`, `/sprint-start`, `/sprint-status`, `/sprint-close`, `/labels-sync`, `/initial-setup`, `/review`, `/test-check`, `/test-gen`
|
||||
|
||||
### pr-review
|
||||
|
||||
| Level | Variable | Default | Description |
|
||||
|-------|----------|---------|-------------|
|
||||
| System | `GITEA_URL` | (required) | Gitea API base URL |
|
||||
| System | `GITEA_TOKEN` | (required) | API token |
|
||||
| Project | `GITEA_REPO` | (required) | Repository name |
|
||||
| Project | `PR_REVIEW_CONFIDENCE_THRESHOLD` | `0.5` | Minimum confidence |
|
||||
| Project | `PR_REVIEW_AUTO_SUBMIT` | `false` | Auto-submit reviews |
|
||||
|
||||
**Commands:** `/pr-review`, `/pr-summary`, `/pr-findings`
|
||||
|
||||
### git-flow
|
||||
|
||||
| Level | Variable | Default | Description |
|
||||
|-------|----------|---------|-------------|
|
||||
| System/Project | `GIT_WORKFLOW_STYLE` | `feature-branch` | Branching strategy |
|
||||
| System/Project | `GIT_DEFAULT_BASE` | `development` | Default base branch |
|
||||
| System/Project | `GIT_AUTO_DELETE_MERGED` | `true` | Delete merged branches |
|
||||
| System/Project | `GIT_AUTO_PUSH` | `false` | Auto-push after commit |
|
||||
| System/Project | `GIT_PROTECTED_BRANCHES` | `main,master,...` | Protected branches |
|
||||
| System/Project | `GIT_COMMIT_STYLE` | `conventional` | Commit message style |
|
||||
| System/Project | `GIT_CO_AUTHOR` | `true` | Include Claude co-author |
|
||||
|
||||
**Commands:** `/commit`, `/commit-push`, `/commit-merge`, `/commit-sync`, `/branch-start`, `/branch-cleanup`, `/git-status`, `/git-config`
|
||||
|
||||
### clarity-assist
|
||||
|
||||
No configuration required. Uses sensible defaults.
|
||||
|
||||
**Commands:** `/clarify`, `/quick-clarify`
|
||||
|
||||
### cmdb-assistant
|
||||
|
||||
| Level | Variable | Default | Description |
|
||||
|-------|----------|---------|-------------|
|
||||
| System | `NETBOX_URL` | (required) | NetBox API base URL |
|
||||
| System | `NETBOX_TOKEN` | (required) | API token |
|
||||
|
||||
### doc-guardian
|
||||
|
||||
No configuration required. Hook-based plugin.
|
||||
|
||||
### code-sentinel
|
||||
|
||||
No configuration required. Hook-based plugin.
|
||||
|
||||
### project-hygiene
|
||||
|
||||
No configuration required. Hook-based plugin.
|
||||
|
||||
### claude-config-maintainer
|
||||
|
||||
No configuration required.
|
||||
| Plugin | System Config | Project Config | Setup Commands |
|
||||
|--------|---------------|----------------|----------------|
|
||||
| **projman** | gitea.env | .env (GITEA_ORG, GITEA_REPO) | `/initial-setup`, `/project-init`, `/project-sync` |
|
||||
| **pr-review** | gitea.env | .env (GITEA_ORG, GITEA_REPO) | `/initial-setup`, `/project-init`, `/project-sync` |
|
||||
| **git-flow** | git-flow.env (optional) | .env (optional) | None needed |
|
||||
| **clarity-assist** | None | None | None needed |
|
||||
| **cmdb-assistant** | netbox.env | None | `/initial-setup` |
|
||||
| **doc-guardian** | None | None | None needed |
|
||||
| **code-sentinel** | None | None | None needed |
|
||||
| **project-hygiene** | None | None | None needed |
|
||||
| **claude-config-maintainer** | None | None | None needed |
|
||||
|
||||
---
|
||||
|
||||
## Multi-Project Setup
|
||||
## Multi-Project Workflow
|
||||
|
||||
1. **System config:** Set up once (credentials)
|
||||
2. **Project config:** Create `.env` in each project root
|
||||
Once system-level config is set up, adding new projects is simple:
|
||||
|
||||
**Example:**
|
||||
```bash
|
||||
# ~/projects/my-app/.env
|
||||
GITEA_REPO=my-app
|
||||
|
||||
# ~/projects/another-app/.env
|
||||
GITEA_REPO=another-app
|
||||
GIT_WORKFLOW_STYLE=trunk-based
|
||||
**Option 1: Use `/project-init` (faster)**
|
||||
```
|
||||
cd ~/projects/new-project
|
||||
/project-init
|
||||
```
|
||||
|
||||
**Option 2: Use `/initial-setup` (auto-detects)**
|
||||
```
|
||||
cd ~/projects/new-project
|
||||
/initial-setup
|
||||
# → Detects system config exists
|
||||
# → Offers "Quick project setup" option
|
||||
```
|
||||
|
||||
Both approaches work. Use `/project-init` when you know the system is already configured.
|
||||
|
||||
---
|
||||
|
||||
## Automatic Validation Features
|
||||
|
||||
### API Validation
|
||||
|
||||
When running `/initial-setup`, `/project-init`, or `/project-sync`, the commands:
|
||||
|
||||
1. **Detect** organization and repository from git remote URL
|
||||
2. **Validate** via Gitea API: `GET /api/v1/repos/{org}/{repo}`
|
||||
3. **Auto-fill** if repository exists and is accessible (no confirmation needed)
|
||||
4. **Ask for confirmation** only if validation fails (404 or permission error)
|
||||
|
||||
This catches typos and permission issues before saving configuration.
|
||||
|
||||
### Mismatch Detection (SessionStart Hook)
|
||||
|
||||
When you start a Claude Code session, a hook automatically:
|
||||
|
||||
1. Reads `GITEA_ORG` and `GITEA_REPO` from `.env`
|
||||
2. Compares with current `git remote get-url origin`
|
||||
3. **Warns** if mismatch detected: "Repository location mismatch. Run `/project-sync` to update."
|
||||
|
||||
This helps when you:
|
||||
- Move a repository to a different organization
|
||||
- Rename a repository
|
||||
- Clone a repo but forget to update `.env`
|
||||
|
||||
---
|
||||
|
||||
@@ -279,31 +455,29 @@ GIT_WORKFLOW_STYLE=trunk-based
|
||||
### Test Gitea Connection
|
||||
|
||||
```bash
|
||||
curl -H "Authorization: token YOUR_TOKEN" \
|
||||
https://gitea.example.com/api/v1/user
|
||||
source ~/.config/claude/gitea.env
|
||||
curl -H "Authorization: token $GITEA_API_TOKEN" "$GITEA_API_URL/user"
|
||||
```
|
||||
|
||||
### Test MCP Server
|
||||
### Verify Project Setup
|
||||
|
||||
```bash
|
||||
cd mcp-servers/gitea
|
||||
source .venv/bin/activate
|
||||
python -c "from mcp_server import server; print('OK')"
|
||||
In Claude Code, after restarting your session:
|
||||
```
|
||||
|
||||
### Run Plugin Setup
|
||||
|
||||
```bash
|
||||
# For projman
|
||||
/initial-setup
|
||||
/labels-sync
|
||||
```
|
||||
|
||||
If this works, your setup is complete.
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Configuration not found
|
||||
### MCP tools not available
|
||||
|
||||
**Cause:** Session wasn't restarted after setup.
|
||||
**Solution:** Exit Claude Code and start a new session.
|
||||
|
||||
### "Configuration not found" error
|
||||
|
||||
```bash
|
||||
# Check system config exists
|
||||
@@ -317,23 +491,25 @@ stat ~/.config/claude/gitea.env
|
||||
|
||||
```bash
|
||||
# Test token directly
|
||||
curl -H "Authorization: token YOUR_TOKEN" \
|
||||
https://gitea.example.com/api/v1/user
|
||||
|
||||
# Regenerate if invalid
|
||||
source ~/.config/claude/gitea.env
|
||||
curl -H "Authorization: token $GITEA_API_TOKEN" "$GITEA_API_URL/user"
|
||||
```
|
||||
|
||||
### MCP server not starting
|
||||
If you get 401, regenerate your token in Gitea.
|
||||
|
||||
### MCP server won't start
|
||||
|
||||
```bash
|
||||
# Check venv exists
|
||||
ls mcp-servers/gitea/.venv
|
||||
ls /path/to/mcp-servers/gitea/.venv
|
||||
|
||||
# Reinstall if missing
|
||||
cd mcp-servers/gitea
|
||||
cd /path/to/mcp-servers/gitea
|
||||
rm -rf .venv
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
deactivate
|
||||
```
|
||||
|
||||
### Wrong repository
|
||||
@@ -342,7 +518,7 @@ pip install -r requirements.txt
|
||||
# Check project .env
|
||||
cat .env
|
||||
|
||||
# Verify GITEA_REPO matches exactly
|
||||
# Verify GITEA_REPO matches the Gitea repository name exactly
|
||||
```
|
||||
|
||||
---
|
||||
@@ -358,23 +534,14 @@ cat .env
|
||||
chmod 600 ~/.config/claude/*.env
|
||||
```
|
||||
|
||||
3. **Rotate tokens periodically**
|
||||
3. **Never type tokens into AI chat**
|
||||
- Always edit config files directly in your editor
|
||||
- The `/initial-setup` wizard respects this
|
||||
|
||||
4. **Rotate tokens periodically**
|
||||
- Every 6-12 months
|
||||
- Immediately if compromised
|
||||
|
||||
4. **Minimum permissions**
|
||||
5. **Minimum permissions**
|
||||
- Only grant required token permissions
|
||||
- Use separate tokens for different environments
|
||||
|
||||
---
|
||||
|
||||
## Quick Setup Checklist
|
||||
|
||||
- [ ] Python 3.10+ installed
|
||||
- [ ] `~/.config/claude/` directory created
|
||||
- [ ] Service credentials configured (gitea.env, netbox.env)
|
||||
- [ ] Configuration files secured (chmod 600)
|
||||
- [ ] MCP servers installed with venv
|
||||
- [ ] Project `.env` created with repository settings
|
||||
- [ ] Connections tested
|
||||
- [ ] Plugin commands verified
|
||||
|
||||
213
docs/DEBUGGING-CHECKLIST.md
Normal file
213
docs/DEBUGGING-CHECKLIST.md
Normal file
@@ -0,0 +1,213 @@
|
||||
# Debugging Checklist for Marketplace Troubleshooting
|
||||
|
||||
**Purpose:** Systematic approach to diagnose and fix plugin loading issues.
|
||||
|
||||
Last Updated: 2026-01-22
|
||||
|
||||
---
|
||||
|
||||
## Step 1: Identify the Loading Path
|
||||
|
||||
Claude Code loads plugins from different locations depending on context:
|
||||
|
||||
| Location | Path | When Used |
|
||||
|----------|------|-----------|
|
||||
| **Source** | `~/claude-plugins-work/` | When developing in this directory |
|
||||
| **Installed** | `~/.claude/plugins/marketplaces/leo-claude-mktplace/` | After marketplace install |
|
||||
| **Cache** | `~/.claude/` | Plugin metadata, settings |
|
||||
|
||||
**Determine which path Claude is using:**
|
||||
|
||||
```bash
|
||||
# Check if installed marketplace exists
|
||||
ls -la ~/.claude/plugins/marketplaces/leo-claude-mktplace/
|
||||
|
||||
# Check Claude's current plugin loading
|
||||
cat ~/.claude/settings.local.json | grep -A5 "mcpServers"
|
||||
```
|
||||
|
||||
**Key insight:** If you're editing source but Claude uses installed, your changes won't take effect.
|
||||
|
||||
---
|
||||
|
||||
## Step 2: Verify Files Exist at Runtime Location
|
||||
|
||||
Check the files Claude will actually load:
|
||||
|
||||
```bash
|
||||
# For installed marketplace
|
||||
RUNTIME=~/.claude/plugins/marketplaces/leo-claude-mktplace
|
||||
|
||||
# Check MCP server exists
|
||||
ls -la $RUNTIME/mcp-servers/gitea/
|
||||
ls -la $RUNTIME/mcp-servers/netbox/
|
||||
|
||||
# Check plugin manifests
|
||||
ls -la $RUNTIME/plugins/projman/.claude-plugin/plugin.json
|
||||
ls -la $RUNTIME/plugins/pr-review/.claude-plugin/plugin.json
|
||||
|
||||
# Check .mcp.json files
|
||||
cat $RUNTIME/plugins/projman/.mcp.json
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 3: Verify Virtual Environments Exist
|
||||
|
||||
**This is the most common failure point after installation.**
|
||||
|
||||
MCP servers require Python venvs to exist at the INSTALLED location:
|
||||
|
||||
```bash
|
||||
RUNTIME=~/.claude/plugins/marketplaces/leo-claude-mktplace
|
||||
|
||||
# Check venvs exist
|
||||
ls -la $RUNTIME/mcp-servers/gitea/.venv/bin/python
|
||||
ls -la $RUNTIME/mcp-servers/netbox/.venv/bin/python
|
||||
|
||||
# If missing, create them:
|
||||
cd $RUNTIME && ./scripts/setup.sh
|
||||
```
|
||||
|
||||
**Common error:** "X MCP servers failed to start" = venvs don't exist in installed path.
|
||||
|
||||
---
|
||||
|
||||
## Step 4: Verify Symlink Resolution
|
||||
|
||||
Plugins use symlinks to shared MCP servers. Verify they resolve correctly:
|
||||
|
||||
```bash
|
||||
RUNTIME=~/.claude/plugins/marketplaces/leo-claude-mktplace
|
||||
|
||||
# Check symlinks exist and resolve
|
||||
readlink -f $RUNTIME/plugins/projman/mcp-servers/gitea
|
||||
readlink -f $RUNTIME/plugins/pr-review/mcp-servers/gitea
|
||||
readlink -f $RUNTIME/plugins/cmdb-assistant/mcp-servers/netbox
|
||||
|
||||
# Should resolve to:
|
||||
# $RUNTIME/mcp-servers/gitea
|
||||
# $RUNTIME/mcp-servers/netbox
|
||||
```
|
||||
|
||||
**If broken:** Symlinks are relative. If directory structure differs, they'll break.
|
||||
|
||||
---
|
||||
|
||||
## Step 5: Test MCP Server Startup
|
||||
|
||||
Manually test if the MCP server can start:
|
||||
|
||||
```bash
|
||||
RUNTIME=~/.claude/plugins/marketplaces/leo-claude-mktplace
|
||||
|
||||
# Test Gitea MCP
|
||||
cd $RUNTIME/mcp-servers/gitea
|
||||
PYTHONPATH=. .venv/bin/python -c "from mcp_server.server import main; print('OK')"
|
||||
|
||||
# Test NetBox MCP
|
||||
cd $RUNTIME/mcp-servers/netbox
|
||||
PYTHONPATH=. .venv/bin/python -c "from mcp_server.server import main; print('OK')"
|
||||
```
|
||||
|
||||
**If import fails:** Check requirements.txt installed, check Python version compatibility.
|
||||
|
||||
---
|
||||
|
||||
## Step 6: Verify Configuration Files
|
||||
|
||||
Check environment variables are set:
|
||||
|
||||
```bash
|
||||
# System-level credentials (should exist)
|
||||
cat ~/.config/claude/gitea.env
|
||||
# Should contain: GITEA_API_URL, GITEA_API_TOKEN
|
||||
|
||||
cat ~/.config/claude/netbox.env
|
||||
# Should contain: NETBOX_API_URL, NETBOX_API_TOKEN
|
||||
|
||||
# Project-level config (in target project)
|
||||
cat /path/to/project/.env
|
||||
# Should contain: GITEA_ORG, GITEA_REPO
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 7: Verify Hooks Configuration
|
||||
|
||||
Check hooks are valid:
|
||||
|
||||
```bash
|
||||
RUNTIME=~/.claude/plugins/marketplaces/leo-claude-mktplace
|
||||
|
||||
# List all hooks.json files
|
||||
find $RUNTIME/plugins -name "hooks.json" -exec echo "=== {} ===" \; -exec cat {} \;
|
||||
|
||||
# Verify hook events are valid
|
||||
# Valid: PreToolUse, PostToolUse, UserPromptSubmit, SessionStart, SessionEnd,
|
||||
# Notification, Stop, SubagentStop, PreCompact
|
||||
# INVALID: task-completed, file-changed, git-commit-msg-needed
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Quick Diagnostic Commands
|
||||
|
||||
Run these to quickly identify issues:
|
||||
|
||||
```bash
|
||||
RUNTIME=~/.claude/plugins/marketplaces/leo-claude-mktplace
|
||||
|
||||
echo "=== Installation Status ==="
|
||||
[ -d "$RUNTIME" ] && echo "Installed: YES" || echo "Installed: NO"
|
||||
|
||||
echo -e "\n=== Virtual Environments ==="
|
||||
[ -f "$RUNTIME/mcp-servers/gitea/.venv/bin/python" ] && echo "Gitea venv: OK" || echo "Gitea venv: MISSING"
|
||||
[ -f "$RUNTIME/mcp-servers/netbox/.venv/bin/python" ] && echo "NetBox venv: OK" || echo "NetBox venv: MISSING"
|
||||
|
||||
echo -e "\n=== Symlinks ==="
|
||||
[ -L "$RUNTIME/plugins/projman/mcp-servers/gitea" ] && echo "projman->gitea: OK" || echo "projman->gitea: MISSING"
|
||||
[ -L "$RUNTIME/plugins/pr-review/mcp-servers/gitea" ] && echo "pr-review->gitea: OK" || echo "pr-review->gitea: MISSING"
|
||||
[ -L "$RUNTIME/plugins/cmdb-assistant/mcp-servers/netbox" ] && echo "cmdb-assistant->netbox: OK" || echo "cmdb-assistant->netbox: MISSING"
|
||||
|
||||
echo -e "\n=== Config Files ==="
|
||||
[ -f ~/.config/claude/gitea.env ] && echo "gitea.env: OK" || echo "gitea.env: MISSING"
|
||||
[ -f ~/.config/claude/netbox.env ] && echo "netbox.env: OK" || echo "netbox.env: MISSING"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Common Issues and Fixes
|
||||
|
||||
| Issue | Symptom | Fix |
|
||||
|-------|---------|-----|
|
||||
| Missing venvs | "X MCP servers failed" | `cd ~/.claude/plugins/marketplaces/leo-claude-mktplace && ./scripts/setup.sh` |
|
||||
| Broken symlinks | MCP tools not available | Reinstall marketplace or manually recreate symlinks |
|
||||
| Wrong path edits | Changes don't take effect | Edit installed path or reinstall after source changes |
|
||||
| Missing credentials | MCP connection errors | Create `~/.config/claude/gitea.env` with API credentials |
|
||||
| Invalid hook events | Hooks don't fire | Use only valid event names (see Step 7) |
|
||||
|
||||
---
|
||||
|
||||
## After Fixing Issues
|
||||
|
||||
1. **Restart Claude Code** - Plugins are loaded at startup
|
||||
2. **Verify fix works** - Run a simple command that uses the MCP
|
||||
3. **Document the issue** - If it's a new failure mode, add to this checklist
|
||||
|
||||
---
|
||||
|
||||
## Automated Diagnostics
|
||||
|
||||
Use these commands for automated checking:
|
||||
|
||||
- `/debug-report` - Run full diagnostics, create issue if problems found
|
||||
- `/debug-review` - Investigate existing diagnostic issues and propose fixes
|
||||
|
||||
---
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- `CLAUDE.md` - Installation Paths and Troubleshooting sections
|
||||
- `docs/CONFIGURATION.md` - Setup and configuration guide
|
||||
- `docs/UPDATING.md` - Update procedures
|
||||
169
docs/UPDATING.md
169
docs/UPDATING.md
@@ -1,24 +1,71 @@
|
||||
# Updating support-claude-mktplace
|
||||
# Updating Leo Claude Marketplace
|
||||
|
||||
This guide covers how to update your local installation when new versions are released.
|
||||
|
||||
## Quick Update
|
||||
---
|
||||
|
||||
## ⚠️ CRITICAL: Run Setup in Installed Location
|
||||
|
||||
When Claude Code installs a marketplace, it copies files to `~/.claude/plugins/marketplaces/` but **does NOT create Python virtual environments**. You must run setup manually after installation or update.
|
||||
|
||||
**After installing or updating the marketplace:**
|
||||
|
||||
```bash
|
||||
# 1. Pull latest changes
|
||||
cd /path/to/support-claude-mktplace
|
||||
cd ~/.claude/plugins/marketplaces/leo-claude-mktplace && ./scripts/setup.sh
|
||||
```
|
||||
|
||||
This creates the required `.venv` directories for MCP servers. Without this step, **all MCP servers will fail to start**.
|
||||
|
||||
---
|
||||
|
||||
## Quick Update (Source Repository)
|
||||
|
||||
```bash
|
||||
# 1. Pull latest changes to source
|
||||
cd /path/to/leo-claude-mktplace
|
||||
git pull origin main
|
||||
|
||||
# 2. Run post-update script
|
||||
# 2. Run post-update script (updates source repo venvs)
|
||||
./scripts/post-update.sh
|
||||
|
||||
# 3. CRITICAL: Run setup in installed marketplace location
|
||||
cd ~/.claude/plugins/marketplaces/leo-claude-mktplace && ./scripts/setup.sh
|
||||
```
|
||||
|
||||
**Then restart your Claude Code session** to load any changes.
|
||||
|
||||
---
|
||||
|
||||
## What the Post-Update Script Does
|
||||
|
||||
1. **Updates Python dependencies** for MCP servers
|
||||
1. **Updates Python dependencies** for MCP servers (gitea, netbox)
|
||||
2. **Shows recent changelog entries** so you know what changed
|
||||
3. **Validates your configuration** is still compatible
|
||||
|
||||
---
|
||||
|
||||
## After Updating: Re-run Setup if Needed
|
||||
|
||||
### When to Re-run `/initial-setup`
|
||||
|
||||
You typically **don't need** to re-run setup after updates. However, re-run if:
|
||||
|
||||
- Changelog mentions **new required environment variables**
|
||||
- Changelog mentions **breaking changes** to configuration
|
||||
- MCP tools stop working after update
|
||||
|
||||
### For Existing Projects
|
||||
|
||||
If an update requires new project-level configuration:
|
||||
|
||||
```
|
||||
/project-init
|
||||
```
|
||||
|
||||
This will detect existing settings and only add what's missing.
|
||||
|
||||
---
|
||||
|
||||
## Manual Steps After Update
|
||||
|
||||
Some updates may require manual configuration changes:
|
||||
@@ -29,7 +76,7 @@ If the changelog mentions new environment variables:
|
||||
|
||||
1. Check the variable name and purpose in the changelog
|
||||
2. Add it to the appropriate config file:
|
||||
- Gitea variables → `~/.config/claude/gitea.env`
|
||||
- System variables → `~/.config/claude/gitea.env` or `netbox.env`
|
||||
- Project variables → `.env` in your project root
|
||||
|
||||
### New MCP Server Features
|
||||
@@ -37,20 +84,56 @@ If the changelog mentions new environment variables:
|
||||
If a new MCP server tool is added:
|
||||
|
||||
1. The post-update script handles dependency installation
|
||||
2. Check `plugins/projman/README.md` for usage documentation
|
||||
3. New tools are available immediately after update
|
||||
2. Check plugin documentation for usage
|
||||
3. New tools are available immediately after session restart
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
Breaking changes will be clearly marked in CHANGELOG.md with migration instructions.
|
||||
|
||||
## Troubleshooting
|
||||
### Setup Script and Configuration Workflow Changes
|
||||
|
||||
When updating, review if changes affect the setup workflow:
|
||||
|
||||
1. **Check for setup command changes:**
|
||||
```bash
|
||||
git diff HEAD~1 plugins/*/commands/initial-setup.md
|
||||
git diff HEAD~1 plugins/*/commands/project-init.md
|
||||
git diff HEAD~1 plugins/*/commands/project-sync.md
|
||||
```
|
||||
|
||||
2. **Check for hook changes:**
|
||||
```bash
|
||||
git diff HEAD~1 plugins/*/hooks/hooks.json
|
||||
```
|
||||
|
||||
3. **Check for configuration structure changes:**
|
||||
```bash
|
||||
git diff HEAD~1 docs/CONFIGURATION.md
|
||||
```
|
||||
|
||||
**If setup commands changed:**
|
||||
- Review what's new (new validation steps, new prompts, etc.)
|
||||
- Consider re-running `/initial-setup` or `/project-init` to benefit from improvements
|
||||
- Existing configurations remain valid unless changelog notes breaking changes
|
||||
|
||||
**If hooks changed:**
|
||||
- Restart your Claude Code session to load new hooks
|
||||
- New hooks (like SessionStart validation) activate automatically
|
||||
|
||||
**If configuration structure changed:**
|
||||
- Check if new variables are required
|
||||
- Run `/project-sync` if repository detection logic improved
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting Updates
|
||||
|
||||
### Dependencies fail to install
|
||||
|
||||
```bash
|
||||
# Rebuild virtual environment
|
||||
cd plugins/projman/mcp-servers/gitea
|
||||
cd mcp-servers/gitea
|
||||
rm -rf .venv
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
@@ -61,14 +144,47 @@ deactivate
|
||||
### Configuration no longer works
|
||||
|
||||
1. Check CHANGELOG.md for breaking changes
|
||||
2. Compare your config files with updated `.env.example` (if provided)
|
||||
3. Run `./scripts/setup.sh` to validate configuration
|
||||
2. Run `/initial-setup` to re-validate and fix configuration
|
||||
3. Compare your config files with documentation in `docs/CONFIGURATION.md`
|
||||
|
||||
### MCP server won't start
|
||||
### MCP server won't start after update
|
||||
|
||||
**Most common cause:** Virtual environments don't exist in the installed marketplace.
|
||||
|
||||
```bash
|
||||
# Fix: Run setup in installed location
|
||||
cd ~/.claude/plugins/marketplaces/leo-claude-mktplace && ./scripts/setup.sh
|
||||
```
|
||||
|
||||
If that doesn't work:
|
||||
|
||||
1. Check Python version: `python3 --version` (requires 3.10+)
|
||||
2. Verify venv exists: `ls plugins/projman/mcp-servers/gitea/.venv`
|
||||
3. Check logs for specific errors
|
||||
2. Verify venv exists in INSTALLED location:
|
||||
```bash
|
||||
ls ~/.claude/plugins/marketplaces/leo-claude-mktplace/mcp-servers/gitea/.venv
|
||||
ls ~/.claude/plugins/marketplaces/leo-claude-mktplace/mcp-servers/netbox/.venv
|
||||
```
|
||||
3. If missing, the symlinks won't resolve. Run setup.sh as shown above.
|
||||
4. Restart Claude Code session
|
||||
5. Check logs for specific errors
|
||||
|
||||
### "X MCP servers failed" on startup
|
||||
|
||||
This almost always means the venvs don't exist in the installed marketplace:
|
||||
|
||||
```bash
|
||||
cd ~/.claude/plugins/marketplaces/leo-claude-mktplace && ./scripts/setup.sh
|
||||
```
|
||||
|
||||
Then restart Claude Code.
|
||||
|
||||
### New commands not available
|
||||
|
||||
1. Restart your Claude Code session
|
||||
2. Verify the plugin is still installed
|
||||
3. Check if the command requires additional setup
|
||||
|
||||
---
|
||||
|
||||
## Version Pinning
|
||||
|
||||
@@ -79,15 +195,28 @@ To stay on a specific version:
|
||||
git tag
|
||||
|
||||
# Checkout specific version
|
||||
git checkout v2.2.0
|
||||
git checkout v3.0.0
|
||||
|
||||
# Run post-update
|
||||
./scripts/post-update.sh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Checking Current Version
|
||||
|
||||
The version is displayed in the main README.md title and in `CHANGELOG.md`.
|
||||
|
||||
```bash
|
||||
# Check version from changelog
|
||||
head -20 CHANGELOG.md
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Getting Help
|
||||
|
||||
- Check `plugins/projman/README.md` for projman documentation
|
||||
- Check `plugins/projman/CONFIGURATION.md` for setup guide
|
||||
- Review CHANGELOG.md for recent changes
|
||||
- Check `docs/CONFIGURATION.md` for setup guide
|
||||
- Check `docs/COMMANDS-CHEATSHEET.md` for command reference
|
||||
- Review `CHANGELOG.md` for recent changes
|
||||
- Search existing issues in Gitea
|
||||
|
||||
@@ -389,7 +389,7 @@ def list_issues(self, state='open', labels=None, repo=None):
|
||||
|
||||
## License
|
||||
|
||||
MIT License - Part of the Claude Code Marketplace project.
|
||||
MIT License - Part of the Leo Claude Marketplace project.
|
||||
|
||||
## Related Documentation
|
||||
|
||||
@@ -406,7 +406,7 @@ For issues or questions:
|
||||
|
||||
---
|
||||
|
||||
**Built for**: Claude Code Marketplace - Project Management Plugins
|
||||
**Built for**: Leo Claude Marketplace - Project Management Plugins
|
||||
**Phase**: 1 (Complete)
|
||||
**Status**: ✅ Production Ready
|
||||
**Last Updated**: 2025-01-06
|
||||
|
||||
@@ -4,10 +4,13 @@ Configuration loader for Gitea MCP Server.
|
||||
Implements hybrid configuration system:
|
||||
- System-level: ~/.config/claude/gitea.env (credentials)
|
||||
- Project-level: .env (repository specification)
|
||||
- Auto-detection: Falls back to git remote URL parsing
|
||||
"""
|
||||
from pathlib import Path
|
||||
from dotenv import load_dotenv
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import logging
|
||||
from typing import Dict, Optional
|
||||
|
||||
@@ -48,8 +51,12 @@ class GiteaConfig:
|
||||
"cat > ~/.config/claude/gitea.env"
|
||||
)
|
||||
|
||||
# Find project directory (MCP server cwd is plugin dir, not project dir)
|
||||
project_dir = self._find_project_directory()
|
||||
|
||||
# Load project config (overrides system)
|
||||
project_config = Path.cwd() / '.env'
|
||||
if project_dir:
|
||||
project_config = project_dir / '.env'
|
||||
if project_config.exists():
|
||||
load_dotenv(project_config, override=True)
|
||||
logger.info(f"Loaded project configuration from {project_config}")
|
||||
@@ -59,6 +66,12 @@ class GiteaConfig:
|
||||
self.api_token = os.getenv('GITEA_API_TOKEN')
|
||||
self.repo = os.getenv('GITEA_REPO') # Optional, must be owner/repo format
|
||||
|
||||
# Auto-detect repo from git remote if not specified
|
||||
if not self.repo and project_dir:
|
||||
self.repo = self._detect_repo_from_git(project_dir)
|
||||
if self.repo:
|
||||
logger.info(f"Auto-detected repository from git remote: {self.repo}")
|
||||
|
||||
# Detect mode
|
||||
if self.repo:
|
||||
self.mode = 'project'
|
||||
@@ -96,3 +109,119 @@ class GiteaConfig:
|
||||
f"Missing required configuration: {', '.join(missing)}\n"
|
||||
"Check your ~/.config/claude/gitea.env file"
|
||||
)
|
||||
|
||||
def _find_project_directory(self) -> Optional[Path]:
|
||||
"""
|
||||
Find the user's project directory.
|
||||
|
||||
The MCP server runs with cwd set to the plugin directory, not the
|
||||
user's project. We need to find the actual project directory using
|
||||
various heuristics.
|
||||
|
||||
Returns:
|
||||
Path to project directory, or None if not found
|
||||
"""
|
||||
# Strategy 1: Check CLAUDE_PROJECT_DIR environment variable
|
||||
project_dir = os.getenv('CLAUDE_PROJECT_DIR')
|
||||
if project_dir:
|
||||
path = Path(project_dir)
|
||||
if path.exists():
|
||||
logger.info(f"Found project directory from CLAUDE_PROJECT_DIR: {path}")
|
||||
return path
|
||||
|
||||
# Strategy 2: Check PWD (original working directory before cwd override)
|
||||
pwd = os.getenv('PWD')
|
||||
if pwd:
|
||||
path = Path(pwd)
|
||||
# Verify it has .git or .env (indicates a project)
|
||||
if path.exists() and ((path / '.git').exists() or (path / '.env').exists()):
|
||||
logger.info(f"Found project directory from PWD: {path}")
|
||||
return path
|
||||
|
||||
# Strategy 3: Check current working directory
|
||||
# This handles test scenarios and cases where cwd is actually the project
|
||||
cwd = Path.cwd()
|
||||
if (cwd / '.git').exists() or (cwd / '.env').exists():
|
||||
logger.info(f"Found project directory from cwd: {cwd}")
|
||||
return cwd
|
||||
|
||||
# Strategy 4: Check if GITEA_REPO is already set (user configured it)
|
||||
# If so, we don't need to find the project directory for git detection
|
||||
if os.getenv('GITEA_REPO'):
|
||||
logger.debug("GITEA_REPO already set, skipping project directory detection")
|
||||
return None
|
||||
|
||||
logger.debug("Could not determine project directory")
|
||||
return None
|
||||
|
||||
def _detect_repo_from_git(self, project_dir: Optional[Path] = None) -> Optional[str]:
|
||||
"""
|
||||
Auto-detect repository from git remote origin URL.
|
||||
|
||||
Args:
|
||||
project_dir: Directory to run git command from (defaults to cwd)
|
||||
|
||||
Supports URL formats:
|
||||
- SSH: ssh://git@host:port/owner/repo.git
|
||||
- SSH short: git@host:owner/repo.git
|
||||
- HTTPS: https://host/owner/repo.git
|
||||
- HTTP: http://host/owner/repo.git
|
||||
|
||||
Returns:
|
||||
Repository in 'owner/repo' format, or None if detection fails
|
||||
"""
|
||||
try:
|
||||
result = subprocess.run(
|
||||
['git', 'remote', 'get-url', 'origin'],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=5,
|
||||
cwd=str(project_dir) if project_dir else None
|
||||
)
|
||||
if result.returncode != 0:
|
||||
logger.debug("No git remote 'origin' found")
|
||||
return None
|
||||
|
||||
url = result.stdout.strip()
|
||||
return self._parse_git_url(url)
|
||||
|
||||
except subprocess.TimeoutExpired:
|
||||
logger.warning("Git command timed out")
|
||||
return None
|
||||
except FileNotFoundError:
|
||||
logger.debug("Git not available")
|
||||
return None
|
||||
except Exception as e:
|
||||
logger.debug(f"Failed to detect repo from git: {e}")
|
||||
return None
|
||||
|
||||
def _parse_git_url(self, url: str) -> Optional[str]:
|
||||
"""
|
||||
Parse git URL to extract owner/repo.
|
||||
|
||||
Args:
|
||||
url: Git remote URL
|
||||
|
||||
Returns:
|
||||
Repository in 'owner/repo' format, or None if parsing fails
|
||||
"""
|
||||
# Remove .git suffix if present
|
||||
url = re.sub(r'\.git$', '', url)
|
||||
|
||||
# SSH format: ssh://git@host:port/owner/repo
|
||||
ssh_match = re.match(r'ssh://[^/]+/(.+/.+)$', url)
|
||||
if ssh_match:
|
||||
return ssh_match.group(1)
|
||||
|
||||
# SSH short format: git@host:owner/repo
|
||||
ssh_short_match = re.match(r'git@[^:]+:(.+/.+)$', url)
|
||||
if ssh_short_match:
|
||||
return ssh_short_match.group(1)
|
||||
|
||||
# HTTPS/HTTP format: https://host/owner/repo
|
||||
http_match = re.match(r'https?://[^/]+/(.+/.+)$', url)
|
||||
if http_match:
|
||||
return http_match.group(1)
|
||||
|
||||
logger.warning(f"Could not parse git URL: {url}")
|
||||
return None
|
||||
|
||||
@@ -110,8 +110,14 @@ class GiteaClient:
|
||||
|
||||
def _resolve_label_ids(self, label_names: List[str], owner: str, repo: str) -> List[int]:
|
||||
"""Convert label names to label IDs."""
|
||||
full_repo = f"{owner}/{repo}"
|
||||
|
||||
# Only fetch org labels if repo belongs to an organization
|
||||
org_labels = []
|
||||
if self.is_org_repo(full_repo):
|
||||
org_labels = self.get_org_labels(owner)
|
||||
repo_labels = self.get_labels(f"{owner}/{repo}")
|
||||
|
||||
repo_labels = self.get_labels(full_repo)
|
||||
all_labels = org_labels + repo_labels
|
||||
label_map = {label['name']: label['id'] for label in all_labels}
|
||||
label_ids = []
|
||||
@@ -548,10 +554,33 @@ class GiteaClient:
|
||||
return response.json()
|
||||
|
||||
def is_org_repo(self, repo: Optional[str] = None) -> bool:
|
||||
"""Check if repository belongs to an organization (not a user)."""
|
||||
info = self.get_repo_info(repo)
|
||||
owner_type = info.get('owner', {}).get('type', '')
|
||||
return owner_type.lower() == 'organization'
|
||||
"""
|
||||
Check if repository belongs to an organization (not a user).
|
||||
|
||||
Uses the /orgs/{owner} endpoint to reliably detect organizations,
|
||||
as the owner.type field in repo info may be null in some Gitea versions.
|
||||
"""
|
||||
owner, _ = self._parse_repo(repo)
|
||||
return self._is_organization(owner)
|
||||
|
||||
def _is_organization(self, owner: str) -> bool:
|
||||
"""
|
||||
Check if an owner is an organization by querying the orgs endpoint.
|
||||
|
||||
Args:
|
||||
owner: The owner name to check
|
||||
|
||||
Returns:
|
||||
True if owner is an organization, False if user or unknown
|
||||
"""
|
||||
url = f"{self.base_url}/orgs/{owner}"
|
||||
try:
|
||||
response = self.session.get(url)
|
||||
# 200 = organization exists, 404 = not an organization (user account)
|
||||
return response.status_code == 200
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to check if {owner} is organization: {e}")
|
||||
return False
|
||||
|
||||
def get_branch_protection(
|
||||
self,
|
||||
|
||||
@@ -220,6 +220,10 @@ class GiteaMCPServer:
|
||||
"context": {
|
||||
"type": "string",
|
||||
"description": "Issue title + description or sprint context"
|
||||
},
|
||||
"repo": {
|
||||
"type": "string",
|
||||
"description": "Repository name (owner/repo format)"
|
||||
}
|
||||
},
|
||||
"required": ["context"]
|
||||
|
||||
@@ -8,6 +8,7 @@ Provides async wrappers for label operations with:
|
||||
"""
|
||||
import asyncio
|
||||
import logging
|
||||
import re
|
||||
from typing import List, Dict, Optional
|
||||
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
@@ -27,15 +28,22 @@ class LabelTools:
|
||||
self.gitea = gitea_client
|
||||
|
||||
async def get_labels(self, repo: Optional[str] = None) -> Dict[str, List[Dict]]:
|
||||
"""Get all labels (org + repo). Repo must be 'owner/repo' format."""
|
||||
"""Get all labels (org + repo if org-owned, repo-only if user-owned)."""
|
||||
loop = asyncio.get_event_loop()
|
||||
|
||||
target_repo = repo or self.gitea.repo
|
||||
if not target_repo or '/' not in target_repo:
|
||||
raise ValueError("Use 'owner/repo' format (e.g. 'org/repo-name')")
|
||||
|
||||
org = target_repo.split('/')[0]
|
||||
# Check if repo belongs to an organization or user
|
||||
is_org = await loop.run_in_executor(
|
||||
None,
|
||||
lambda: self.gitea.is_org_repo(target_repo)
|
||||
)
|
||||
|
||||
org_labels = []
|
||||
if is_org:
|
||||
org = target_repo.split('/')[0]
|
||||
org_labels = await loop.run_in_executor(
|
||||
None,
|
||||
lambda: self.gitea.get_org_labels(org)
|
||||
@@ -52,107 +60,202 @@ class LabelTools:
|
||||
'total_count': len(org_labels) + len(repo_labels)
|
||||
}
|
||||
|
||||
async def suggest_labels(self, context: str) -> List[str]:
|
||||
async def suggest_labels(self, context: str, repo: Optional[str] = None) -> List[str]:
|
||||
"""
|
||||
Analyze context and suggest appropriate labels.
|
||||
Analyze context and suggest appropriate labels from repository's actual labels.
|
||||
|
||||
This method fetches actual labels from the repository and matches them
|
||||
dynamically, supporting any label naming convention (slash, colon-space, etc.).
|
||||
|
||||
Args:
|
||||
context: Issue title + description or sprint context
|
||||
repo: Repository in 'owner/repo' format (optional, uses default if not provided)
|
||||
|
||||
Returns:
|
||||
List of suggested label names
|
||||
List of suggested label names that exist in the repository
|
||||
"""
|
||||
# Fetch actual labels from repository
|
||||
target_repo = repo or self.gitea.repo
|
||||
if not target_repo:
|
||||
logger.warning("No repository specified, returning empty suggestions")
|
||||
return []
|
||||
|
||||
try:
|
||||
labels_data = await self.get_labels(target_repo)
|
||||
all_labels = labels_data.get('organization', []) + labels_data.get('repository', [])
|
||||
label_names = [label['name'] for label in all_labels]
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to fetch labels: {e}. Using fallback suggestions.")
|
||||
label_names = []
|
||||
|
||||
# Build label lookup for dynamic matching
|
||||
label_lookup = self._build_label_lookup(label_names)
|
||||
|
||||
suggested = []
|
||||
context_lower = context.lower()
|
||||
|
||||
# Type detection (exclusive - only one)
|
||||
type_label = None
|
||||
if any(word in context_lower for word in ['bug', 'error', 'fix', 'broken', 'crash', 'fail']):
|
||||
suggested.append('Type/Bug')
|
||||
type_label = self._find_label(label_lookup, 'type', 'bug')
|
||||
elif any(word in context_lower for word in ['refactor', 'extract', 'restructure', 'architecture', 'service extraction']):
|
||||
suggested.append('Type/Refactor')
|
||||
type_label = self._find_label(label_lookup, 'type', 'refactor')
|
||||
elif any(word in context_lower for word in ['feature', 'add', 'implement', 'new', 'create']):
|
||||
suggested.append('Type/Feature')
|
||||
type_label = self._find_label(label_lookup, 'type', 'feature')
|
||||
elif any(word in context_lower for word in ['docs', 'documentation', 'readme', 'guide']):
|
||||
suggested.append('Type/Documentation')
|
||||
type_label = self._find_label(label_lookup, 'type', 'documentation')
|
||||
elif any(word in context_lower for word in ['test', 'testing', 'spec', 'coverage']):
|
||||
suggested.append('Type/Test')
|
||||
type_label = self._find_label(label_lookup, 'type', 'test')
|
||||
elif any(word in context_lower for word in ['chore', 'maintenance', 'update', 'upgrade']):
|
||||
suggested.append('Type/Chore')
|
||||
type_label = self._find_label(label_lookup, 'type', 'chore')
|
||||
if type_label:
|
||||
suggested.append(type_label)
|
||||
|
||||
# Priority detection
|
||||
priority_label = None
|
||||
if any(word in context_lower for word in ['critical', 'urgent', 'blocker', 'blocking', 'emergency']):
|
||||
suggested.append('Priority/Critical')
|
||||
priority_label = self._find_label(label_lookup, 'priority', 'critical')
|
||||
elif any(word in context_lower for word in ['high', 'important', 'asap', 'soon']):
|
||||
suggested.append('Priority/High')
|
||||
priority_label = self._find_label(label_lookup, 'priority', 'high')
|
||||
elif any(word in context_lower for word in ['low', 'nice-to-have', 'optional', 'later']):
|
||||
suggested.append('Priority/Low')
|
||||
priority_label = self._find_label(label_lookup, 'priority', 'low')
|
||||
else:
|
||||
suggested.append('Priority/Medium')
|
||||
priority_label = self._find_label(label_lookup, 'priority', 'medium')
|
||||
if priority_label:
|
||||
suggested.append(priority_label)
|
||||
|
||||
# Complexity detection
|
||||
complexity_label = None
|
||||
if any(word in context_lower for word in ['simple', 'trivial', 'easy', 'quick']):
|
||||
suggested.append('Complexity/Simple')
|
||||
complexity_label = self._find_label(label_lookup, 'complexity', 'simple')
|
||||
elif any(word in context_lower for word in ['complex', 'difficult', 'challenging', 'intricate']):
|
||||
suggested.append('Complexity/Complex')
|
||||
complexity_label = self._find_label(label_lookup, 'complexity', 'complex')
|
||||
else:
|
||||
suggested.append('Complexity/Medium')
|
||||
complexity_label = self._find_label(label_lookup, 'complexity', 'medium')
|
||||
if complexity_label:
|
||||
suggested.append(complexity_label)
|
||||
|
||||
# Efforts detection
|
||||
# Effort detection (supports both "Effort" and "Efforts" naming)
|
||||
effort_label = None
|
||||
if any(word in context_lower for word in ['xs', 'tiny', '1 hour', '2 hours']):
|
||||
suggested.append('Efforts/XS')
|
||||
effort_label = self._find_label(label_lookup, 'effort', 'xs')
|
||||
elif any(word in context_lower for word in ['small', 's ', '1 day', 'half day']):
|
||||
suggested.append('Efforts/S')
|
||||
effort_label = self._find_label(label_lookup, 'effort', 's')
|
||||
elif any(word in context_lower for word in ['medium', 'm ', '2 days', '3 days']):
|
||||
suggested.append('Efforts/M')
|
||||
effort_label = self._find_label(label_lookup, 'effort', 'm')
|
||||
elif any(word in context_lower for word in ['large', 'l ', '1 week', '5 days']):
|
||||
suggested.append('Efforts/L')
|
||||
effort_label = self._find_label(label_lookup, 'effort', 'l')
|
||||
elif any(word in context_lower for word in ['xl', 'extra large', '2 weeks', 'sprint']):
|
||||
suggested.append('Efforts/XL')
|
||||
effort_label = self._find_label(label_lookup, 'effort', 'xl')
|
||||
if effort_label:
|
||||
suggested.append(effort_label)
|
||||
|
||||
# Component detection (based on keywords)
|
||||
component_keywords = {
|
||||
'Component/Backend': ['backend', 'server', 'api', 'database', 'service'],
|
||||
'Component/Frontend': ['frontend', 'ui', 'interface', 'react', 'vue', 'component'],
|
||||
'Component/API': ['api', 'endpoint', 'rest', 'graphql', 'route'],
|
||||
'Component/Database': ['database', 'db', 'sql', 'migration', 'schema', 'postgres'],
|
||||
'Component/Auth': ['auth', 'authentication', 'login', 'oauth', 'token', 'session'],
|
||||
'Component/Deploy': ['deploy', 'deployment', 'docker', 'kubernetes', 'ci/cd'],
|
||||
'Component/Testing': ['test', 'testing', 'spec', 'jest', 'pytest', 'coverage'],
|
||||
'Component/Docs': ['docs', 'documentation', 'readme', 'guide', 'wiki']
|
||||
component_mappings = {
|
||||
'backend': ['backend', 'server', 'api', 'database', 'service'],
|
||||
'frontend': ['frontend', 'ui', 'interface', 'react', 'vue', 'component'],
|
||||
'api': ['api', 'endpoint', 'rest', 'graphql', 'route'],
|
||||
'database': ['database', 'db', 'sql', 'migration', 'schema', 'postgres'],
|
||||
'auth': ['auth', 'authentication', 'login', 'oauth', 'token', 'session'],
|
||||
'deploy': ['deploy', 'deployment', 'docker', 'kubernetes', 'ci/cd'],
|
||||
'testing': ['test', 'testing', 'spec', 'jest', 'pytest', 'coverage'],
|
||||
'docs': ['docs', 'documentation', 'readme', 'guide', 'wiki']
|
||||
}
|
||||
|
||||
for label, keywords in component_keywords.items():
|
||||
for component, keywords in component_mappings.items():
|
||||
if any(keyword in context_lower for keyword in keywords):
|
||||
label = self._find_label(label_lookup, 'component', component)
|
||||
if label and label not in suggested:
|
||||
suggested.append(label)
|
||||
|
||||
# Tech stack detection
|
||||
tech_keywords = {
|
||||
'Tech/Python': ['python', 'fastapi', 'django', 'flask', 'pytest'],
|
||||
'Tech/JavaScript': ['javascript', 'js', 'node', 'npm', 'yarn'],
|
||||
'Tech/Docker': ['docker', 'dockerfile', 'container', 'compose'],
|
||||
'Tech/PostgreSQL': ['postgres', 'postgresql', 'psql', 'sql'],
|
||||
'Tech/Redis': ['redis', 'cache', 'session store'],
|
||||
'Tech/Vue': ['vue', 'vuejs', 'nuxt'],
|
||||
'Tech/FastAPI': ['fastapi', 'pydantic', 'starlette']
|
||||
tech_mappings = {
|
||||
'python': ['python', 'fastapi', 'django', 'flask', 'pytest'],
|
||||
'javascript': ['javascript', 'js', 'node', 'npm', 'yarn'],
|
||||
'docker': ['docker', 'dockerfile', 'container', 'compose'],
|
||||
'postgresql': ['postgres', 'postgresql', 'psql', 'sql'],
|
||||
'redis': ['redis', 'cache', 'session store'],
|
||||
'vue': ['vue', 'vuejs', 'nuxt'],
|
||||
'fastapi': ['fastapi', 'pydantic', 'starlette']
|
||||
}
|
||||
|
||||
for label, keywords in tech_keywords.items():
|
||||
for tech, keywords in tech_mappings.items():
|
||||
if any(keyword in context_lower for keyword in keywords):
|
||||
label = self._find_label(label_lookup, 'tech', tech)
|
||||
if label and label not in suggested:
|
||||
suggested.append(label)
|
||||
|
||||
# Source detection (based on git branch or context)
|
||||
source_label = None
|
||||
if 'development' in context_lower or 'dev/' in context_lower:
|
||||
suggested.append('Source/Development')
|
||||
source_label = self._find_label(label_lookup, 'source', 'development')
|
||||
elif 'staging' in context_lower or 'stage/' in context_lower:
|
||||
suggested.append('Source/Staging')
|
||||
source_label = self._find_label(label_lookup, 'source', 'staging')
|
||||
elif 'production' in context_lower or 'prod' in context_lower:
|
||||
suggested.append('Source/Production')
|
||||
source_label = self._find_label(label_lookup, 'source', 'production')
|
||||
if source_label:
|
||||
suggested.append(source_label)
|
||||
|
||||
# Risk detection
|
||||
risk_label = None
|
||||
if any(word in context_lower for word in ['breaking', 'breaking change', 'major', 'risky']):
|
||||
suggested.append('Risk/High')
|
||||
risk_label = self._find_label(label_lookup, 'risk', 'high')
|
||||
elif any(word in context_lower for word in ['safe', 'low risk', 'minor']):
|
||||
suggested.append('Risk/Low')
|
||||
risk_label = self._find_label(label_lookup, 'risk', 'low')
|
||||
if risk_label:
|
||||
suggested.append(risk_label)
|
||||
|
||||
logger.info(f"Suggested {len(suggested)} labels based on context")
|
||||
logger.info(f"Suggested {len(suggested)} labels based on context and {len(label_names)} available labels")
|
||||
return suggested
|
||||
|
||||
def _build_label_lookup(self, label_names: List[str]) -> Dict[str, Dict[str, str]]:
|
||||
"""
|
||||
Build a lookup dictionary for label matching.
|
||||
|
||||
Supports various label formats:
|
||||
- Slash format: Type/Bug, Priority/High
|
||||
- Colon-space format: Type: Bug, Priority: High
|
||||
- Colon format: Type:Bug
|
||||
|
||||
Args:
|
||||
label_names: List of actual label names from repository
|
||||
|
||||
Returns:
|
||||
Nested dict: {category: {value: actual_label_name}}
|
||||
"""
|
||||
lookup: Dict[str, Dict[str, str]] = {}
|
||||
|
||||
for label in label_names:
|
||||
# Try different separator patterns
|
||||
# Pattern: Category<separator>Value
|
||||
# Separators: /, : , :
|
||||
match = re.match(r'^([^/:]+)(?:/|:\s*|:)(.+)$', label)
|
||||
if match:
|
||||
category = match.group(1).lower().rstrip('s') # Normalize: "Efforts" -> "effort"
|
||||
value = match.group(2).lower()
|
||||
|
||||
if category not in lookup:
|
||||
lookup[category] = {}
|
||||
lookup[category][value] = label
|
||||
|
||||
return lookup
|
||||
|
||||
def _find_label(self, lookup: Dict[str, Dict[str, str]], category: str, value: str) -> Optional[str]:
|
||||
"""
|
||||
Find actual label name from lookup.
|
||||
|
||||
Args:
|
||||
lookup: Label lookup dictionary
|
||||
category: Category to search (e.g., 'type', 'priority')
|
||||
value: Value to find (e.g., 'bug', 'high')
|
||||
|
||||
Returns:
|
||||
Actual label name if found, None otherwise
|
||||
"""
|
||||
category_lower = category.lower().rstrip('s') # Normalize
|
||||
value_lower = value.lower()
|
||||
|
||||
if category_lower in lookup and value_lower in lookup[category_lower]:
|
||||
return lookup[category_lower][value_lower]
|
||||
|
||||
return None
|
||||
|
||||
@@ -149,3 +149,112 @@ def test_mode_detection_company(tmp_path, monkeypatch):
|
||||
|
||||
assert result['mode'] == 'company'
|
||||
assert result['repo'] is None
|
||||
|
||||
|
||||
# ========================================
|
||||
# GIT URL PARSING TESTS
|
||||
# ========================================
|
||||
|
||||
def test_parse_git_url_ssh_format():
|
||||
"""Test parsing SSH format git URL"""
|
||||
config = GiteaConfig()
|
||||
|
||||
# SSH with port: ssh://git@host:port/owner/repo.git
|
||||
url = "ssh://git@hotserv.tailc9b278.ts.net:2222/personal-projects/personal-portfolio.git"
|
||||
result = config._parse_git_url(url)
|
||||
assert result == "personal-projects/personal-portfolio"
|
||||
|
||||
|
||||
def test_parse_git_url_ssh_short_format():
|
||||
"""Test parsing SSH short format git URL"""
|
||||
config = GiteaConfig()
|
||||
|
||||
# SSH short: git@host:owner/repo.git
|
||||
url = "git@github.com:owner/repo.git"
|
||||
result = config._parse_git_url(url)
|
||||
assert result == "owner/repo"
|
||||
|
||||
|
||||
def test_parse_git_url_https_format():
|
||||
"""Test parsing HTTPS format git URL"""
|
||||
config = GiteaConfig()
|
||||
|
||||
# HTTPS: https://host/owner/repo.git
|
||||
url = "https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace.git"
|
||||
result = config._parse_git_url(url)
|
||||
assert result == "personal-projects/leo-claude-mktplace"
|
||||
|
||||
|
||||
def test_parse_git_url_http_format():
|
||||
"""Test parsing HTTP format git URL"""
|
||||
config = GiteaConfig()
|
||||
|
||||
# HTTP: http://host/owner/repo.git
|
||||
url = "http://gitea.hotserv.cloud/personal-projects/repo.git"
|
||||
result = config._parse_git_url(url)
|
||||
assert result == "personal-projects/repo"
|
||||
|
||||
|
||||
def test_parse_git_url_without_git_suffix():
|
||||
"""Test parsing git URL without .git suffix"""
|
||||
config = GiteaConfig()
|
||||
|
||||
url = "https://github.com/owner/repo"
|
||||
result = config._parse_git_url(url)
|
||||
assert result == "owner/repo"
|
||||
|
||||
|
||||
def test_parse_git_url_invalid_format():
|
||||
"""Test parsing invalid git URL returns None"""
|
||||
config = GiteaConfig()
|
||||
|
||||
url = "not-a-valid-url"
|
||||
result = config._parse_git_url(url)
|
||||
assert result is None
|
||||
|
||||
|
||||
def test_find_project_directory_from_env(tmp_path, monkeypatch):
|
||||
"""Test finding project directory from CLAUDE_PROJECT_DIR env var"""
|
||||
project_dir = tmp_path / 'my-project'
|
||||
project_dir.mkdir()
|
||||
(project_dir / '.git').mkdir()
|
||||
|
||||
monkeypatch.setenv('CLAUDE_PROJECT_DIR', str(project_dir))
|
||||
|
||||
config = GiteaConfig()
|
||||
result = config._find_project_directory()
|
||||
|
||||
assert result == project_dir
|
||||
|
||||
|
||||
def test_find_project_directory_from_cwd(tmp_path, monkeypatch):
|
||||
"""Test finding project directory from cwd with .env file"""
|
||||
project_dir = tmp_path / 'project'
|
||||
project_dir.mkdir()
|
||||
(project_dir / '.env').write_text("GITEA_REPO=test/repo")
|
||||
|
||||
monkeypatch.chdir(project_dir)
|
||||
# Clear env vars that might interfere
|
||||
monkeypatch.delenv('CLAUDE_PROJECT_DIR', raising=False)
|
||||
monkeypatch.delenv('PWD', raising=False)
|
||||
|
||||
config = GiteaConfig()
|
||||
result = config._find_project_directory()
|
||||
|
||||
assert result == project_dir
|
||||
|
||||
|
||||
def test_find_project_directory_none_when_no_markers(tmp_path, monkeypatch):
|
||||
"""Test returns None when no project markers found"""
|
||||
empty_dir = tmp_path / 'empty'
|
||||
empty_dir.mkdir()
|
||||
|
||||
monkeypatch.chdir(empty_dir)
|
||||
monkeypatch.delenv('CLAUDE_PROJECT_DIR', raising=False)
|
||||
monkeypatch.delenv('PWD', raising=False)
|
||||
monkeypatch.delenv('GITEA_REPO', raising=False)
|
||||
|
||||
config = GiteaConfig()
|
||||
result = config._find_project_directory()
|
||||
|
||||
assert result is None
|
||||
|
||||
@@ -222,3 +222,47 @@ def test_no_repo_specified_error(gitea_client):
|
||||
client.list_issues()
|
||||
|
||||
assert "Repository not specified" in str(exc_info.value)
|
||||
|
||||
|
||||
# ========================================
|
||||
# ORGANIZATION DETECTION TESTS
|
||||
# ========================================
|
||||
|
||||
def test_is_organization_true(gitea_client):
|
||||
"""Test _is_organization returns True for valid organization"""
|
||||
mock_response = Mock()
|
||||
mock_response.status_code = 200
|
||||
|
||||
with patch.object(gitea_client.session, 'get', return_value=mock_response):
|
||||
result = gitea_client._is_organization('personal-projects')
|
||||
|
||||
assert result is True
|
||||
gitea_client.session.get.assert_called_once_with(
|
||||
'https://test.com/api/v1/orgs/personal-projects'
|
||||
)
|
||||
|
||||
|
||||
def test_is_organization_false(gitea_client):
|
||||
"""Test _is_organization returns False for user account"""
|
||||
mock_response = Mock()
|
||||
mock_response.status_code = 404
|
||||
|
||||
with patch.object(gitea_client.session, 'get', return_value=mock_response):
|
||||
result = gitea_client._is_organization('lmiranda')
|
||||
|
||||
assert result is False
|
||||
|
||||
|
||||
def test_is_org_repo_uses_orgs_endpoint(gitea_client):
|
||||
"""Test is_org_repo uses /orgs endpoint instead of owner.type"""
|
||||
mock_response = Mock()
|
||||
mock_response.status_code = 200
|
||||
|
||||
with patch.object(gitea_client.session, 'get', return_value=mock_response):
|
||||
result = gitea_client.is_org_repo('personal-projects/repo')
|
||||
|
||||
assert result is True
|
||||
# Should call /orgs/personal-projects, not /repos/.../
|
||||
gitea_client.session.get.assert_called_once_with(
|
||||
'https://test.com/api/v1/orgs/personal-projects'
|
||||
)
|
||||
|
||||
@@ -10,7 +10,8 @@ from mcp_server.tools.labels import LabelTools
|
||||
def mock_gitea_client():
|
||||
"""Fixture providing mocked Gitea client"""
|
||||
client = Mock()
|
||||
client.repo = 'test_repo'
|
||||
client.repo = 'test_org/test_repo'
|
||||
client.is_org_repo = Mock(return_value=True)
|
||||
return client
|
||||
|
||||
|
||||
@@ -39,10 +40,141 @@ async def test_get_labels(label_tools):
|
||||
assert result['total_count'] == 4
|
||||
|
||||
|
||||
# ========================================
|
||||
# LABEL LOOKUP TESTS (NEW)
|
||||
# ========================================
|
||||
|
||||
def test_build_label_lookup_slash_format():
|
||||
"""Test building label lookup with slash format labels"""
|
||||
mock_client = Mock()
|
||||
mock_client.repo = 'test/repo'
|
||||
tools = LabelTools(mock_client)
|
||||
|
||||
labels = ['Type/Bug', 'Type/Feature', 'Priority/High', 'Priority/Low']
|
||||
lookup = tools._build_label_lookup(labels)
|
||||
|
||||
assert 'type' in lookup
|
||||
assert 'bug' in lookup['type']
|
||||
assert lookup['type']['bug'] == 'Type/Bug'
|
||||
assert lookup['type']['feature'] == 'Type/Feature'
|
||||
assert 'priority' in lookup
|
||||
assert lookup['priority']['high'] == 'Priority/High'
|
||||
|
||||
|
||||
def test_build_label_lookup_colon_space_format():
|
||||
"""Test building label lookup with colon-space format labels"""
|
||||
mock_client = Mock()
|
||||
mock_client.repo = 'test/repo'
|
||||
tools = LabelTools(mock_client)
|
||||
|
||||
labels = ['Type: Bug', 'Type: Feature', 'Priority: High', 'Effort: M']
|
||||
lookup = tools._build_label_lookup(labels)
|
||||
|
||||
assert 'type' in lookup
|
||||
assert 'bug' in lookup['type']
|
||||
assert lookup['type']['bug'] == 'Type: Bug'
|
||||
assert lookup['type']['feature'] == 'Type: Feature'
|
||||
assert 'priority' in lookup
|
||||
assert lookup['priority']['high'] == 'Priority: High'
|
||||
# Test singular "Effort" (not "Efforts")
|
||||
assert 'effort' in lookup
|
||||
assert lookup['effort']['m'] == 'Effort: M'
|
||||
|
||||
|
||||
def test_build_label_lookup_efforts_normalization():
|
||||
"""Test that 'Efforts' is normalized to 'effort' for matching"""
|
||||
mock_client = Mock()
|
||||
mock_client.repo = 'test/repo'
|
||||
tools = LabelTools(mock_client)
|
||||
|
||||
labels = ['Efforts/XS', 'Efforts/S', 'Efforts/M']
|
||||
lookup = tools._build_label_lookup(labels)
|
||||
|
||||
# 'Efforts' should be normalized to 'effort'
|
||||
assert 'effort' in lookup
|
||||
assert lookup['effort']['xs'] == 'Efforts/XS'
|
||||
|
||||
|
||||
def test_find_label():
|
||||
"""Test finding labels from lookup"""
|
||||
mock_client = Mock()
|
||||
mock_client.repo = 'test/repo'
|
||||
tools = LabelTools(mock_client)
|
||||
|
||||
lookup = {
|
||||
'type': {'bug': 'Type: Bug', 'feature': 'Type: Feature'},
|
||||
'priority': {'high': 'Priority: High', 'low': 'Priority: Low'}
|
||||
}
|
||||
|
||||
assert tools._find_label(lookup, 'type', 'bug') == 'Type: Bug'
|
||||
assert tools._find_label(lookup, 'priority', 'high') == 'Priority: High'
|
||||
assert tools._find_label(lookup, 'type', 'nonexistent') is None
|
||||
assert tools._find_label(lookup, 'nonexistent', 'bug') is None
|
||||
|
||||
|
||||
# ========================================
|
||||
# SUGGEST LABELS WITH DYNAMIC FORMAT TESTS
|
||||
# ========================================
|
||||
|
||||
def _create_tools_with_labels(labels):
|
||||
"""Helper to create LabelTools with mocked labels"""
|
||||
import asyncio
|
||||
mock_client = Mock()
|
||||
mock_client.repo = 'test/repo'
|
||||
mock_client.is_org_repo = Mock(return_value=False)
|
||||
mock_client.get_labels = Mock(return_value=[{'name': l} for l in labels])
|
||||
return LabelTools(mock_client)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_suggest_labels_with_slash_format():
|
||||
"""Test label suggestion with slash format labels"""
|
||||
labels = [
|
||||
'Type/Bug', 'Type/Feature', 'Type/Refactor',
|
||||
'Priority/Critical', 'Priority/High', 'Priority/Medium', 'Priority/Low',
|
||||
'Complexity/Simple', 'Complexity/Medium', 'Complexity/Complex',
|
||||
'Component/Auth'
|
||||
]
|
||||
tools = _create_tools_with_labels(labels)
|
||||
|
||||
context = "Fix critical bug in login authentication"
|
||||
suggestions = await tools.suggest_labels(context)
|
||||
|
||||
assert 'Type/Bug' in suggestions
|
||||
assert 'Priority/Critical' in suggestions
|
||||
assert 'Component/Auth' in suggestions
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_suggest_labels_with_colon_space_format():
|
||||
"""Test label suggestion with colon-space format labels"""
|
||||
labels = [
|
||||
'Type: Bug', 'Type: Feature', 'Type: Refactor',
|
||||
'Priority: Critical', 'Priority: High', 'Priority: Medium', 'Priority: Low',
|
||||
'Complexity: Simple', 'Complexity: Medium', 'Complexity: Complex',
|
||||
'Effort: XS', 'Effort: S', 'Effort: M', 'Effort: L', 'Effort: XL'
|
||||
]
|
||||
tools = _create_tools_with_labels(labels)
|
||||
|
||||
context = "Fix critical bug for tiny 1 hour fix"
|
||||
suggestions = await tools.suggest_labels(context)
|
||||
|
||||
# Should return colon-space format labels
|
||||
assert 'Type: Bug' in suggestions
|
||||
assert 'Priority: Critical' in suggestions
|
||||
assert 'Effort: XS' in suggestions
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_suggest_labels_bug():
|
||||
"""Test label suggestion for bug context"""
|
||||
tools = LabelTools(Mock())
|
||||
labels = [
|
||||
'Type/Bug', 'Type/Feature',
|
||||
'Priority/Critical', 'Priority/High', 'Priority/Medium', 'Priority/Low',
|
||||
'Complexity/Simple', 'Complexity/Medium', 'Complexity/Complex',
|
||||
'Component/Auth'
|
||||
]
|
||||
tools = _create_tools_with_labels(labels)
|
||||
|
||||
context = "Fix critical bug in login authentication"
|
||||
suggestions = await tools.suggest_labels(context)
|
||||
@@ -55,7 +187,8 @@ async def test_suggest_labels_bug():
|
||||
@pytest.mark.asyncio
|
||||
async def test_suggest_labels_feature():
|
||||
"""Test label suggestion for feature context"""
|
||||
tools = LabelTools(Mock())
|
||||
labels = ['Type/Feature', 'Priority/Medium', 'Complexity/Medium']
|
||||
tools = _create_tools_with_labels(labels)
|
||||
|
||||
context = "Add new feature to implement user dashboard"
|
||||
suggestions = await tools.suggest_labels(context)
|
||||
@@ -67,7 +200,8 @@ async def test_suggest_labels_feature():
|
||||
@pytest.mark.asyncio
|
||||
async def test_suggest_labels_refactor():
|
||||
"""Test label suggestion for refactor context"""
|
||||
tools = LabelTools(Mock())
|
||||
labels = ['Type/Refactor', 'Priority/Medium', 'Complexity/Medium', 'Component/Backend']
|
||||
tools = _create_tools_with_labels(labels)
|
||||
|
||||
context = "Refactor architecture to extract service layer"
|
||||
suggestions = await tools.suggest_labels(context)
|
||||
@@ -79,7 +213,8 @@ async def test_suggest_labels_refactor():
|
||||
@pytest.mark.asyncio
|
||||
async def test_suggest_labels_documentation():
|
||||
"""Test label suggestion for documentation context"""
|
||||
tools = LabelTools(Mock())
|
||||
labels = ['Type/Documentation', 'Priority/Medium', 'Complexity/Medium', 'Component/API', 'Component/Docs']
|
||||
tools = _create_tools_with_labels(labels)
|
||||
|
||||
context = "Update documentation for API endpoints"
|
||||
suggestions = await tools.suggest_labels(context)
|
||||
@@ -91,7 +226,8 @@ async def test_suggest_labels_documentation():
|
||||
@pytest.mark.asyncio
|
||||
async def test_suggest_labels_priority():
|
||||
"""Test priority detection in suggestions"""
|
||||
tools = LabelTools(Mock())
|
||||
labels = ['Type/Feature', 'Priority/Critical', 'Priority/High', 'Priority/Medium', 'Priority/Low', 'Complexity/Medium']
|
||||
tools = _create_tools_with_labels(labels)
|
||||
|
||||
# Critical priority
|
||||
context = "Urgent blocker in production"
|
||||
@@ -112,7 +248,8 @@ async def test_suggest_labels_priority():
|
||||
@pytest.mark.asyncio
|
||||
async def test_suggest_labels_complexity():
|
||||
"""Test complexity detection in suggestions"""
|
||||
tools = LabelTools(Mock())
|
||||
labels = ['Type/Feature', 'Priority/Medium', 'Complexity/Simple', 'Complexity/Medium', 'Complexity/Complex']
|
||||
tools = _create_tools_with_labels(labels)
|
||||
|
||||
# Simple complexity
|
||||
context = "Simple quick fix for typo"
|
||||
@@ -128,7 +265,8 @@ async def test_suggest_labels_complexity():
|
||||
@pytest.mark.asyncio
|
||||
async def test_suggest_labels_efforts():
|
||||
"""Test efforts detection in suggestions"""
|
||||
tools = LabelTools(Mock())
|
||||
labels = ['Type/Feature', 'Priority/Medium', 'Complexity/Medium', 'Efforts/XS', 'Efforts/S', 'Efforts/M', 'Efforts/L', 'Efforts/XL']
|
||||
tools = _create_tools_with_labels(labels)
|
||||
|
||||
# XS effort
|
||||
context = "Tiny fix that takes 1 hour"
|
||||
@@ -144,7 +282,8 @@ async def test_suggest_labels_efforts():
|
||||
@pytest.mark.asyncio
|
||||
async def test_suggest_labels_components():
|
||||
"""Test component detection in suggestions"""
|
||||
tools = LabelTools(Mock())
|
||||
labels = ['Type/Feature', 'Priority/Medium', 'Complexity/Medium', 'Component/Backend', 'Component/Frontend', 'Component/API', 'Component/Database']
|
||||
tools = _create_tools_with_labels(labels)
|
||||
|
||||
# Backend component
|
||||
context = "Update backend API service"
|
||||
@@ -166,7 +305,8 @@ async def test_suggest_labels_components():
|
||||
@pytest.mark.asyncio
|
||||
async def test_suggest_labels_tech_stack():
|
||||
"""Test tech stack detection in suggestions"""
|
||||
tools = LabelTools(Mock())
|
||||
labels = ['Type/Feature', 'Priority/Medium', 'Complexity/Medium', 'Tech/Python', 'Tech/FastAPI', 'Tech/Docker', 'Tech/PostgreSQL']
|
||||
tools = _create_tools_with_labels(labels)
|
||||
|
||||
# Python
|
||||
context = "Update Python FastAPI endpoint"
|
||||
@@ -188,7 +328,8 @@ async def test_suggest_labels_tech_stack():
|
||||
@pytest.mark.asyncio
|
||||
async def test_suggest_labels_source():
|
||||
"""Test source detection in suggestions"""
|
||||
tools = LabelTools(Mock())
|
||||
labels = ['Type/Feature', 'Priority/Medium', 'Complexity/Medium', 'Source/Development', 'Source/Staging', 'Source/Production']
|
||||
tools = _create_tools_with_labels(labels)
|
||||
|
||||
# Development
|
||||
context = "Issue found in development environment"
|
||||
@@ -204,7 +345,8 @@ async def test_suggest_labels_source():
|
||||
@pytest.mark.asyncio
|
||||
async def test_suggest_labels_risk():
|
||||
"""Test risk detection in suggestions"""
|
||||
tools = LabelTools(Mock())
|
||||
labels = ['Type/Feature', 'Priority/Medium', 'Complexity/Medium', 'Risk/High', 'Risk/Low']
|
||||
tools = _create_tools_with_labels(labels)
|
||||
|
||||
# High risk
|
||||
context = "Breaking change to major API"
|
||||
@@ -220,7 +362,15 @@ async def test_suggest_labels_risk():
|
||||
@pytest.mark.asyncio
|
||||
async def test_suggest_labels_multiple_categories():
|
||||
"""Test that suggestions span multiple categories"""
|
||||
tools = LabelTools(Mock())
|
||||
labels = [
|
||||
'Type/Bug', 'Type/Feature',
|
||||
'Priority/Critical', 'Priority/Medium',
|
||||
'Complexity/Complex', 'Complexity/Medium',
|
||||
'Component/Backend', 'Component/API', 'Component/Auth',
|
||||
'Tech/FastAPI', 'Tech/PostgreSQL',
|
||||
'Source/Production'
|
||||
]
|
||||
tools = _create_tools_with_labels(labels)
|
||||
|
||||
context = """
|
||||
Urgent critical bug in production backend API service.
|
||||
@@ -244,3 +394,85 @@ async def test_suggest_labels_multiple_categories():
|
||||
|
||||
# Should have Source
|
||||
assert any('Source/' in label for label in suggestions)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_suggest_labels_empty_repo():
|
||||
"""Test suggestions when no repo specified and no labels available"""
|
||||
mock_client = Mock()
|
||||
mock_client.repo = None
|
||||
tools = LabelTools(mock_client)
|
||||
|
||||
context = "Fix a bug"
|
||||
suggestions = await tools.suggest_labels(context)
|
||||
|
||||
# Should return empty list when no repo
|
||||
assert suggestions == []
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_suggest_labels_no_matching_labels():
|
||||
"""Test suggestions return empty when no matching labels exist"""
|
||||
labels = ['Custom/Label', 'Other/Thing'] # No standard labels
|
||||
tools = _create_tools_with_labels(labels)
|
||||
|
||||
context = "Fix a bug"
|
||||
suggestions = await tools.suggest_labels(context)
|
||||
|
||||
# Should return empty list since no Type/Bug or similar exists
|
||||
assert len(suggestions) == 0
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_labels_org_owned_repo():
|
||||
"""Test getting labels for organization-owned repository"""
|
||||
mock_client = Mock()
|
||||
mock_client.repo = 'myorg/myrepo'
|
||||
mock_client.is_org_repo = Mock(return_value=True)
|
||||
mock_client.get_org_labels = Mock(return_value=[
|
||||
{'name': 'Type/Bug', 'id': 1},
|
||||
{'name': 'Type/Feature', 'id': 2}
|
||||
])
|
||||
mock_client.get_labels = Mock(return_value=[
|
||||
{'name': 'Component/Backend', 'id': 3}
|
||||
])
|
||||
|
||||
tools = LabelTools(mock_client)
|
||||
result = await tools.get_labels()
|
||||
|
||||
# Should fetch both org and repo labels
|
||||
mock_client.is_org_repo.assert_called_once_with('myorg/myrepo')
|
||||
mock_client.get_org_labels.assert_called_once_with('myorg')
|
||||
mock_client.get_labels.assert_called_once_with('myorg/myrepo')
|
||||
|
||||
assert len(result['organization']) == 2
|
||||
assert len(result['repository']) == 1
|
||||
assert result['total_count'] == 3
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_labels_user_owned_repo():
|
||||
"""Test getting labels for user-owned repository (no org labels)"""
|
||||
mock_client = Mock()
|
||||
mock_client.repo = 'lmiranda/personal-portfolio'
|
||||
mock_client.is_org_repo = Mock(return_value=False)
|
||||
mock_client.get_labels = Mock(return_value=[
|
||||
{'name': 'bug', 'id': 1},
|
||||
{'name': 'enhancement', 'id': 2}
|
||||
])
|
||||
|
||||
tools = LabelTools(mock_client)
|
||||
result = await tools.get_labels()
|
||||
|
||||
# Should check if org repo
|
||||
mock_client.is_org_repo.assert_called_once_with('lmiranda/personal-portfolio')
|
||||
|
||||
# Should NOT call get_org_labels for user-owned repos
|
||||
mock_client.get_org_labels.assert_not_called()
|
||||
|
||||
# Should still get repo labels
|
||||
mock_client.get_labels.assert_called_once_with('lmiranda/personal-portfolio')
|
||||
|
||||
assert len(result['organization']) == 0
|
||||
assert len(result['repository']) == 2
|
||||
assert result['total_count'] == 2
|
||||
|
||||
@@ -294,4 +294,4 @@ logging.basicConfig(level=logging.DEBUG)
|
||||
|
||||
## License
|
||||
|
||||
MIT License - Part of the Claude Code Marketplace (`support-claude-mktplace`).
|
||||
MIT License - Part of the Leo Claude Marketplace.
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
"name": "Leo Miranda",
|
||||
"email": "leobmiranda@gmail.com"
|
||||
},
|
||||
"homepage": "https://gitea.hotserv.cloud/personal-projects/support-claude-mktplace/src/branch/main/plugins/clarity-assist/README.md",
|
||||
"repository": "https://gitea.hotserv.cloud/personal-projects/support-claude-mktplace.git",
|
||||
"homepage": "https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace/src/branch/main/plugins/clarity-assist/README.md",
|
||||
"repository": "https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace.git",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"prompt-optimization",
|
||||
@@ -16,30 +16,5 @@
|
||||
"requirements",
|
||||
"methodology"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"name": "clarify",
|
||||
"description": "Full 4-D prompt optimization (Deconstruct, Diagnose, Develop, Deliver)",
|
||||
"file": "commands/clarify.md"
|
||||
},
|
||||
{
|
||||
"name": "quick-clarify",
|
||||
"description": "Rapid mode - single-pass clarification for simple requests",
|
||||
"file": "commands/quick-clarify.md"
|
||||
}
|
||||
],
|
||||
"agents": [
|
||||
{
|
||||
"name": "clarity-coach",
|
||||
"description": "ND-friendly coach for structured requirement gathering",
|
||||
"file": "agents/clarity-coach.md"
|
||||
}
|
||||
],
|
||||
"skills": [
|
||||
{
|
||||
"name": "prompt-patterns",
|
||||
"description": "Optimization rules and patterns for effective prompts",
|
||||
"path": "skills/prompt-patterns"
|
||||
}
|
||||
]
|
||||
"commands": ["./commands/"]
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
"name": "Leo Miranda",
|
||||
"email": "leobmiranda@gmail.com"
|
||||
},
|
||||
"homepage": "https://gitea.hotserv.cloud/personal-projects/support-claude-mktplace/src/branch/main/plugins/claude-config-maintainer/README.md",
|
||||
"repository": "https://gitea.hotserv.cloud/personal-projects/support-claude-mktplace.git",
|
||||
"homepage": "https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace/src/branch/main/plugins/claude-config-maintainer/README.md",
|
||||
"repository": "https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace.git",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"claude-code",
|
||||
@@ -16,7 +16,5 @@
|
||||
"claude-md",
|
||||
"developer-tools"
|
||||
],
|
||||
"entryPoint": "agents/maintainer.md",
|
||||
"commands": ["./commands/"],
|
||||
"agents": ["./agents/"]
|
||||
"commands": ["./commands/"]
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ CLAUDE.md files provide instructions to Claude Code when working with a project.
|
||||
|
||||
## Installation
|
||||
|
||||
This plugin is part of the support-claude-mktplace collection. Install the marketplace and the plugin will be available.
|
||||
This plugin is part of the Leo Claude Marketplace. Install the marketplace and the plugin will be available.
|
||||
|
||||
## Commands
|
||||
|
||||
@@ -96,4 +96,4 @@ Target score: **70+** for effective Claude Code usage.
|
||||
|
||||
## Contributing
|
||||
|
||||
This plugin is part of the personal-projects/support-claude-mktplace repository.
|
||||
This plugin is part of the personal-projects/leo-claude-mktplace repository.
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
"name": "Leo Miranda",
|
||||
"email": "leobmiranda@gmail.com"
|
||||
},
|
||||
"homepage": "https://gitea.hotserv.cloud/personal-projects/support-claude-mktplace/src/branch/main/plugins/cmdb-assistant/README.md",
|
||||
"repository": "https://gitea.hotserv.cloud/personal-projects/support-claude-mktplace.git",
|
||||
"homepage": "https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace/src/branch/main/plugins/cmdb-assistant/README.md",
|
||||
"repository": "https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace.git",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"netbox",
|
||||
@@ -18,6 +18,5 @@
|
||||
"dcim"
|
||||
],
|
||||
"commands": ["./commands/"],
|
||||
"agents": ["./agents/"],
|
||||
"mcpServers": "./.mcp.json"
|
||||
"mcpServers": ["./.mcp.json"]
|
||||
}
|
||||
|
||||
@@ -167,4 +167,4 @@ The plugin uses the shared NetBox MCP server at `../mcp-servers/netbox/`.
|
||||
|
||||
## License
|
||||
|
||||
MIT License - Part of the Claude Code Marketplace.
|
||||
MIT License - Part of the Leo Claude Marketplace.
|
||||
|
||||
160
plugins/cmdb-assistant/commands/initial-setup.md
Normal file
160
plugins/cmdb-assistant/commands/initial-setup.md
Normal file
@@ -0,0 +1,160 @@
|
||||
---
|
||||
description: Interactive setup wizard for cmdb-assistant plugin - configures NetBox MCP server
|
||||
---
|
||||
|
||||
# CMDB Assistant Setup Wizard
|
||||
|
||||
This command sets up the cmdb-assistant plugin with NetBox integration.
|
||||
|
||||
## Important Context
|
||||
|
||||
- **This command uses Bash, Read, Write, and AskUserQuestion tools** - NOT MCP tools
|
||||
- **MCP tools won't work until after setup + session restart**
|
||||
- **Uses NetBox MCP server (separate from Gitea MCP)**
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Environment Validation
|
||||
|
||||
### Step 1.1: Check Python Version
|
||||
|
||||
```bash
|
||||
python3 --version
|
||||
```
|
||||
|
||||
If below 3.10, stop setup and inform user.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: MCP Server Setup
|
||||
|
||||
### Step 2.1: Locate NetBox MCP Server
|
||||
|
||||
```bash
|
||||
find ~/.claude ~/.config/claude -name "mcp_server" -path "*netbox*" 2>/dev/null | head -5
|
||||
```
|
||||
|
||||
If not found, ask user for marketplace location.
|
||||
|
||||
### Step 2.2: Check Virtual Environment
|
||||
|
||||
```bash
|
||||
ls -la /path/to/mcp-servers/netbox/.venv/bin/python 2>/dev/null && echo "VENV_EXISTS" || echo "VENV_MISSING"
|
||||
```
|
||||
|
||||
### Step 2.3: Create Virtual Environment (if missing)
|
||||
|
||||
```bash
|
||||
cd /path/to/mcp-servers/netbox && python3 -m venv .venv && source .venv/bin/activate && pip install --upgrade pip && pip install -r requirements.txt && deactivate
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: System Configuration
|
||||
|
||||
### Step 3.1: Create Config Directory
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.config/claude
|
||||
```
|
||||
|
||||
### Step 3.2: Check NetBox Configuration
|
||||
|
||||
```bash
|
||||
cat ~/.config/claude/netbox.env 2>/dev/null || echo "FILE_NOT_FOUND"
|
||||
```
|
||||
|
||||
**If file exists with valid values:** Skip to Phase 4.
|
||||
**If missing or has placeholders:** Continue.
|
||||
|
||||
### Step 3.3: Gather NetBox Information
|
||||
|
||||
Use AskUserQuestion:
|
||||
- Question: "What is your NetBox server URL? (e.g., https://netbox.company.com)"
|
||||
- Header: "NetBox URL"
|
||||
- Options:
|
||||
- "Other (I'll provide the URL)"
|
||||
|
||||
Ask user to provide the URL.
|
||||
|
||||
### Step 3.4: Create Configuration File
|
||||
|
||||
```bash
|
||||
cat > ~/.config/claude/netbox.env << 'EOF'
|
||||
# NetBox API Configuration
|
||||
# Generated by cmdb-assistant /initial-setup
|
||||
|
||||
NETBOX_API_URL=<USER_PROVIDED_URL>
|
||||
NETBOX_API_TOKEN=PASTE_YOUR_TOKEN_HERE
|
||||
EOF
|
||||
chmod 600 ~/.config/claude/netbox.env
|
||||
```
|
||||
|
||||
### Step 3.5: Token Instructions
|
||||
|
||||
---
|
||||
|
||||
**Action Required: Add Your NetBox API Token**
|
||||
|
||||
I've created `~/.config/claude/netbox.env` but you need to add your API token manually.
|
||||
|
||||
**Steps:**
|
||||
1. Open: `nano ~/.config/claude/netbox.env`
|
||||
2. Generate token in NetBox: Admin → API Tokens → Add Token
|
||||
3. Replace `PASTE_YOUR_TOKEN_HERE` with your token
|
||||
4. Save the file
|
||||
|
||||
---
|
||||
|
||||
Use AskUserQuestion:
|
||||
- Question: "Have you added your NetBox token?"
|
||||
- Header: "Token"
|
||||
- Options:
|
||||
- "Yes, I've added the token"
|
||||
- "Skip for now"
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Validation
|
||||
|
||||
### Step 4.1: Test Configuration (if token was added)
|
||||
|
||||
```bash
|
||||
source ~/.config/claude/netbox.env && curl -s -o /dev/null -w "%{http_code}" -H "Authorization: Token $NETBOX_API_TOKEN" "$NETBOX_API_URL/api/"
|
||||
```
|
||||
|
||||
Report result:
|
||||
- 200: Success
|
||||
- 403: Invalid token
|
||||
- Other: Connection issue
|
||||
|
||||
### Step 4.2: Summary
|
||||
|
||||
```
|
||||
╔════════════════════════════════════════════════════════════╗
|
||||
║ CMDB-ASSISTANT SETUP COMPLETE ║
|
||||
╠════════════════════════════════════════════════════════════╣
|
||||
║ MCP Server (NetBox): ✓ Ready ║
|
||||
║ System Config: ✓ ~/.config/claude/netbox.env ║
|
||||
╚════════════════════════════════════════════════════════════╝
|
||||
```
|
||||
|
||||
### Step 4.3: Session Restart Notice
|
||||
|
||||
---
|
||||
|
||||
**⚠️ Session Restart Required**
|
||||
|
||||
Restart your Claude Code session for MCP tools to become available.
|
||||
|
||||
**After restart, you can:**
|
||||
- Run `/cmdb-device <hostname>` to look up a device
|
||||
- Run `/cmdb-ip <address>` to look up an IP address
|
||||
- Run `/cmdb-site <name>` to look up a site
|
||||
- Run `/cmdb-search <query>` for general search
|
||||
|
||||
---
|
||||
|
||||
## Note on Project Configuration
|
||||
|
||||
cmdb-assistant does not require project-level configuration. The NetBox connection is system-wide and not tied to specific repositories.
|
||||
@@ -6,8 +6,8 @@
|
||||
"name": "Leo Miranda",
|
||||
"email": "leobmiranda@gmail.com"
|
||||
},
|
||||
"homepage": "https://gitea.hotserv.cloud/personal-projects/support-claude-mktplace/src/branch/main/plugins/code-sentinel/README.md",
|
||||
"repository": "https://gitea.hotserv.cloud/personal-projects/support-claude-mktplace.git",
|
||||
"homepage": "https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace/src/branch/main/plugins/code-sentinel/README.md",
|
||||
"repository": "https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace.git",
|
||||
"license": "MIT",
|
||||
"keywords": ["security", "refactoring", "code-quality", "static-analysis", "hooks"]
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ Security scanning and code refactoring tools for Claude Code projects.
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
/plugin marketplace add https://gitea.hotserv.cloud/personal-projects/support-claude-mktplace.git
|
||||
/plugin marketplace add https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace.git
|
||||
/plugin install code-sentinel
|
||||
```
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
"name": "Leo Miranda",
|
||||
"email": "leobmiranda@gmail.com"
|
||||
},
|
||||
"homepage": "https://gitea.hotserv.cloud/personal-projects/support-claude-mktplace/src/branch/main/plugins/doc-guardian/README.md",
|
||||
"repository": "https://gitea.hotserv.cloud/personal-projects/support-claude-mktplace.git",
|
||||
"homepage": "https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace/src/branch/main/plugins/doc-guardian/README.md",
|
||||
"repository": "https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace.git",
|
||||
"license": "MIT",
|
||||
"keywords": ["documentation", "sync", "drift-detection", "automation", "hooks"]
|
||||
}
|
||||
|
||||
@@ -11,10 +11,10 @@ Documentation gets outdated. Functions get renamed, configs change, versions bum
|
||||
|
||||
## Solution
|
||||
|
||||
doc-guardian watches your code changes and automatically:
|
||||
1. Detects when changes affect documentation
|
||||
2. Queues updates silently (doesn't interrupt your flow)
|
||||
3. Syncs all doc changes in a single commit when ready
|
||||
doc-guardian monitors your code changes via hooks:
|
||||
1. Detects when changes might affect documentation
|
||||
2. Alerts you to potential drift (doesn't interrupt your flow)
|
||||
3. Provides commands to audit and sync docs when ready
|
||||
|
||||
## Commands
|
||||
|
||||
@@ -25,8 +25,7 @@ doc-guardian watches your code changes and automatically:
|
||||
|
||||
## Hooks
|
||||
|
||||
- **PostToolUse (Write\|Edit)**: Silently checks if code changes affect docs
|
||||
- **Stop**: Reminds you of pending doc updates before session ends
|
||||
- **PostToolUse (Write|Edit)**: Silently checks if code changes affect docs
|
||||
|
||||
## What It Detects
|
||||
|
||||
@@ -37,10 +36,10 @@ doc-guardian watches your code changes and automatically:
|
||||
|
||||
## Installation
|
||||
|
||||
This plugin is part of the claude-code-marketplace.
|
||||
This plugin is part of the Leo Claude Marketplace.
|
||||
|
||||
```bash
|
||||
/plugin marketplace add https://gitea.hotserv.cloud/personal-projects/support-claude-mktplace.git
|
||||
/plugin marketplace add https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace.git
|
||||
/plugin install doc-guardian
|
||||
```
|
||||
|
||||
|
||||
@@ -6,18 +6,7 @@
|
||||
"hooks": [
|
||||
{
|
||||
"type": "prompt",
|
||||
"prompt": "A file was just modified. Silently check if this change affects any documentation:\n\n1. If a code file changed: check if README, CLAUDE.md, docstrings, or API docs reference the modified functions/classes/configs\n2. If drift detected: add to internal queue (do NOT interrupt user flow)\n3. At natural breakpoints or when user runs /doc-sync: report pending doc updates\n\nDo NOT announce this check unless drift is found. Work silently."
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"Stop": [
|
||||
{
|
||||
"matcher": ".*",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "prompt",
|
||||
"prompt": "Before ending, check if there are pending documentation updates queued by doc-guardian. If yes, ask user: 'I detected documentation drift in X files. Run /doc-sync to update, or skip for now?'"
|
||||
"prompt": "A file was just modified. Silently check if this change affects any documentation:\n\n1. If a code file changed: check if README, CLAUDE.md, docstrings, or API docs reference the modified functions/classes/configs\n2. If drift detected: briefly mention it to the user (e.g., 'Note: This change may require updating X documentation')\n3. Do NOT block the workflow - just inform\n\nDo NOT announce this check unless drift is found. Work silently."
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
"name": "Leo Miranda",
|
||||
"email": "leobmiranda@gmail.com"
|
||||
},
|
||||
"homepage": "https://gitea.hotserv.cloud/personal-projects/support-claude-mktplace/src/branch/main/plugins/git-flow/README.md",
|
||||
"repository": "https://gitea.hotserv.cloud/personal-projects/support-claude-mktplace.git",
|
||||
"homepage": "https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace/src/branch/main/plugins/git-flow/README.md",
|
||||
"repository": "https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace.git",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"git",
|
||||
@@ -16,60 +16,5 @@
|
||||
"branch",
|
||||
"automation"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"name": "commit",
|
||||
"description": "Create a commit with auto-generated conventional message",
|
||||
"file": "commands/commit.md"
|
||||
},
|
||||
{
|
||||
"name": "commit-push",
|
||||
"description": "Commit and push to remote in one operation",
|
||||
"file": "commands/commit-push.md"
|
||||
},
|
||||
{
|
||||
"name": "commit-merge",
|
||||
"description": "Commit current changes and merge into target branch",
|
||||
"file": "commands/commit-merge.md"
|
||||
},
|
||||
{
|
||||
"name": "commit-sync",
|
||||
"description": "Commit, push, and sync with upstream",
|
||||
"file": "commands/commit-sync.md"
|
||||
},
|
||||
{
|
||||
"name": "branch-start",
|
||||
"description": "Start a new feature/fix/chore branch with naming convention",
|
||||
"file": "commands/branch-start.md"
|
||||
},
|
||||
{
|
||||
"name": "branch-cleanup",
|
||||
"description": "Clean up merged branches locally and optionally remotely",
|
||||
"file": "commands/branch-cleanup.md"
|
||||
},
|
||||
{
|
||||
"name": "git-status",
|
||||
"description": "Enhanced git status with recommendations",
|
||||
"file": "commands/git-status.md"
|
||||
},
|
||||
{
|
||||
"name": "git-config",
|
||||
"description": "Configure git-flow settings for this project",
|
||||
"file": "commands/git-config.md"
|
||||
}
|
||||
],
|
||||
"agents": [
|
||||
{
|
||||
"name": "git-assistant",
|
||||
"description": "Git workflow assistant for complex operations",
|
||||
"file": "agents/git-assistant.md"
|
||||
}
|
||||
],
|
||||
"skills": [
|
||||
{
|
||||
"name": "workflow-patterns",
|
||||
"description": "Git branching strategies and workflow patterns",
|
||||
"path": "skills/workflow-patterns"
|
||||
}
|
||||
]
|
||||
"commands": ["./commands/"]
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
"name": "Leo Miranda",
|
||||
"email": "leobmiranda@gmail.com"
|
||||
},
|
||||
"homepage": "https://gitea.hotserv.cloud/personal-projects/support-claude-mktplace/src/branch/main/plugins/pr-review/README.md",
|
||||
"repository": "https://gitea.hotserv.cloud/personal-projects/support-claude-mktplace.git",
|
||||
"homepage": "https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace/src/branch/main/plugins/pr-review/README.md",
|
||||
"repository": "https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace.git",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"pull-request",
|
||||
@@ -16,56 +16,6 @@
|
||||
"performance",
|
||||
"multi-agent"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"name": "pr-review",
|
||||
"description": "Full multi-agent PR review (security, performance, maintainability, tests)",
|
||||
"file": "commands/pr-review.md"
|
||||
},
|
||||
{
|
||||
"name": "pr-summary",
|
||||
"description": "Quick summary of PR changes without full review",
|
||||
"file": "commands/pr-summary.md"
|
||||
},
|
||||
{
|
||||
"name": "pr-findings",
|
||||
"description": "List and filter review findings by category or confidence",
|
||||
"file": "commands/pr-findings.md"
|
||||
}
|
||||
],
|
||||
"agents": [
|
||||
{
|
||||
"name": "coordinator",
|
||||
"description": "Orchestrates the multi-agent review process",
|
||||
"file": "agents/coordinator.md"
|
||||
},
|
||||
{
|
||||
"name": "security-reviewer",
|
||||
"description": "Analyzes code for security vulnerabilities",
|
||||
"file": "agents/security-reviewer.md"
|
||||
},
|
||||
{
|
||||
"name": "performance-analyst",
|
||||
"description": "Identifies performance issues and optimization opportunities",
|
||||
"file": "agents/performance-analyst.md"
|
||||
},
|
||||
{
|
||||
"name": "maintainability-auditor",
|
||||
"description": "Reviews code quality, patterns, and maintainability",
|
||||
"file": "agents/maintainability-auditor.md"
|
||||
},
|
||||
{
|
||||
"name": "test-validator",
|
||||
"description": "Validates test coverage and test quality",
|
||||
"file": "agents/test-validator.md"
|
||||
}
|
||||
],
|
||||
"skills": [
|
||||
{
|
||||
"name": "review-patterns",
|
||||
"description": "Code review patterns and confidence scoring rules",
|
||||
"path": "skills/review-patterns"
|
||||
}
|
||||
],
|
||||
"mcpServers": ["gitea"]
|
||||
"commands": ["./commands/"],
|
||||
"mcpServers": ["./.mcp.json"]
|
||||
}
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
"gitea": {
|
||||
"command": "${CLAUDE_PLUGIN_ROOT}/mcp-servers/gitea/.venv/bin/python",
|
||||
"args": ["-m", "mcp_server.server"],
|
||||
"cwd": "${CLAUDE_PLUGIN_ROOT}/mcp-servers/gitea"
|
||||
"cwd": "${CLAUDE_PLUGIN_ROOT}/mcp-servers/gitea",
|
||||
"env": {
|
||||
"PYTHONPATH": "${CLAUDE_PLUGIN_ROOT}/mcp-servers/gitea"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
273
plugins/pr-review/commands/initial-setup.md
Normal file
273
plugins/pr-review/commands/initial-setup.md
Normal file
@@ -0,0 +1,273 @@
|
||||
---
|
||||
description: Interactive setup wizard for pr-review plugin - configures Gitea MCP and project settings
|
||||
---
|
||||
|
||||
# PR Review Setup Wizard
|
||||
|
||||
This command sets up the pr-review plugin. It shares the Gitea MCP server with projman, so if you've already run `/initial-setup` for projman, most of the work is done.
|
||||
|
||||
## Important Context
|
||||
|
||||
- **This command uses Bash, Read, Write, and AskUserQuestion tools** - NOT MCP tools
|
||||
- **MCP tools won't work until after setup + session restart**
|
||||
- **Shares Gitea MCP server with projman plugin**
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Check Existing Setup
|
||||
|
||||
### Step 1.1: Check if Gitea MCP is Already Configured
|
||||
|
||||
First, check if the system configuration already exists (from projman or previous setup):
|
||||
|
||||
```bash
|
||||
cat ~/.config/claude/gitea.env 2>/dev/null || echo "FILE_NOT_FOUND"
|
||||
```
|
||||
|
||||
**If file exists with valid values (no placeholders):**
|
||||
- Skip to Phase 3 (Project Configuration)
|
||||
- Inform user: "Gitea configuration found. Skipping system setup."
|
||||
|
||||
**If file doesn't exist or has placeholders:**
|
||||
- Continue to Phase 2
|
||||
|
||||
### Step 1.2: Check if projman is Installed
|
||||
|
||||
Check if projman plugin exists (they share MCP server):
|
||||
|
||||
```bash
|
||||
find ~/.claude ~/.config/claude -name "projman" -type d 2>/dev/null | head -1
|
||||
```
|
||||
|
||||
**If projman exists:**
|
||||
- Suggest: "The projman plugin is installed and shares the same Gitea MCP server. Consider running `/initial-setup` from projman for the full setup wizard."
|
||||
|
||||
Use AskUserQuestion:
|
||||
- Question: "How would you like to proceed with setup?"
|
||||
- Header: "Setup"
|
||||
- Options:
|
||||
- "Continue with pr-review setup (Recommended if not using projman)"
|
||||
- "I'll use projman's /initial-setup instead"
|
||||
|
||||
**If user chooses projman setup:** End here with instructions to run projman's setup.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: System Setup (if needed)
|
||||
|
||||
This is a condensed version focusing on what pr-review needs.
|
||||
|
||||
### Step 2.1: Python and MCP Server
|
||||
|
||||
Check Python version:
|
||||
```bash
|
||||
python3 --version
|
||||
```
|
||||
|
||||
If below 3.10, stop and inform user.
|
||||
|
||||
Locate and set up the MCP server:
|
||||
```bash
|
||||
find ~/.claude ~/.config/claude -name "mcp_server" -path "*gitea*" 2>/dev/null | head -5
|
||||
```
|
||||
|
||||
If venv doesn't exist, create it:
|
||||
```bash
|
||||
cd /path/to/mcp-servers/gitea && python3 -m venv .venv && source .venv/bin/activate && pip install --upgrade pip && pip install -r requirements.txt && deactivate
|
||||
```
|
||||
|
||||
### Step 2.2: Gitea Configuration
|
||||
|
||||
Create config directory:
|
||||
```bash
|
||||
mkdir -p ~/.config/claude
|
||||
```
|
||||
|
||||
Use AskUserQuestion:
|
||||
- Question: "What is your Gitea server URL?"
|
||||
- Header: "Gitea URL"
|
||||
- Options:
|
||||
- "https://gitea.hotserv.cloud"
|
||||
- "Other (I'll provide the URL)"
|
||||
|
||||
Create configuration file (credentials only, org is per-project):
|
||||
```bash
|
||||
cat > ~/.config/claude/gitea.env << 'EOF'
|
||||
# Gitea API Configuration
|
||||
# Generated by pr-review /initial-setup
|
||||
# Note: GITEA_ORG is configured per-project in .env
|
||||
|
||||
GITEA_API_URL=<USER_PROVIDED_URL>
|
||||
GITEA_API_TOKEN=PASTE_YOUR_TOKEN_HERE
|
||||
EOF
|
||||
chmod 600 ~/.config/claude/gitea.env
|
||||
```
|
||||
|
||||
### Step 2.3: Token Instructions
|
||||
|
||||
Display these instructions:
|
||||
|
||||
---
|
||||
|
||||
**Action Required: Add Your Gitea API Token**
|
||||
|
||||
I've created `~/.config/claude/gitea.env` but you need to add your API token manually.
|
||||
|
||||
**Steps:**
|
||||
1. Open: `nano ~/.config/claude/gitea.env`
|
||||
2. Generate token in Gitea: Settings → Applications → Generate New Token
|
||||
- Permissions needed: `repo`, `read:org`, `read:user`
|
||||
3. Replace `PASTE_YOUR_TOKEN_HERE` with your token
|
||||
4. Save the file
|
||||
|
||||
---
|
||||
|
||||
Use AskUserQuestion:
|
||||
- Question: "Have you added your Gitea token?"
|
||||
- Header: "Token"
|
||||
- Options:
|
||||
- "Yes, I've added the token"
|
||||
- "Skip for now"
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: Project Configuration
|
||||
|
||||
### Step 3.1: Check Current Directory
|
||||
|
||||
```bash
|
||||
pwd && git rev-parse --show-toplevel 2>/dev/null || echo "NOT_A_GIT_REPO"
|
||||
```
|
||||
|
||||
### Step 3.2: Check Existing Project Config
|
||||
|
||||
```bash
|
||||
cat .env 2>/dev/null | grep GITEA_REPO || echo "NOT_FOUND"
|
||||
```
|
||||
|
||||
If `GITEA_REPO` is already set, skip to Phase 4.
|
||||
|
||||
### Step 3.3: Detect Organization and Repository
|
||||
|
||||
Extract organization:
|
||||
```bash
|
||||
git remote get-url origin 2>/dev/null | sed 's/.*[:/]\([^/]*\)\/[^/]*$/\1/'
|
||||
```
|
||||
|
||||
Extract repository:
|
||||
```bash
|
||||
git remote get-url origin 2>/dev/null | sed 's/.*[:/]\([^/]*\)\.git$/\1/' | sed 's/.*\/\([^/]*\)$/\1/'
|
||||
```
|
||||
|
||||
### Step 3.4: Validate Repository via Gitea API
|
||||
|
||||
```bash
|
||||
source ~/.config/claude/gitea.env
|
||||
curl -s -o /dev/null -w "%{http_code}" -H "Authorization: token $GITEA_API_TOKEN" "$GITEA_API_URL/repos/<detected-org>/<detected-repo>"
|
||||
```
|
||||
|
||||
| HTTP Code | Action |
|
||||
|-----------|--------|
|
||||
| **200** | Auto-fill - "Verified: <org>/<repo> exists" - skip to Step 3.7 |
|
||||
| **404** | Not found - proceed to Step 3.5 |
|
||||
| **401/403** | Permission issue - warn, proceed to Step 3.5 |
|
||||
|
||||
### Step 3.5: Confirm Organization (only if validation failed)
|
||||
|
||||
Use AskUserQuestion:
|
||||
- Question: "Repository not found. Is '<detected-org>' the correct organization?"
|
||||
- Header: "Organization"
|
||||
- Options:
|
||||
- "Yes, that's correct"
|
||||
- "No, let me specify"
|
||||
|
||||
### Step 3.6: Confirm Repository (only if validation failed)
|
||||
|
||||
Use AskUserQuestion:
|
||||
- Question: "Is '<detected-repo-name>' the correct repository?"
|
||||
- Header: "Repository"
|
||||
- Options:
|
||||
- "Yes, that's correct"
|
||||
- "No, let me specify"
|
||||
|
||||
**After corrections, re-validate via API (Step 3.4).**
|
||||
|
||||
### Step 3.7: Create/Update Project Config
|
||||
|
||||
If `.env` exists, append:
|
||||
```bash
|
||||
echo "GITEA_ORG=<ORG_NAME>" >> .env
|
||||
echo "GITEA_REPO=<REPO_NAME>" >> .env
|
||||
```
|
||||
|
||||
If `.env` doesn't exist:
|
||||
```bash
|
||||
cat > .env << 'EOF'
|
||||
# Project Configuration
|
||||
GITEA_ORG=<ORG_NAME>
|
||||
GITEA_REPO=<REPO_NAME>
|
||||
EOF
|
||||
```
|
||||
|
||||
### Step 3.5: PR Review Settings (Optional)
|
||||
|
||||
Use AskUserQuestion:
|
||||
- Question: "Do you want to configure PR review settings?"
|
||||
- Header: "Settings"
|
||||
- Options:
|
||||
- "Use defaults (Recommended)"
|
||||
- "Let me customize"
|
||||
|
||||
If customize, ask about:
|
||||
- `PR_REVIEW_CONFIDENCE_THRESHOLD` (default: 0.5)
|
||||
- `PR_REVIEW_AUTO_SUBMIT` (default: false)
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Validation and Next Steps
|
||||
|
||||
### Step 4.1: Test Configuration (if token was added)
|
||||
|
||||
```bash
|
||||
source ~/.config/claude/gitea.env && curl -s -o /dev/null -w "%{http_code}" -H "Authorization: token $GITEA_API_TOKEN" "$GITEA_API_URL/user"
|
||||
```
|
||||
|
||||
Report result:
|
||||
- 200: Success
|
||||
- 401: Invalid token
|
||||
- Other: Connection issue
|
||||
|
||||
### Step 4.2: Summary
|
||||
|
||||
```
|
||||
╔════════════════════════════════════════════════════════════╗
|
||||
║ PR-REVIEW SETUP COMPLETE ║
|
||||
╠════════════════════════════════════════════════════════════╣
|
||||
║ MCP Server (Gitea): ✓ Ready ║
|
||||
║ System Config: ✓ ~/.config/claude/gitea.env ║
|
||||
║ Project Config: ✓ ./.env ║
|
||||
╚════════════════════════════════════════════════════════════╝
|
||||
```
|
||||
|
||||
### Step 4.3: Session Restart Notice
|
||||
|
||||
---
|
||||
|
||||
**⚠️ Session Restart Required**
|
||||
|
||||
Restart your Claude Code session for MCP tools to become available.
|
||||
|
||||
**After restart, you can:**
|
||||
- Run `/pr-review <PR_NUMBER>` to review a pull request
|
||||
- Run `/pr-summary <PR_NUMBER>` for a quick summary
|
||||
- Run `/pr-findings <PR_NUMBER>` to list actionable findings
|
||||
|
||||
---
|
||||
|
||||
## Available Commands After Setup
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `/pr-review <number>` | Full multi-agent PR review with confidence scoring |
|
||||
| `/pr-summary <number>` | Quick PR summary |
|
||||
| `/pr-findings <number>` | List findings with severity and line numbers |
|
||||
136
plugins/pr-review/commands/project-init.md
Normal file
136
plugins/pr-review/commands/project-init.md
Normal file
@@ -0,0 +1,136 @@
|
||||
---
|
||||
description: Quick project setup - configures only project-level settings for PR review
|
||||
---
|
||||
|
||||
# Project Initialization (PR Review)
|
||||
|
||||
Fast setup for a new project when system-level configuration is already complete.
|
||||
|
||||
**Use this when:**
|
||||
- You've already run `/initial-setup` on this machine
|
||||
- You're starting work on a new project/repository
|
||||
- You just need to configure this project for PR reviews
|
||||
|
||||
---
|
||||
|
||||
## Pre-Flight Check
|
||||
|
||||
### Step 1: Verify System Configuration
|
||||
|
||||
```bash
|
||||
cat ~/.config/claude/gitea.env 2>/dev/null | grep -v "^#" | grep -v "PASTE_YOUR" | grep "GITEA_API_TOKEN=" && echo "SYSTEM_OK" || echo "SYSTEM_MISSING"
|
||||
```
|
||||
|
||||
**If SYSTEM_MISSING:**
|
||||
|
||||
---
|
||||
|
||||
**System configuration not found.**
|
||||
|
||||
Please run `/initial-setup` first to configure Gitea credentials.
|
||||
|
||||
---
|
||||
|
||||
**If SYSTEM_OK:** Continue.
|
||||
|
||||
---
|
||||
|
||||
## Project Setup
|
||||
|
||||
### Step 2: Verify Current Directory
|
||||
|
||||
```bash
|
||||
pwd && git rev-parse --show-toplevel 2>/dev/null || echo "NOT_A_GIT_REPO"
|
||||
```
|
||||
|
||||
### Step 3: Check Existing Configuration
|
||||
|
||||
```bash
|
||||
cat .env 2>/dev/null | grep "GITEA_REPO=" || echo "NOT_CONFIGURED"
|
||||
```
|
||||
|
||||
If already configured, ask if user wants to keep or reconfigure.
|
||||
|
||||
### Step 4: Detect Organization and Repository
|
||||
|
||||
Extract organization:
|
||||
```bash
|
||||
git remote get-url origin 2>/dev/null | sed 's/.*[:/]\([^/]*\)\/[^/]*$/\1/'
|
||||
```
|
||||
|
||||
Extract repository:
|
||||
```bash
|
||||
git remote get-url origin 2>/dev/null | sed 's/.*[:/]\([^/]*\)\.git$/\1/' | sed 's/.*\/\([^/]*\)$/\1/'
|
||||
```
|
||||
|
||||
### Step 5: Validate Repository via Gitea API
|
||||
|
||||
```bash
|
||||
source ~/.config/claude/gitea.env
|
||||
curl -s -o /dev/null -w "%{http_code}" -H "Authorization: token $GITEA_API_TOKEN" "$GITEA_API_URL/repos/<detected-org>/<detected-repo>"
|
||||
```
|
||||
|
||||
| HTTP Code | Action |
|
||||
|-----------|--------|
|
||||
| **200** | Auto-fill - "Verified: <org>/<repo> exists" - skip to Step 8 |
|
||||
| **404** | Not found - proceed to Step 6 |
|
||||
| **401/403** | Permission issue - warn, proceed to Step 6 |
|
||||
|
||||
### Step 6: Confirm Organization (only if validation failed)
|
||||
|
||||
Use AskUserQuestion:
|
||||
- Question: "Repository not found. Is '<detected-org>' the correct organization?"
|
||||
- Header: "Organization"
|
||||
- Options:
|
||||
- "Yes, that's correct"
|
||||
- "No, let me specify"
|
||||
|
||||
### Step 7: Confirm Repository (only if validation failed)
|
||||
|
||||
Use AskUserQuestion:
|
||||
- Question: "Is '<detected-repo-name>' the correct repository?"
|
||||
- Header: "Repository"
|
||||
- Options:
|
||||
- "Yes, that's correct"
|
||||
- "No, let me specify"
|
||||
|
||||
**After corrections, re-validate via API (Step 5).**
|
||||
|
||||
### Step 8: Create/Update .env
|
||||
|
||||
```bash
|
||||
echo "GITEA_ORG=<ORG_NAME>" >> .env
|
||||
echo "GITEA_REPO=<REPO_NAME>" >> .env
|
||||
```
|
||||
|
||||
### Step 9: Optional PR Review Settings
|
||||
|
||||
Use AskUserQuestion:
|
||||
- Question: "Configure PR review settings?"
|
||||
- Header: "Settings"
|
||||
- Options:
|
||||
- "Use defaults (Recommended)"
|
||||
- "Customize settings"
|
||||
|
||||
If customize:
|
||||
- `PR_REVIEW_CONFIDENCE_THRESHOLD` (default: 0.5)
|
||||
- `PR_REVIEW_AUTO_SUBMIT` (default: false)
|
||||
|
||||
---
|
||||
|
||||
## Complete
|
||||
|
||||
```
|
||||
╔══════════════════════════════════════════════════════════════╗
|
||||
║ PROJECT CONFIGURED ║
|
||||
╠══════════════════════════════════════════════════════════════╣
|
||||
║ Organization: <ORG_NAME> ║
|
||||
║ Repository: <REPO_NAME> ║
|
||||
║ Config file: ./.env ║
|
||||
╚══════════════════════════════════════════════════════════════╝
|
||||
|
||||
Ready to review PRs:
|
||||
• /pr-review <number> - Full multi-agent review
|
||||
• /pr-summary <number> - Quick summary
|
||||
• /pr-findings <number> - List findings
|
||||
```
|
||||
93
plugins/pr-review/commands/project-sync.md
Normal file
93
plugins/pr-review/commands/project-sync.md
Normal file
@@ -0,0 +1,93 @@
|
||||
---
|
||||
description: Sync project configuration with current git remote - use after changing repository location
|
||||
---
|
||||
|
||||
# Project Sync (PR Review)
|
||||
|
||||
Updates project configuration when the git remote URL has changed.
|
||||
|
||||
**Use this when:**
|
||||
- Repository was moved to a different organization
|
||||
- Repository was renamed
|
||||
- Git remote URL changed
|
||||
- SessionStart hook detected a mismatch
|
||||
|
||||
---
|
||||
|
||||
## Step 1: Verify System Configuration
|
||||
|
||||
```bash
|
||||
cat ~/.config/claude/gitea.env 2>/dev/null | grep -v "^#" | grep -v "PASTE_YOUR" | grep "GITEA_API_TOKEN=" && echo "SYSTEM_OK" || echo "SYSTEM_MISSING"
|
||||
```
|
||||
|
||||
**If SYSTEM_MISSING:** Run `/initial-setup` first.
|
||||
|
||||
---
|
||||
|
||||
## Step 2: Read Current .env
|
||||
|
||||
```bash
|
||||
cat .env 2>/dev/null
|
||||
```
|
||||
|
||||
Extract `GITEA_ORG` and `GITEA_REPO` values.
|
||||
|
||||
**If missing:** Redirect to `/project-init`.
|
||||
|
||||
---
|
||||
|
||||
## Step 3: Detect Git Remote
|
||||
|
||||
```bash
|
||||
git remote get-url origin 2>/dev/null
|
||||
```
|
||||
|
||||
Extract organization and repository from URL.
|
||||
|
||||
---
|
||||
|
||||
## Step 4: Compare Values
|
||||
|
||||
| Scenario | Action |
|
||||
|----------|--------|
|
||||
| **Match** | "Configuration in sync" - exit |
|
||||
| **Mismatch** | Show diff, proceed to validation |
|
||||
|
||||
---
|
||||
|
||||
## Step 5: Validate via Gitea API
|
||||
|
||||
```bash
|
||||
source ~/.config/claude/gitea.env
|
||||
curl -s -o /dev/null -w "%{http_code}" -H "Authorization: token $GITEA_API_TOKEN" "$GITEA_API_URL/repos/<NEW_ORG>/<NEW_REPO>"
|
||||
```
|
||||
|
||||
| Code | Action |
|
||||
|------|--------|
|
||||
| **200** | Verified - proceed to update |
|
||||
| **404** | Not found - ask to confirm |
|
||||
| **401/403** | Permission issue - warn |
|
||||
|
||||
---
|
||||
|
||||
## Step 6: Confirm and Update
|
||||
|
||||
Use AskUserQuestion to confirm, then update .env:
|
||||
|
||||
```bash
|
||||
sed -i 's/^GITEA_ORG=.*/GITEA_ORG=<NEW_ORG>/' .env
|
||||
sed -i 's/^GITEA_REPO=.*/GITEA_REPO=<NEW_REPO>/' .env
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 7: Confirm Success
|
||||
|
||||
```
|
||||
╔══════════════════════════════════════════════════════════════╗
|
||||
║ CONFIGURATION UPDATED ║
|
||||
╠══════════════════════════════════════════════════════════════╣
|
||||
║ Organization: <NEW_ORG> ║
|
||||
║ Repository: <NEW_REPO> ║
|
||||
╚══════════════════════════════════════════════════════════════╝
|
||||
```
|
||||
10
plugins/pr-review/hooks/hooks.json
Normal file
10
plugins/pr-review/hooks/hooks.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"hooks": {
|
||||
"SessionStart": [
|
||||
{
|
||||
"type": "prompt",
|
||||
"prompt": "Perform silent startup checks:\n\n1. Check if MCP venvs exist at the installed marketplace location. If the marketplace is installed but venvs are missing, warn the user to run setup.sh from that location.\n\n2. Check if the project git remote matches .env configuration (GITEA_ORG/GITEA_REPO). If mismatch, warn about /project-sync.\n\nStay silent if all checks pass or not applicable. Be quick and non-blocking."
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -6,8 +6,8 @@
|
||||
"name": "Leo Miranda",
|
||||
"email": "leobmiranda@gmail.com"
|
||||
},
|
||||
"homepage": "https://gitea.hotserv.cloud/personal-projects/support-claude-mktplace/src/branch/main/plugins/project-hygiene/README.md",
|
||||
"repository": "https://gitea.hotserv.cloud/personal-projects/support-claude-mktplace.git",
|
||||
"homepage": "https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace/src/branch/main/plugins/project-hygiene/README.md",
|
||||
"repository": "https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace.git",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"cleanup",
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"name": "projman",
|
||||
"version": "3.0.0",
|
||||
"version": "3.1.0",
|
||||
"description": "Sprint planning and project management with Gitea integration",
|
||||
"author": {
|
||||
"name": "Leo Miranda",
|
||||
"email": "leobmiranda@gmail.com"
|
||||
},
|
||||
"homepage": "https://gitea.hotserv.cloud/personal-projects/support-claude-mktplace/src/branch/main/plugins/projman/README.md",
|
||||
"repository": "https://gitea.hotserv.cloud/personal-projects/support-claude-mktplace.git",
|
||||
"homepage": "https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace/src/branch/main/plugins/projman/README.md",
|
||||
"repository": "https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace.git",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"project-management",
|
||||
@@ -17,5 +17,5 @@
|
||||
"lessons-learned"
|
||||
],
|
||||
"commands": ["./commands/"],
|
||||
"agents": ["./agents/"]
|
||||
"mcpServers": ["./.mcp.json"]
|
||||
}
|
||||
|
||||
@@ -1,39 +1,10 @@
|
||||
# Configuration Guide - Projman Plugin
|
||||
# Configuration - Projman Plugin
|
||||
|
||||
For comprehensive configuration instructions, see the **[Centralized Configuration Guide](../../docs/CONFIGURATION.md)**.
|
||||
See **[docs/CONFIGURATION.md](../../docs/CONFIGURATION.md)** for complete setup instructions.
|
||||
|
||||
## Quick Reference
|
||||
## Quick Commands
|
||||
|
||||
### Required Configuration
|
||||
|
||||
**System-level** (`~/.config/claude/gitea.env`):
|
||||
```bash
|
||||
GITEA_URL=https://gitea.example.com
|
||||
GITEA_TOKEN=your_token
|
||||
GITEA_ORG=your_organization
|
||||
```
|
||||
|
||||
**Project-level** (`.env` in project root):
|
||||
```bash
|
||||
GITEA_REPO=your-repo-name
|
||||
/initial-setup # First time on this machine
|
||||
/project-init # New project (system already configured)
|
||||
```
|
||||
|
||||
### MCP Server Installation
|
||||
|
||||
```bash
|
||||
cd mcp-servers/gitea
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
### Verification
|
||||
|
||||
```bash
|
||||
/initial-setup
|
||||
/labels-sync
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
For detailed setup instructions, troubleshooting, and security best practices, see [docs/CONFIGURATION.md](../../docs/CONFIGURATION.md).
|
||||
|
||||
@@ -25,57 +25,38 @@ Projman transforms a proven 15-sprint workflow into a distributable Claude Code
|
||||
- Python 3.10+ installed
|
||||
- Git repository initialized
|
||||
|
||||
### 2. Install MCP Server
|
||||
### 2. Run Interactive Setup
|
||||
|
||||
The plugin bundles the Gitea MCP server:
|
||||
The setup wizard handles everything:
|
||||
|
||||
```bash
|
||||
cd plugins/projman/mcp-servers/gitea
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate # or .venv\Scripts\activate on Windows
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
See [CONFIGURATION.md](./CONFIGURATION.md) for detailed setup instructions.
|
||||
|
||||
### 3. Configure System-Level Settings
|
||||
|
||||
Create system-wide configuration with your Gitea credentials:
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.config/claude
|
||||
|
||||
# Gitea configuration
|
||||
cat > ~/.config/claude/gitea.env << 'EOF'
|
||||
GITEA_URL=https://gitea.example.com
|
||||
GITEA_TOKEN=your_gitea_token_here
|
||||
GITEA_ORG=your_organization
|
||||
EOF
|
||||
|
||||
# Secure the file
|
||||
chmod 600 ~/.config/claude/gitea.env
|
||||
```
|
||||
|
||||
### 4. Configure Project-Level Settings
|
||||
|
||||
In your project root directory, create a `.env` file:
|
||||
|
||||
```bash
|
||||
# In your project directory
|
||||
cat > .env << 'EOF'
|
||||
GITEA_REPO=your-repo-name
|
||||
EOF
|
||||
```
|
||||
|
||||
### 5. Run Initial Setup
|
||||
|
||||
```bash
|
||||
/initial-setup
|
||||
```
|
||||
|
||||
### 6. Start Planning!
|
||||
This will:
|
||||
- Set up the MCP server (Python venv + dependencies)
|
||||
- Create system config (`~/.config/claude/gitea.env`)
|
||||
- Guide you through adding your Gitea token
|
||||
- Detect and validate your repository via API
|
||||
- Create project config (`.env`)
|
||||
|
||||
```bash
|
||||
**For new projects** (when system is already configured):
|
||||
|
||||
```
|
||||
/project-init
|
||||
```
|
||||
|
||||
**After moving a repository:**
|
||||
|
||||
```
|
||||
/project-sync
|
||||
```
|
||||
|
||||
See [docs/CONFIGURATION.md](../../docs/CONFIGURATION.md) for detailed instructions.
|
||||
|
||||
### 3. Start Planning!
|
||||
|
||||
```
|
||||
/sprint-plan
|
||||
```
|
||||
|
||||
@@ -164,15 +145,42 @@ Synchronize label taxonomy from Gitea.
|
||||
- When new labels are added to Gitea
|
||||
|
||||
### `/initial-setup`
|
||||
Run initial setup for a new project.
|
||||
Full interactive setup wizard.
|
||||
|
||||
**What it does:**
|
||||
- Validates Gitea MCP server connection
|
||||
- Tests credential configuration
|
||||
- Syncs label taxonomy
|
||||
- Creates required directory structure
|
||||
- Checks Python version (requires 3.10+)
|
||||
- Sets up MCP server virtual environment
|
||||
- Creates system-level config (`~/.config/claude/gitea.env`)
|
||||
- Guides token setup (manual entry for security)
|
||||
- Detects and validates repository via Gitea API
|
||||
- Creates project-level config (`.env` with GITEA_ORG, GITEA_REPO)
|
||||
|
||||
**When to use:** First time setting up projman for a project
|
||||
**When to use:** First time on a new machine
|
||||
|
||||
### `/project-init`
|
||||
Quick project setup (assumes system config exists).
|
||||
|
||||
**What it does:**
|
||||
- Verifies system configuration exists
|
||||
- Detects organization and repository from git remote
|
||||
- Validates via Gitea API
|
||||
- Creates project `.env` file
|
||||
|
||||
**When to use:** Starting work on a new project
|
||||
|
||||
### `/project-sync`
|
||||
Sync configuration with current git remote.
|
||||
|
||||
**What it does:**
|
||||
- Compares .env values with git remote URL
|
||||
- Validates new repository via Gitea API
|
||||
- Updates .env if mismatch detected
|
||||
|
||||
**When to use:** After moving or renaming a repository
|
||||
|
||||
**Note:** A SessionStart hook automatically checks for:
|
||||
1. Missing MCP venvs at the installed marketplace location (warns to run setup.sh)
|
||||
2. Repository config mismatches (warns to run `/project-sync`)
|
||||
|
||||
### `/review`
|
||||
Pre-sprint-close code quality review.
|
||||
@@ -226,6 +234,39 @@ Generate tests for specified code.
|
||||
|
||||
**When to use:** When adding new code that needs test coverage
|
||||
|
||||
## Debug Workflow Commands
|
||||
|
||||
These commands enable a cross-repository debugging workflow between your project and the marketplace.
|
||||
|
||||
### `/debug-report`
|
||||
Run diagnostics and create structured issue in marketplace repository.
|
||||
|
||||
**What it does:**
|
||||
- Runs MCP tool diagnostics (validate_repo_org, get_labels, list_issues, etc.)
|
||||
- Captures error messages and hypothesis
|
||||
- Creates a structured issue in the marketplace repository
|
||||
- Tags with `Source: Diagnostic` label
|
||||
|
||||
**When to use:** When MCP tools fail in your project, run this to report the issue to the marketplace for investigation.
|
||||
|
||||
### `/debug-review`
|
||||
Investigate diagnostic issues and propose fixes with human approval.
|
||||
|
||||
**What it does:**
|
||||
- Fetches open diagnostic issues from marketplace
|
||||
- Lets you select which issue to investigate
|
||||
- Maps errors to relevant source files
|
||||
- Reads code and analyzes root cause
|
||||
- Proposes fixes with THREE mandatory approval gates
|
||||
- Creates PR with fix after approval
|
||||
|
||||
**Approval Gates:**
|
||||
1. Analysis confirmation - Does the investigation match your understanding?
|
||||
2. Fix approach - Proceed with proposed changes?
|
||||
3. PR creation - Create pull request?
|
||||
|
||||
**When to use:** In the marketplace repo, to investigate and fix issues reported by `/debug-report`.
|
||||
|
||||
## Code Quality Commands
|
||||
|
||||
The `/review` and `/test-check` commands complement the Executor agent by catching issues before work is marked complete. Run both commands before `/sprint-close` for a complete quality check.
|
||||
@@ -441,9 +482,13 @@ projman/
|
||||
│ ├── sprint-close.md
|
||||
│ ├── labels-sync.md
|
||||
│ ├── initial-setup.md
|
||||
│ ├── project-init.md
|
||||
│ ├── project-sync.md
|
||||
│ ├── review.md
|
||||
│ ├── test-check.md
|
||||
│ └── test-gen.md
|
||||
│ ├── test-gen.md
|
||||
│ ├── debug-report.md
|
||||
│ └── debug-review.md
|
||||
├── agents/ # Agent prompts
|
||||
│ ├── planner.md
|
||||
│ ├── orchestrator.md
|
||||
|
||||
262
plugins/projman/commands/debug-report.md
Normal file
262
plugins/projman/commands/debug-report.md
Normal file
@@ -0,0 +1,262 @@
|
||||
---
|
||||
description: Run diagnostics and create structured issue in marketplace repository
|
||||
---
|
||||
|
||||
# Debug Report
|
||||
|
||||
Run diagnostic checks on projman MCP tools and create a structured issue in the marketplace repository for investigation.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Your project `.env` must have:
|
||||
|
||||
```env
|
||||
PROJMAN_MARKETPLACE_REPO=personal-projects/leo-claude-mktplace
|
||||
```
|
||||
|
||||
If not configured, ask the user for the marketplace repository path.
|
||||
|
||||
## CRITICAL: Execution Steps
|
||||
|
||||
You MUST follow these steps in order. Do NOT skip any step.
|
||||
|
||||
### Step 1: Gather Project Context
|
||||
|
||||
Run these Bash commands to capture project information:
|
||||
|
||||
```bash
|
||||
# Get git remote URL
|
||||
git remote get-url origin
|
||||
|
||||
# Get current branch
|
||||
git branch --show-current
|
||||
|
||||
# Get working directory
|
||||
pwd
|
||||
```
|
||||
|
||||
Parse the git remote to extract `REPO_NAME` in `owner/repo` format.
|
||||
|
||||
Store all values:
|
||||
- `PROJECT_REPO`: The detected owner/repo
|
||||
- `GIT_REMOTE`: Full git remote URL
|
||||
- `CURRENT_BRANCH`: Current branch name
|
||||
- `WORKING_DIR`: Current working directory
|
||||
|
||||
### Step 2: Read Marketplace Configuration
|
||||
|
||||
```bash
|
||||
grep PROJMAN_MARKETPLACE_REPO .env
|
||||
```
|
||||
|
||||
Store as `MARKETPLACE_REPO`. If not found, ask the user.
|
||||
|
||||
### Step 3: Run Diagnostic Suite
|
||||
|
||||
Run each MCP tool with explicit `repo` parameter. Record success/failure and full response.
|
||||
|
||||
**Test 1: validate_repo_org**
|
||||
```
|
||||
mcp__plugin_projman_gitea__validate_repo_org(repo=PROJECT_REPO)
|
||||
```
|
||||
Expected: `{is_organization: true/false}`
|
||||
|
||||
**Test 2: get_labels**
|
||||
```
|
||||
mcp__plugin_projman_gitea__get_labels(repo=PROJECT_REPO)
|
||||
```
|
||||
Expected: `{organization: [...], repository: [...], total_count: N}`
|
||||
|
||||
**Test 3: list_issues**
|
||||
```
|
||||
mcp__plugin_projman_gitea__list_issues(repo=PROJECT_REPO, state="open")
|
||||
```
|
||||
Expected: Array of issues
|
||||
|
||||
**Test 4: list_milestones**
|
||||
```
|
||||
mcp__plugin_projman_gitea__list_milestones(repo=PROJECT_REPO)
|
||||
```
|
||||
Expected: Array of milestones
|
||||
|
||||
**Test 5: suggest_labels**
|
||||
```
|
||||
mcp__plugin_projman_gitea__suggest_labels(context="Test bug fix for authentication")
|
||||
```
|
||||
Expected: Array of label names matching repo's format
|
||||
|
||||
For each test, record:
|
||||
- Tool name
|
||||
- Exact parameters used
|
||||
- Status: PASS or FAIL
|
||||
- Response or error message
|
||||
|
||||
### Step 4: Analyze Results
|
||||
|
||||
Count failures and categorize errors:
|
||||
|
||||
| Category | Indicators |
|
||||
|----------|------------|
|
||||
| Parameter Format | "owner/repo format", "missing parameter" |
|
||||
| Authentication | "401", "403", "unauthorized" |
|
||||
| Not Found | "404", "not found" |
|
||||
| Network | "connection", "timeout", "ECONNREFUSED" |
|
||||
| Logic | Unexpected response format, wrong data |
|
||||
|
||||
For each failure, write a hypothesis about the likely cause.
|
||||
|
||||
### Step 5: Generate Issue Content
|
||||
|
||||
Use this exact template:
|
||||
|
||||
```markdown
|
||||
## Diagnostic Report
|
||||
|
||||
**Generated**: [ISO timestamp]
|
||||
**Command Tested**: [What the user was trying to run, or "general diagnostic"]
|
||||
**Reporter**: Claude Code via /debug-report
|
||||
|
||||
## Project Context
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| Repository | `[PROJECT_REPO]` |
|
||||
| Git Remote | `[GIT_REMOTE]` |
|
||||
| Working Directory | `[WORKING_DIR]` |
|
||||
| Current Branch | `[CURRENT_BRANCH]` |
|
||||
|
||||
## Diagnostic Results
|
||||
|
||||
### Test 1: validate_repo_org
|
||||
|
||||
**Call**: `validate_repo_org(repo="[PROJECT_REPO]")`
|
||||
**Status**: [PASS/FAIL]
|
||||
**Response**:
|
||||
```json
|
||||
[full response or error]
|
||||
```
|
||||
|
||||
### Test 2: get_labels
|
||||
|
||||
**Call**: `get_labels(repo="[PROJECT_REPO]")`
|
||||
**Status**: [PASS/FAIL]
|
||||
**Response**:
|
||||
```json
|
||||
[full response or error - truncate if very long]
|
||||
```
|
||||
|
||||
[... repeat for each test ...]
|
||||
|
||||
## Summary
|
||||
|
||||
- **Total Tests**: 5
|
||||
- **Passed**: [N]
|
||||
- **Failed**: [N]
|
||||
|
||||
### Failed Tools
|
||||
|
||||
[List each failed tool with its error]
|
||||
|
||||
### Error Category
|
||||
|
||||
[Check applicable categories]
|
||||
|
||||
### Hypothesis
|
||||
|
||||
[Your analysis of what's wrong and why]
|
||||
|
||||
### Suggested Investigation
|
||||
|
||||
1. [First file/function to check]
|
||||
2. [Second file/function to check]
|
||||
3. [etc.]
|
||||
|
||||
## Reproduction Steps
|
||||
|
||||
1. Navigate to `[WORKING_DIR]`
|
||||
2. Run `[command that was being tested]`
|
||||
3. Observe error at step [X]
|
||||
|
||||
---
|
||||
|
||||
*Generated by /debug-report - Labels: Type: Bug, Source: Diagnostic, Agent: Claude*
|
||||
```
|
||||
|
||||
### Step 6: Create Issue in Marketplace
|
||||
|
||||
```
|
||||
mcp__plugin_projman_gitea__create_issue(
|
||||
repo=MARKETPLACE_REPO,
|
||||
title="[Diagnostic] [summary of main failure]",
|
||||
body=[generated content from Step 5],
|
||||
labels=["Type: Bug", "Source: Diagnostic", "Agent: Claude"]
|
||||
)
|
||||
```
|
||||
|
||||
If labels don't exist, create issue without labels.
|
||||
|
||||
### Step 7: Report to User
|
||||
|
||||
Display summary:
|
||||
|
||||
```
|
||||
Debug Report Complete
|
||||
=====================
|
||||
|
||||
Project: [PROJECT_REPO]
|
||||
Tests Run: 5
|
||||
Passed: [N]
|
||||
Failed: [N]
|
||||
|
||||
Failed Tools:
|
||||
- [tool1]: [brief error]
|
||||
- [tool2]: [brief error]
|
||||
|
||||
Issue Created: [issue URL]
|
||||
|
||||
Next Steps:
|
||||
1. Switch to marketplace repo: cd [marketplace path]
|
||||
2. Run: /debug-review
|
||||
3. Select issue #[N] to investigate
|
||||
```
|
||||
|
||||
## DO NOT
|
||||
|
||||
- **DO NOT** attempt to fix anything - only report
|
||||
- **DO NOT** create issues if all tests pass (just report success)
|
||||
- **DO NOT** skip any diagnostic test
|
||||
- **DO NOT** call MCP tools without the `repo` parameter
|
||||
- **DO NOT** ask user questions during execution - run autonomously
|
||||
|
||||
## If All Tests Pass
|
||||
|
||||
If all 5 tests pass, report success without creating an issue:
|
||||
|
||||
```
|
||||
Debug Report Complete
|
||||
=====================
|
||||
|
||||
Project: [PROJECT_REPO]
|
||||
Tests Run: 5
|
||||
Passed: 5
|
||||
Failed: 0
|
||||
|
||||
All diagnostics passed. No issues to report.
|
||||
|
||||
If you're experiencing a specific problem, please describe it
|
||||
and I can create a manual bug report.
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**PROJMAN_MARKETPLACE_REPO not configured**
|
||||
- Ask user: "What is the marketplace repository? (e.g., personal-projects/leo-claude-mktplace)"
|
||||
- Store for this session and remind user to add to .env
|
||||
|
||||
**Cannot detect project repository**
|
||||
- Check if in a git repository: `git rev-parse --git-dir`
|
||||
- If not a git repo, ask user for the repository path
|
||||
|
||||
**MCP tools not available**
|
||||
- The projman plugin may not be properly installed
|
||||
- Check if .mcp.json exists and is configured
|
||||
389
plugins/projman/commands/debug-review.md
Normal file
389
plugins/projman/commands/debug-review.md
Normal file
@@ -0,0 +1,389 @@
|
||||
---
|
||||
description: Investigate diagnostic issues and propose fixes with human approval
|
||||
---
|
||||
|
||||
# Debug Review
|
||||
|
||||
Investigate diagnostic issues created by `/debug-report`, read relevant code, and propose fixes with human approval at each step.
|
||||
|
||||
## CRITICAL: This Command Requires Human Approval
|
||||
|
||||
This command has THREE mandatory approval gates. You MUST stop and wait for user confirmation at each gate before proceeding.
|
||||
|
||||
## Execution Steps
|
||||
|
||||
### Step 1: Detect Repository
|
||||
|
||||
Run Bash to get the current repository:
|
||||
|
||||
```bash
|
||||
git remote get-url origin
|
||||
```
|
||||
|
||||
Parse to extract `REPO_NAME` in `owner/repo` format.
|
||||
|
||||
### Step 2: Fetch Diagnostic Issues
|
||||
|
||||
```
|
||||
mcp__plugin_projman_gitea__list_issues(
|
||||
repo=REPO_NAME,
|
||||
state="open",
|
||||
labels=["Source: Diagnostic"]
|
||||
)
|
||||
```
|
||||
|
||||
If no issues with that label, try without label filter and look for issues with "[Diagnostic]" in title.
|
||||
|
||||
### Step 3: Display Issue List
|
||||
|
||||
Show the user available issues:
|
||||
|
||||
```
|
||||
Debug Review
|
||||
============
|
||||
|
||||
Open Diagnostic Issues:
|
||||
|
||||
#80 - [Diagnostic] get_labels fails without repo parameter
|
||||
Created: 2026-01-21 | Labels: Type: Bug, Source: Diagnostic
|
||||
|
||||
#77 - [Diagnostic] MCP tools require explicit repo parameter
|
||||
Created: 2026-01-21 | Labels: Type: Bug, Source: Diagnostic
|
||||
|
||||
No diagnostic issues? Showing recent bugs:
|
||||
|
||||
#75 - [Bug] Some other issue
|
||||
Created: 2026-01-20
|
||||
```
|
||||
|
||||
### Step 4: User Selects Issue
|
||||
|
||||
Use AskUserQuestion:
|
||||
|
||||
```
|
||||
Which issue would you like to investigate?
|
||||
Options: [List issue numbers]
|
||||
```
|
||||
|
||||
Wait for user selection.
|
||||
|
||||
### Step 5: Fetch Full Issue Details
|
||||
|
||||
```
|
||||
mcp__plugin_projman_gitea__get_issue(repo=REPO_NAME, issue_number=SELECTED)
|
||||
```
|
||||
|
||||
### Step 6: Parse Diagnostic Report
|
||||
|
||||
Extract from the issue body:
|
||||
|
||||
1. **Failed Tools**: Which MCP tools failed
|
||||
2. **Error Messages**: Exact error text
|
||||
3. **Hypothesis**: Reporter's analysis
|
||||
4. **Suggested Investigation**: Files to check
|
||||
5. **Project Context**: Repo, branch, cwd where error occurred
|
||||
|
||||
If the issue doesn't follow the diagnostic template, extract what information is available.
|
||||
|
||||
### Step 7: Map Errors to Code Files
|
||||
|
||||
Use this mapping to identify relevant files:
|
||||
|
||||
**By Tool Name:**
|
||||
| Tool | Primary Files |
|
||||
|------|---------------|
|
||||
| `validate_repo_org` | `mcp-servers/gitea/mcp_server/gitea_client.py` |
|
||||
| `get_labels` | `mcp-servers/gitea/mcp_server/tools/labels.py` |
|
||||
| `suggest_labels` | `mcp-servers/gitea/mcp_server/tools/labels.py` |
|
||||
| `list_issues` | `mcp-servers/gitea/mcp_server/tools/issues.py` |
|
||||
| `create_issue` | `mcp-servers/gitea/mcp_server/tools/issues.py` |
|
||||
| `list_milestones` | `mcp-servers/gitea/mcp_server/gitea_client.py` |
|
||||
|
||||
**By Error Pattern:**
|
||||
| Error Contains | Check Files |
|
||||
|----------------|-------------|
|
||||
| "owner/repo format" | `config.py`, `gitea_client.py` |
|
||||
| "404" + "orgs" | `gitea_client.py` (is_org_repo method) |
|
||||
| "401", "403" | `config.py` (token loading) |
|
||||
| "No repository" | Command `.md` file (repo detection step) |
|
||||
|
||||
**By Command:**
|
||||
| Command | Documentation File |
|
||||
|---------|-------------------|
|
||||
| `/labels-sync` | `plugins/projman/commands/labels-sync.md` |
|
||||
| `/sprint-plan` | `plugins/projman/commands/sprint-plan.md` |
|
||||
| `/sprint-start` | `plugins/projman/commands/sprint-start.md` |
|
||||
| `/debug-report` | `plugins/projman/commands/debug-report.md` |
|
||||
|
||||
### Step 8: Read Relevant Files (MANDATORY)
|
||||
|
||||
You MUST read the identified files before proposing any fix.
|
||||
|
||||
For each relevant file:
|
||||
1. Read the file using the Read tool
|
||||
2. Find the specific function/method mentioned in the error
|
||||
3. Understand the code path that leads to the error
|
||||
4. Note any related code that might be affected
|
||||
|
||||
Display snippets of relevant code to the user:
|
||||
|
||||
```
|
||||
Reading relevant files...
|
||||
|
||||
┌─ mcp-servers/gitea/mcp_server/tools/labels.py (lines 29-40) ────────┐
|
||||
│ │
|
||||
│ async def get_labels(self, repo: Optional[str] = None): │
|
||||
│ target_repo = repo or self.gitea.repo │
|
||||
│ if not target_repo or '/' not in target_repo: │
|
||||
│ raise ValueError("Use 'owner/repo' format...") │
|
||||
│ │
|
||||
└──────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Step 9: Present Investigation Summary
|
||||
|
||||
Summarize what you found:
|
||||
|
||||
```
|
||||
Investigation Summary
|
||||
=====================
|
||||
|
||||
ISSUE: #80 - get_labels fails without repo parameter
|
||||
|
||||
FAILED TOOLS:
|
||||
• get_labels - "Use 'owner/repo' format"
|
||||
|
||||
CODE ANALYSIS:
|
||||
|
||||
1. labels.py:get_labels() requires repo parameter
|
||||
- Line 30: `target_repo = repo or self.gitea.repo`
|
||||
- Line 31-32: Raises ValueError if no repo
|
||||
|
||||
2. labels-sync.md documents Step 1 for repo detection
|
||||
- Lines 13-26: Instructs to run `git remote get-url origin`
|
||||
- This step may not be followed by executing Claude
|
||||
|
||||
ROOT CAUSE HYPOTHESIS:
|
||||
|
||||
The command documentation (labels-sync.md) correctly instructs
|
||||
repo detection, but the executing Claude may be skipping Step 1
|
||||
and calling MCP tools directly.
|
||||
|
||||
Evidence:
|
||||
• Error indicates repo parameter was not passed
|
||||
• labels-sync.md has correct instructions
|
||||
• MCP server cannot auto-detect (sandboxed environment)
|
||||
|
||||
LIKELY FIX:
|
||||
|
||||
Option A: Make Step 1 more prominent in labels-sync.md
|
||||
Option B: Add validation that repo was detected before proceeding
|
||||
Option C: [Other based on analysis]
|
||||
```
|
||||
|
||||
## APPROVAL GATE 1
|
||||
|
||||
```
|
||||
Does this analysis match your understanding of the problem?
|
||||
|
||||
[Y] Yes, proceed to propose fix
|
||||
[N] No, let me clarify
|
||||
[R] Read more files first
|
||||
```
|
||||
|
||||
**STOP HERE AND WAIT FOR USER RESPONSE**
|
||||
|
||||
Do NOT proceed until user approves.
|
||||
|
||||
### Step 10: Propose Fix Approach
|
||||
|
||||
Based on the analysis, propose a specific fix:
|
||||
|
||||
```
|
||||
Proposed Fix
|
||||
============
|
||||
|
||||
APPROACH: [A/B/C from above]
|
||||
|
||||
CHANGES NEEDED:
|
||||
|
||||
1. File: plugins/projman/commands/labels-sync.md
|
||||
Change: Add warning box after Step 1 emphasizing repo must be detected
|
||||
|
||||
2. File: [if applicable]
|
||||
Change: [description]
|
||||
|
||||
RATIONALE:
|
||||
|
||||
[Explain why this fix addresses the root cause]
|
||||
|
||||
RISKS:
|
||||
|
||||
[Any potential issues with this approach]
|
||||
```
|
||||
|
||||
## APPROVAL GATE 2
|
||||
|
||||
```
|
||||
Proceed with this fix approach?
|
||||
|
||||
[Y] Yes, implement it
|
||||
[N] No, try different approach
|
||||
[M] Modify the approach (tell me what to change)
|
||||
```
|
||||
|
||||
**STOP HERE AND WAIT FOR USER RESPONSE**
|
||||
|
||||
Do NOT implement until user approves.
|
||||
|
||||
### Step 11: Implement Fix
|
||||
|
||||
Only after user approves:
|
||||
|
||||
1. Create feature branch:
|
||||
```bash
|
||||
git checkout -b fix/issue-[NUMBER]-[brief-description]
|
||||
```
|
||||
|
||||
2. Make the code changes using Edit tool
|
||||
|
||||
3. Run relevant tests if they exist:
|
||||
```bash
|
||||
cd mcp-servers/gitea && .venv/bin/python -m pytest tests/ -v
|
||||
```
|
||||
|
||||
4. Show the changes to user:
|
||||
```bash
|
||||
git diff
|
||||
```
|
||||
|
||||
### Step 12: Present Changes
|
||||
|
||||
```
|
||||
Changes Implemented
|
||||
===================
|
||||
|
||||
Branch: fix/issue-80-labels-sync-instructions
|
||||
|
||||
Files Modified:
|
||||
• plugins/projman/commands/labels-sync.md (+15, -3)
|
||||
|
||||
Diff Summary:
|
||||
[Show git diff output]
|
||||
|
||||
Test Results:
|
||||
• 23 passed, 0 failed (or N/A if no tests)
|
||||
```
|
||||
|
||||
## APPROVAL GATE 3
|
||||
|
||||
```
|
||||
Create PR with these changes?
|
||||
|
||||
[Y] Yes, create PR
|
||||
[N] No, I want to modify something
|
||||
[D] Discard changes
|
||||
```
|
||||
|
||||
**STOP HERE AND WAIT FOR USER RESPONSE**
|
||||
|
||||
Do NOT create PR until user approves.
|
||||
|
||||
### Step 13: Create PR
|
||||
|
||||
Only after user approves:
|
||||
|
||||
1. Commit changes:
|
||||
```bash
|
||||
git add -A
|
||||
git commit -m "fix: [description]
|
||||
|
||||
[Longer explanation]
|
||||
|
||||
Fixes #[ISSUE_NUMBER]
|
||||
|
||||
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>"
|
||||
```
|
||||
|
||||
2. Push branch:
|
||||
```bash
|
||||
git push -u origin fix/issue-[NUMBER]-[brief-description]
|
||||
```
|
||||
|
||||
3. Create PR via API or MCP tools
|
||||
|
||||
4. Add comment to original issue:
|
||||
```
|
||||
mcp__plugin_projman_gitea__add_comment(
|
||||
repo=REPO_NAME,
|
||||
issue_number=ISSUE_NUMBER,
|
||||
comment="Fix proposed in PR #[PR_NUMBER]\n\nChanges:\n- [summary]\n\nPlease test after merge and report back."
|
||||
)
|
||||
```
|
||||
|
||||
### Step 14: Report Completion
|
||||
|
||||
```
|
||||
Debug Review Complete
|
||||
=====================
|
||||
|
||||
Issue: #80 - get_labels fails without repo parameter
|
||||
Status: Fix Proposed
|
||||
|
||||
PR Created: #81 - fix: improve labels-sync repo detection instructions
|
||||
URL: http://gitea.hotserv.cloud/.../pulls/81
|
||||
|
||||
Next Steps:
|
||||
1. Review and merge PR #81
|
||||
2. In test project, pull latest plugin version
|
||||
3. Run /debug-report to verify fix
|
||||
4. If passing, close issue #80
|
||||
```
|
||||
|
||||
## DO NOT
|
||||
|
||||
- **DO NOT** skip reading relevant files - this is MANDATORY
|
||||
- **DO NOT** proceed past approval gates without user confirmation
|
||||
- **DO NOT** guess at fixes without evidence from code
|
||||
- **DO NOT** close issues - let user verify fix works first
|
||||
- **DO NOT** commit directly to development or main branches
|
||||
|
||||
## If Investigation Finds No Bug
|
||||
|
||||
Sometimes investigation reveals the issue is:
|
||||
- User error (didn't follow documented steps)
|
||||
- Configuration issue (missing .env vars)
|
||||
- Already fixed in a newer version
|
||||
|
||||
In this case:
|
||||
|
||||
```
|
||||
Investigation Summary
|
||||
=====================
|
||||
|
||||
FINDING: This does not appear to be a code bug.
|
||||
|
||||
ANALYSIS:
|
||||
[Explanation of what you found]
|
||||
|
||||
RECOMMENDATION:
|
||||
[ ] Close issue as "not a bug" - user error
|
||||
[ ] Close issue as "duplicate" of #[X]
|
||||
[ ] Add documentation to prevent confusion
|
||||
[ ] Other: [specify]
|
||||
|
||||
Would you like me to add a comment explaining this finding?
|
||||
```
|
||||
|
||||
## Error-to-File Quick Reference
|
||||
|
||||
```
|
||||
Error Message → File to Check
|
||||
─────────────────────────────────────────────────────────────────
|
||||
"Use 'owner/repo' format" → config.py, gitea_client.py
|
||||
"404 Client Error.*orgs" → gitea_client.py (_is_organization)
|
||||
"No repository specified" → Command .md file (Step 1)
|
||||
"401 Unauthorized" → config.py (token loading)
|
||||
"labels not found" → labels.py, gitea_client.py
|
||||
"create local.*file" → Command .md file (DO NOT section)
|
||||
```
|
||||
@@ -1,114 +1,463 @@
|
||||
---
|
||||
description: Run initial setup for projman plugin
|
||||
description: Interactive setup wizard for projman plugin - configures MCP servers, credentials, and project settings
|
||||
---
|
||||
|
||||
# Initial Setup
|
||||
# Initial Setup Wizard
|
||||
|
||||
Run the installation script to set up the projman plugin.
|
||||
This command guides the user through complete projman setup interactively. It handles both first-time marketplace setup and per-project configuration.
|
||||
|
||||
## What This Does
|
||||
## Important Context
|
||||
|
||||
1. Creates Python virtual environments for MCP servers
|
||||
2. Installs all dependencies
|
||||
3. Creates configuration file templates
|
||||
4. Validates existing configuration
|
||||
5. Validates repository organization
|
||||
6. Syncs label taxonomy
|
||||
7. Reports remaining manual steps
|
||||
- **This command uses Bash, Read, Write, and AskUserQuestion tools** - NOT MCP tools
|
||||
- **MCP tools won't work until after setup + session restart**
|
||||
- **Tokens must be entered manually by the user** for security (not typed into chat)
|
||||
|
||||
## Execution
|
||||
---
|
||||
|
||||
## Quick Path Detection
|
||||
|
||||
**FIRST**, check if system-level setup is already complete:
|
||||
|
||||
```bash
|
||||
cd ${PROJECT_ROOT}
|
||||
./scripts/setup.sh
|
||||
cat ~/.config/claude/gitea.env 2>/dev/null | grep -v "^#" | grep -v "PASTE_YOUR" | grep -v "example.com" | grep "GITEA_API_TOKEN=" && echo "SYSTEM_CONFIGURED" || echo "SYSTEM_NEEDS_SETUP"
|
||||
```
|
||||
|
||||
## Configuration Structure
|
||||
**If SYSTEM_CONFIGURED:**
|
||||
|
||||
The plugin uses a hybrid configuration approach:
|
||||
The system-level configuration already exists. Offer the user a choice:
|
||||
|
||||
**System-Level (credentials):**
|
||||
Use AskUserQuestion:
|
||||
- Question: "System configuration found. What would you like to do?"
|
||||
- Header: "Setup Mode"
|
||||
- Options:
|
||||
- "Quick project setup only (Recommended for new projects)"
|
||||
- "Full setup (re-check everything)"
|
||||
|
||||
**If "Quick project setup":**
|
||||
- Skip directly to **Phase 4: Project-Level Configuration**
|
||||
- This is equivalent to running `/project-init`
|
||||
|
||||
**If "Full setup":**
|
||||
- Continue with Phase 1 below
|
||||
|
||||
**If SYSTEM_NEEDS_SETUP:**
|
||||
- Continue with Phase 1 (full setup required)
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Environment Validation
|
||||
|
||||
### Step 1.1: Check Python Version
|
||||
|
||||
Run this command to verify Python 3.10+ is available:
|
||||
|
||||
```bash
|
||||
python3 --version
|
||||
```
|
||||
~/.config/claude/gitea.env
|
||||
|
||||
**If version is below 3.10:**
|
||||
- Stop setup and inform user: "Python 3.10 or higher is required. Please install it and run /initial-setup again."
|
||||
- Provide installation hints based on OS (apt, brew, etc.)
|
||||
|
||||
**If successful:** Continue to next step.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: MCP Server Setup
|
||||
|
||||
### Step 2.1: Locate the Plugin Installation
|
||||
|
||||
The plugin is installed somewhere on the system. Find the MCP server directory by resolving the path.
|
||||
|
||||
First, identify where this plugin is installed. The MCP server should be accessible via the symlink structure. Look for the gitea MCP server:
|
||||
|
||||
```bash
|
||||
# Find the plugin's mcp-servers directory (search common locations)
|
||||
find ~/.claude ~/.config/claude -name "mcp_server" -path "*gitea*" 2>/dev/null | head -5
|
||||
```
|
||||
Contains API credentials that work across all projects.
|
||||
|
||||
**Project-Level (repository/paths):**
|
||||
If found, extract the parent path (the gitea MCP server root).
|
||||
|
||||
**Alternative:** If the user knows the marketplace location, ask them:
|
||||
|
||||
Use AskUserQuestion:
|
||||
- Question: "Where is the Leo Claude Marketplace installed?"
|
||||
- Options:
|
||||
- "~/.claude/plugins/leo-claude-mktplace" (default Claude plugins location)
|
||||
- "Let me find it automatically"
|
||||
- Other (user provides path)
|
||||
|
||||
### Step 2.2: Check if Virtual Environment Exists
|
||||
|
||||
Once you have the MCP server path (e.g., `/path/to/mcp-servers/gitea`), check for the venv:
|
||||
|
||||
```bash
|
||||
ls -la /path/to/mcp-servers/gitea/.venv/bin/python 2>/dev/null && echo "VENV_EXISTS" || echo "VENV_MISSING"
|
||||
```
|
||||
project-root/.env
|
||||
|
||||
### Step 2.3: Create Virtual Environment (if missing)
|
||||
|
||||
If venv doesn't exist:
|
||||
|
||||
```bash
|
||||
cd /path/to/mcp-servers/gitea && python3 -m venv .venv
|
||||
```
|
||||
Contains project-specific settings like repository name.
|
||||
|
||||
## After Running
|
||||
Then install dependencies:
|
||||
|
||||
Review the output for any manual steps required:
|
||||
```bash
|
||||
cd /path/to/mcp-servers/gitea && source .venv/bin/activate && pip install --upgrade pip && pip install -r requirements.txt && deactivate
|
||||
```
|
||||
|
||||
1. **Configure API credentials** in `~/.config/claude/gitea.env`:
|
||||
**If pip install fails:**
|
||||
- Show the error to the user
|
||||
- Suggest: "Check your internet connection and try again. You can also manually run: `cd /path/to/mcp-servers/gitea && source .venv/bin/activate && pip install -r requirements.txt`"
|
||||
|
||||
### Step 2.4: NetBox MCP Server (Optional)
|
||||
|
||||
Check if the user wants to set up the NetBox MCP server (for cmdb-assistant plugin):
|
||||
|
||||
Use AskUserQuestion:
|
||||
- Question: "Do you want to set up the NetBox MCP server for infrastructure management?"
|
||||
- Options:
|
||||
- "Yes, set up NetBox MCP"
|
||||
- "No, skip NetBox (Recommended if not using cmdb-assistant)"
|
||||
|
||||
If yes, repeat steps 2.2-2.3 for `/path/to/mcp-servers/netbox`.
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: System-Level Configuration
|
||||
|
||||
System configuration is stored in `~/.config/claude/` and contains credentials that work across all projects.
|
||||
|
||||
### Step 3.1: Create Config Directory
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.config/claude
|
||||
```
|
||||
|
||||
### Step 3.2: Check Gitea Configuration
|
||||
|
||||
```bash
|
||||
cat ~/.config/claude/gitea.env 2>/dev/null || echo "FILE_NOT_FOUND"
|
||||
```
|
||||
|
||||
**If file doesn't exist:** Go to Step 3.3 (Create Template)
|
||||
**If file exists:** Read it and check if values are placeholders (contain "example.com" or "your_" or "token_here"). If placeholders, go to Step 3.4 (Update Existing).
|
||||
**If file has real values:** Go to Step 3.5 (Validate).
|
||||
|
||||
### Step 3.3: Create Gitea Configuration Template
|
||||
|
||||
Gather the Gitea server URL from the user.
|
||||
|
||||
Use AskUserQuestion:
|
||||
- Question: "What is your Gitea server URL? (e.g., https://gitea.company.com)"
|
||||
- Header: "Gitea URL"
|
||||
- Options:
|
||||
- "https://gitea.hotserv.cloud" (if this is Leo's setup)
|
||||
- "Other (I'll provide the URL)"
|
||||
|
||||
If "Other", ask the user to type the URL.
|
||||
|
||||
Now create the configuration file with a placeholder for the token:
|
||||
|
||||
```bash
|
||||
cat > ~/.config/claude/gitea.env << 'EOF'
|
||||
# Gitea API Configuration
|
||||
# Generated by /initial-setup
|
||||
# Note: GITEA_ORG is configured per-project in .env
|
||||
|
||||
GITEA_API_URL=<USER_PROVIDED_URL>
|
||||
GITEA_API_TOKEN=PASTE_YOUR_TOKEN_HERE
|
||||
EOF
|
||||
chmod 600 ~/.config/claude/gitea.env
|
||||
```
|
||||
|
||||
Replace `<USER_PROVIDED_URL>` with the actual value from the user.
|
||||
|
||||
### Step 3.4: Token Entry Instructions
|
||||
|
||||
**CRITICAL: Do not ask the user to type the token into chat.**
|
||||
|
||||
Display these instructions clearly:
|
||||
|
||||
---
|
||||
|
||||
**Action Required: Add Your Gitea API Token**
|
||||
|
||||
I've created the configuration file at `~/.config/claude/gitea.env` but you need to add your API token manually for security.
|
||||
|
||||
**Steps:**
|
||||
1. Open the file in your editor:
|
||||
```
|
||||
GITEA_URL=https://gitea.your-company.com
|
||||
GITEA_TOKEN=your-api-token
|
||||
GITEA_ORG=your-organization
|
||||
nano ~/.config/claude/gitea.env
|
||||
```
|
||||
Or use any editor you prefer.
|
||||
|
||||
2. **Configure project settings** in `.env`:
|
||||
```
|
||||
GITEA_REPO=your-repo-name
|
||||
WIKIJS_PROJECT=your-project
|
||||
```
|
||||
2. Generate a Gitea token (if you don't have one):
|
||||
- Go to your Gitea instance → User Icon → Settings
|
||||
- Click "Applications" tab
|
||||
- Under "Manage Access Tokens", click "Generate New Token"
|
||||
- Name it something like "claude-code"
|
||||
- Select permissions: `repo` (all), `read:org`, `read:user`
|
||||
- Click "Generate Token" and copy it immediately
|
||||
|
||||
3. **Run `/labels-sync`** to sync Gitea labels
|
||||
3. Replace `PASTE_YOUR_TOKEN_HERE` with your actual token
|
||||
|
||||
4. **Verify Gitea Wiki** is accessible and has proper structure
|
||||
4. Save the file
|
||||
|
||||
## Pre-Flight Checks
|
||||
---
|
||||
|
||||
The setup script validates:
|
||||
Use AskUserQuestion:
|
||||
- Question: "Have you added your Gitea token to ~/.config/claude/gitea.env?"
|
||||
- Header: "Token Added?"
|
||||
- Options:
|
||||
- "Yes, I've added the token"
|
||||
- "I need help generating a token"
|
||||
- "Skip for now (I'll do it later)"
|
||||
|
||||
- Repository belongs to an organization (required)
|
||||
- Required label categories exist
|
||||
- API credentials are valid
|
||||
- Network connectivity to Gitea
|
||||
**If "I need help":** Provide detailed instructions for their specific Gitea instance.
|
||||
**If "Skip":** Warn that MCP tools won't work until configured, but continue with project setup.
|
||||
|
||||
## Re-Running
|
||||
### Step 3.5: Validate Gitea Configuration
|
||||
|
||||
This command is safe to run multiple times. It will skip already-completed steps.
|
||||
Read the config file and verify it has non-placeholder values:
|
||||
|
||||
## MCP Server Structure
|
||||
|
||||
The plugin bundles these MCP servers:
|
||||
|
||||
```
|
||||
plugins/projman/mcp-servers/
|
||||
└── gitea/
|
||||
├── .venv/
|
||||
├── requirements.txt
|
||||
└── mcp_server/
|
||||
├── server.py
|
||||
├── gitea_client.py
|
||||
└── tools/
|
||||
├── issues.py
|
||||
├── labels.py
|
||||
├── wiki.py
|
||||
├── milestones.py
|
||||
└── dependencies.py
|
||||
```bash
|
||||
source ~/.config/claude/gitea.env && echo "URL: $GITEA_API_URL" && echo "TOKEN_LENGTH: ${#GITEA_API_TOKEN}"
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
If TOKEN_LENGTH is less than 10 or contains "PASTE" or "your_", the token hasn't been set properly.
|
||||
|
||||
**Error: Repository not under organization**
|
||||
- This plugin requires repositories to belong to a Gitea organization
|
||||
- Transfer your repository to an organization or create one
|
||||
**Note:** GITEA_ORG is configured per-project in `.env`, not in the system-level config.
|
||||
|
||||
**Error: Missing required labels**
|
||||
- Run `/labels-sync` to create missing labels
|
||||
- Or create them manually in Gitea
|
||||
**Test connectivity (optional but recommended):**
|
||||
|
||||
**Error: Cannot connect to Gitea**
|
||||
- Verify `GITEA_URL` in `~/.config/claude/gitea.env`
|
||||
- Check your API token has proper permissions
|
||||
- Ensure network connectivity
|
||||
```bash
|
||||
source ~/.config/claude/gitea.env && curl -s -o /dev/null -w "%{http_code}" -H "Authorization: token $GITEA_API_TOKEN" "$GITEA_API_URL/user"
|
||||
```
|
||||
|
||||
**Error: Virtual environment creation failed**
|
||||
- Ensure Python 3.8+ is installed
|
||||
- Check disk space
|
||||
- Try running `python -m venv .venv` manually in the MCP server directory
|
||||
- **200:** Success! Credentials are valid.
|
||||
- **401:** Invalid token.
|
||||
- **404/Connection error:** Invalid URL or network issue.
|
||||
|
||||
Report the result to the user.
|
||||
|
||||
### Step 3.6: Git-Flow Configuration (Optional)
|
||||
|
||||
Use AskUserQuestion:
|
||||
- Question: "Do you want to configure git-flow defaults for smart commits?"
|
||||
- Header: "Git-Flow"
|
||||
- Options:
|
||||
- "Yes, use recommended defaults (Recommended)"
|
||||
- "Yes, let me customize"
|
||||
- "No, skip git-flow configuration"
|
||||
|
||||
If yes with defaults:
|
||||
```bash
|
||||
cat > ~/.config/claude/git-flow.env << 'EOF'
|
||||
# Git-Flow Default Configuration
|
||||
GIT_WORKFLOW_STYLE=feature-branch
|
||||
GIT_DEFAULT_BASE=development
|
||||
GIT_AUTO_DELETE_MERGED=true
|
||||
GIT_AUTO_PUSH=false
|
||||
GIT_PROTECTED_BRANCHES=main,master,development,staging,production
|
||||
GIT_COMMIT_STYLE=conventional
|
||||
GIT_CO_AUTHOR=true
|
||||
EOF
|
||||
chmod 600 ~/.config/claude/git-flow.env
|
||||
```
|
||||
|
||||
If customize, use AskUserQuestion for each setting.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Project-Level Configuration
|
||||
|
||||
Project configuration is stored in `.env` in the current project root.
|
||||
|
||||
### Step 4.1: Verify Current Directory
|
||||
|
||||
Confirm we're in the right place:
|
||||
|
||||
```bash
|
||||
pwd && git rev-parse --show-toplevel 2>/dev/null || echo "NOT_A_GIT_REPO"
|
||||
```
|
||||
|
||||
If not a git repo, ask the user:
|
||||
|
||||
Use AskUserQuestion:
|
||||
- Question: "The current directory doesn't appear to be a git repository. Where should I create the project configuration?"
|
||||
- Options:
|
||||
- "This directory is correct, continue anyway"
|
||||
- "Let me navigate to the right directory first"
|
||||
|
||||
### Step 4.2: Check Existing Project Configuration
|
||||
|
||||
```bash
|
||||
cat .env 2>/dev/null || echo "FILE_NOT_FOUND"
|
||||
```
|
||||
|
||||
If `.env` exists and has `GITEA_REPO=` set to a non-placeholder value, skip to Phase 5.
|
||||
|
||||
### Step 4.3: Infer Organization and Repository from Git Remote
|
||||
|
||||
Try to detect org and repo name automatically:
|
||||
|
||||
```bash
|
||||
git remote get-url origin 2>/dev/null
|
||||
```
|
||||
|
||||
Parse the output to extract both organization and repository:
|
||||
- `git@gitea.example.com:org/repo-name.git` → org: `org`, repo: `repo-name`
|
||||
- `https://gitea.example.com/org/repo-name.git` → org: `org`, repo: `repo-name`
|
||||
|
||||
Extract organization:
|
||||
```bash
|
||||
git remote get-url origin 2>/dev/null | sed 's/.*[:/]\([^/]*\)\/[^/]*$/\1/'
|
||||
```
|
||||
|
||||
Extract repository:
|
||||
```bash
|
||||
git remote get-url origin 2>/dev/null | sed 's/.*[:/]\([^/]*\)\.git$/\1/' | sed 's/.*\/\([^/]*\)$/\1/'
|
||||
```
|
||||
|
||||
### Step 4.4: Validate Repository via Gitea API
|
||||
|
||||
**Before asking for confirmation**, verify the repository exists and is accessible:
|
||||
|
||||
```bash
|
||||
source ~/.config/claude/gitea.env
|
||||
curl -s -o /dev/null -w "%{http_code}" -H "Authorization: token $GITEA_API_TOKEN" "$GITEA_API_URL/repos/<detected-org>/<detected-repo>"
|
||||
```
|
||||
|
||||
**Based on response:**
|
||||
|
||||
| HTTP Code | Meaning | Action |
|
||||
|-----------|---------|--------|
|
||||
| **200** | Repository exists and accessible | **Auto-fill without asking** - skip to Step 4.7 |
|
||||
| **404** | Repository not found | Ask user to confirm/correct (Step 4.5) |
|
||||
| **401/403** | Token issue or no access | Warn about permissions, ask to confirm |
|
||||
| **Other** | Network/server issue | Warn, ask to confirm manually |
|
||||
|
||||
**If 200 OK:** Display confirmation message and skip to Step 4.7:
|
||||
"Verified: Repository '<detected-org>/<detected-repo>' exists and is accessible."
|
||||
|
||||
### Step 4.5: Confirm Organization (only if API validation failed)
|
||||
|
||||
Use AskUserQuestion:
|
||||
- Question: "Repository '<detected-org>/<detected-repo>' was not found. Is '<detected-org>' the correct organization?"
|
||||
- Header: "Organization"
|
||||
- Options:
|
||||
- "Yes, that's correct"
|
||||
- "No, let me specify the correct organization"
|
||||
|
||||
If no, ask user to provide the correct organization name.
|
||||
|
||||
### Step 4.6: Confirm Repository Name (only if API validation failed)
|
||||
|
||||
Use AskUserQuestion:
|
||||
- Question: "Is '<detected-repo-name>' the correct Gitea repository name?"
|
||||
- Header: "Repository"
|
||||
- Options:
|
||||
- "Yes, that's correct"
|
||||
- "No, let me specify the correct name"
|
||||
|
||||
If no, ask user to provide the correct name.
|
||||
|
||||
**After user provides corrections, re-validate via API (Step 4.4)** to ensure the corrected values are valid.
|
||||
|
||||
### Step 4.7: Create Project Configuration
|
||||
|
||||
```bash
|
||||
cat > .env << 'EOF'
|
||||
# Project Configuration for projman
|
||||
# Generated by /initial-setup
|
||||
|
||||
GITEA_ORG=<ORG_NAME>
|
||||
GITEA_REPO=<REPO_NAME>
|
||||
EOF
|
||||
```
|
||||
|
||||
Replace `<REPO_NAME>` with the confirmed value.
|
||||
|
||||
**Important:** Check if `.env` is in `.gitignore`:
|
||||
|
||||
```bash
|
||||
grep -q "^\.env$" .gitignore 2>/dev/null && echo "GITIGNORE_OK" || echo "GITIGNORE_MISSING"
|
||||
```
|
||||
|
||||
If not in `.gitignore`, warn the user:
|
||||
"Warning: `.env` is not in your `.gitignore`. Consider adding it to prevent accidentally committing credentials."
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: Final Validation and Next Steps
|
||||
|
||||
### Step 5.1: Summary Report
|
||||
|
||||
Display a summary of what was configured:
|
||||
|
||||
```
|
||||
╔══════════════════════════════════════════════════════════════╗
|
||||
║ SETUP COMPLETE ║
|
||||
╠══════════════════════════════════════════════════════════════╣
|
||||
║ MCP Server (Gitea): ✓ Installed ║
|
||||
║ System Config: ✓ ~/.config/claude/gitea.env ║
|
||||
║ Project Config: ✓ ./.env ║
|
||||
║ Gitea Connection: ✓ Verified (or ⚠ Not tested) ║
|
||||
╚══════════════════════════════════════════════════════════════╝
|
||||
```
|
||||
|
||||
### Step 5.2: Session Restart Notice
|
||||
|
||||
**IMPORTANT:** Display this notice clearly:
|
||||
|
||||
---
|
||||
|
||||
**⚠️ Session Restart Required**
|
||||
|
||||
The MCP server has been configured but won't be available until you restart your Claude Code session.
|
||||
|
||||
**To complete setup:**
|
||||
1. Exit this Claude Code session (type `/exit` or close the terminal)
|
||||
2. Start a new Claude Code session in this project
|
||||
3. The Gitea MCP tools will now be available
|
||||
|
||||
**After restart, you can:**
|
||||
- Run `/labels-sync` to sync your label taxonomy
|
||||
- Run `/sprint-plan` to start planning
|
||||
- Use MCP tools like `list_issues`, `create_issue`, etc.
|
||||
|
||||
---
|
||||
|
||||
### Step 5.3: Troubleshooting Checklist
|
||||
|
||||
If something isn't working after restart, check:
|
||||
|
||||
1. **MCP server not found:** Verify venv exists at the expected path
|
||||
2. **Authentication failed:** Re-check token in `~/.config/claude/gitea.env`
|
||||
3. **Wrong repository:** Verify `GITEA_REPO` in `./.env` matches Gitea exactly
|
||||
4. **Network error:** Ensure Gitea URL is accessible from this machine
|
||||
|
||||
---
|
||||
|
||||
## Re-Running This Command
|
||||
|
||||
This command is safe to run multiple times:
|
||||
- Existing venvs are skipped (not recreated)
|
||||
- Existing config files are checked for validity
|
||||
- Only missing or placeholder values are updated
|
||||
- Project config can be regenerated for new projects
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference: Files Created
|
||||
|
||||
| File | Purpose | Contains |
|
||||
|------|---------|----------|
|
||||
| `~/.config/claude/gitea.env` | System credentials | URL, token, org |
|
||||
| `~/.config/claude/git-flow.env` | Git defaults | Workflow settings |
|
||||
| `./.env` | Project settings | Repository name |
|
||||
| `<mcp-server>/.venv/` | Python environment | Dependencies |
|
||||
|
||||
@@ -1,47 +1,95 @@
|
||||
---
|
||||
description: Synchronize label taxonomy from Gitea and update suggestion logic
|
||||
description: Fetch and validate label taxonomy from Gitea, create missing required labels
|
||||
---
|
||||
|
||||
# Sync Label Taxonomy from Gitea
|
||||
|
||||
This command synchronizes the label taxonomy from Gitea (organization + repository labels) and updates the local reference file used by the label suggestion logic.
|
||||
This command fetches the current label taxonomy from Gitea (organization + repository labels), validates that required labels exist, and creates any missing ones.
|
||||
|
||||
## Why Label Sync Matters
|
||||
## CRITICAL: Execution Steps
|
||||
|
||||
The label taxonomy is **dynamic** - new labels may be added to Gitea over time:
|
||||
- Organization-level labels (shared across all repos)
|
||||
- Repository-specific labels (unique to this project)
|
||||
You MUST follow these steps in order. Do NOT skip any step.
|
||||
|
||||
**Dynamic approach:** Never hardcode labels. Always fetch from Gitea and adapt suggestions accordingly.
|
||||
### Step 1: Detect Repository from Git Remote
|
||||
|
||||
## What This Command Does
|
||||
Run this Bash command to get the git remote URL:
|
||||
|
||||
1. **Validate Repository** - Verify repo belongs to an organization using `validate_repo_org`
|
||||
2. **Fetch Current Labels** - Uses `get_labels` MCP tool to fetch all labels (org + repo)
|
||||
3. **Compare with Local Reference** - Checks against `skills/label-taxonomy/labels-reference.md`
|
||||
4. **Detect Changes** - Identifies new, removed, or modified labels
|
||||
5. **Explain Changes** - Shows what changed and why it matters
|
||||
6. **Create Missing Labels** - Uses `create_label` for required labels that don't exist
|
||||
7. **Update Reference** - Updates the local labels-reference.md file
|
||||
8. **Confirm Update** - Asks for user confirmation before updating
|
||||
```bash
|
||||
git remote get-url origin
|
||||
```
|
||||
|
||||
## MCP Tools Used
|
||||
Parse the output to extract `owner/repo`:
|
||||
- SSH format `ssh://git@host:port/owner/repo.git` → extract `owner/repo`
|
||||
- SSH short `git@host:owner/repo.git` → extract `owner/repo`
|
||||
- HTTPS `https://host/owner/repo.git` → extract `owner/repo`
|
||||
|
||||
**Gitea Tools:**
|
||||
- `get_labels` - Fetch all labels (organization + repository)
|
||||
- `create_label` - Create missing required labels
|
||||
- `validate_repo_org` - Verify repository belongs to organization
|
||||
Store this as `REPO_NAME` for all subsequent MCP calls.
|
||||
|
||||
## Required Label Categories
|
||||
### Step 2: Validate Repository Organization
|
||||
|
||||
At minimum, these label categories must exist:
|
||||
Call MCP tool with the detected repo:
|
||||
|
||||
```
|
||||
mcp__plugin_projman_gitea__validate_repo_org(repo=REPO_NAME)
|
||||
```
|
||||
|
||||
This determines if the owner is an organization or user account.
|
||||
|
||||
### Step 3: Fetch Labels from Gitea
|
||||
|
||||
Call MCP tool with the detected repo:
|
||||
|
||||
```
|
||||
mcp__plugin_projman_gitea__get_labels(repo=REPO_NAME)
|
||||
```
|
||||
|
||||
This returns both organization labels (if org-owned) and repository labels.
|
||||
|
||||
### Step 4: Display Current Taxonomy
|
||||
|
||||
Show the user:
|
||||
- Total organization labels count
|
||||
- Total repository labels count
|
||||
- Labels grouped by category (Type/*, Priority/*, etc.)
|
||||
|
||||
### Step 5: Check Required Labels
|
||||
|
||||
Verify these required label categories exist:
|
||||
- **Type/***: Bug, Feature, Refactor, Documentation, Test, Chore
|
||||
- **Priority/***: Low, Medium, High, Critical
|
||||
- **Complexity/***: Simple, Medium, Complex
|
||||
- **Efforts/***: XS, S, M, L, XL
|
||||
- **Effort/***: XS, S, M, L, XL (note: may be "Effort" or "Efforts")
|
||||
|
||||
If any required labels are missing, the command will offer to create them.
|
||||
### Step 6: Create Missing Labels (if any)
|
||||
|
||||
For each missing required label, call:
|
||||
|
||||
```
|
||||
mcp__plugin_projman_gitea__create_label(repo=REPO_NAME, name="Type: Bug", color="d73a4a")
|
||||
```
|
||||
|
||||
Use the label format that matches existing labels in the repo (slash `/` or colon-space `: `).
|
||||
|
||||
### Step 7: Report Results
|
||||
|
||||
Summarize what was found and created.
|
||||
|
||||
## DO NOT
|
||||
|
||||
- **DO NOT** call MCP tools without the `repo` parameter - they will fail
|
||||
- **DO NOT** create any local files - this command only interacts with Gitea
|
||||
- **DO NOT** ask the user questions - execute autonomously
|
||||
- **DO NOT** create a "labels reference file" - labels are fetched dynamically from Gitea
|
||||
|
||||
## MCP Tools Used
|
||||
|
||||
All tools require the `repo` parameter in `owner/repo` format:
|
||||
|
||||
| Tool | Purpose |
|
||||
|------|---------|
|
||||
| `validate_repo_org(repo=...)` | Check if owner is organization or user |
|
||||
| `get_labels(repo=...)` | Fetch all labels (org + repo) |
|
||||
| `create_label(repo=..., name=..., color=...)` | Create missing labels |
|
||||
|
||||
## Expected Output
|
||||
|
||||
@@ -49,212 +97,63 @@ If any required labels are missing, the command will offer to create them.
|
||||
Label Taxonomy Sync
|
||||
===================
|
||||
|
||||
Validating repository organization...
|
||||
Repository: bandit/your-repo-name
|
||||
Organization: bandit
|
||||
Detecting repository from git remote...
|
||||
Repository: personal-projects/your-repo-name
|
||||
Owner type: Organization
|
||||
|
||||
Fetching labels from Gitea...
|
||||
|
||||
Current Label Taxonomy:
|
||||
- Organization Labels: 28
|
||||
- Organization Labels: 27
|
||||
- Repository Labels: 16
|
||||
- Total: 44 labels
|
||||
- Total: 43 labels
|
||||
|
||||
Comparing with local reference...
|
||||
Organization Labels by Category:
|
||||
Type/*: 6 labels
|
||||
Priority/*: 4 labels
|
||||
Complexity/*: 3 labels
|
||||
Effort/*: 5 labels
|
||||
...
|
||||
|
||||
Changes Detected:
|
||||
NEW: Type/Performance (org-level)
|
||||
Description: Performance optimization tasks
|
||||
Color: #FF6B6B
|
||||
Suggestion: Add to suggestion logic for performance-related work
|
||||
|
||||
NEW: Tech/Redis (repo-level)
|
||||
Description: Redis-related technology
|
||||
Color: #DC143C
|
||||
Suggestion: Add to suggestion logic for caching and data store work
|
||||
|
||||
MODIFIED: Priority/Critical
|
||||
Change: Color updated from #D73A4A to #FF0000
|
||||
Impact: Visual only, no logic change needed
|
||||
|
||||
REMOVED: Component/Legacy
|
||||
Reason: Component deprecated and removed from codebase
|
||||
Impact: Remove from suggestion logic
|
||||
Repository Labels by Category:
|
||||
Component/*: 9 labels
|
||||
Tech/*: 7 labels
|
||||
|
||||
Required Labels Check:
|
||||
Type/*: 6/6 present
|
||||
Priority/*: 4/4 present
|
||||
Complexity/*: 3/3 present
|
||||
Efforts/*: 5/5 present
|
||||
Type/*: 6/6 present ✓
|
||||
Priority/*: 4/4 present ✓
|
||||
Complexity/*: 3/3 present ✓
|
||||
Effort/*: 5/5 present ✓
|
||||
|
||||
Summary:
|
||||
- 2 new labels added
|
||||
- 1 label modified (color only)
|
||||
- 1 label removed
|
||||
- Total labels: 44 -> 45
|
||||
- All required labels present
|
||||
|
||||
Update local reference file?
|
||||
[Y/n]
|
||||
All required labels present. Label taxonomy is ready for use.
|
||||
```
|
||||
|
||||
## Label Taxonomy Structure
|
||||
## Label Format Detection
|
||||
|
||||
Labels are organized by namespace:
|
||||
Labels may use different naming conventions:
|
||||
- Slash format: `Type/Bug`, `Priority/High`
|
||||
- Colon-space format: `Type: Bug`, `Priority: High`
|
||||
|
||||
**Organization Labels (28):**
|
||||
- `Agent/*` (2): Agent/Human, Agent/Claude
|
||||
- `Complexity/*` (3): Simple, Medium, Complex
|
||||
- `Efforts/*` (5): XS, S, M, L, XL
|
||||
- `Priority/*` (4): Low, Medium, High, Critical
|
||||
- `Risk/*` (3): Low, Medium, High
|
||||
- `Source/*` (4): Development, Staging, Production, Customer
|
||||
- `Type/*` (6): Bug, Feature, Refactor, Documentation, Test, Chore
|
||||
When creating missing labels, match the format used by existing labels in the repository.
|
||||
|
||||
**Repository Labels (16):**
|
||||
- `Component/*` (9): Backend, Frontend, API, Database, Auth, Deploy, Testing, Docs, Infra
|
||||
- `Tech/*` (7): Python, JavaScript, Docker, PostgreSQL, Redis, Vue, FastAPI
|
||||
## Troubleshooting
|
||||
|
||||
## Local Reference File
|
||||
**Error: Use 'owner/repo' format**
|
||||
- You forgot to pass the `repo` parameter to the MCP tool
|
||||
- Go back to Step 1 and detect the repo from git remote
|
||||
|
||||
The command updates `skills/label-taxonomy/labels-reference.md` with:
|
||||
**Empty organization labels**
|
||||
- If owner is a user account (not org), organization labels will be empty
|
||||
- This is expected - user accounts only have repository-level labels
|
||||
|
||||
```markdown
|
||||
# Label Taxonomy Reference
|
||||
|
||||
Last synced: 2025-01-18 14:30 UTC
|
||||
Source: Gitea (bandit/your-repo-name)
|
||||
|
||||
## Organization Labels (28)
|
||||
|
||||
### Agent (2)
|
||||
- Agent/Human - Work performed by human developers
|
||||
- Agent/Claude - Work performed by Claude Code
|
||||
|
||||
### Type (6)
|
||||
- Type/Bug - Bug fixes and error corrections
|
||||
- Type/Feature - New features and enhancements
|
||||
- Type/Refactor - Code restructuring and architectural changes
|
||||
- Type/Documentation - Documentation updates
|
||||
- Type/Test - Testing-related work
|
||||
- Type/Chore - Maintenance and tooling tasks
|
||||
|
||||
...
|
||||
|
||||
## Repository Labels (16)
|
||||
|
||||
### Component (9)
|
||||
- Component/Backend - Backend service code
|
||||
- Component/Frontend - User interface code
|
||||
- Component/API - API endpoints and contracts
|
||||
...
|
||||
|
||||
## Suggestion Logic
|
||||
|
||||
When suggesting labels, consider:
|
||||
|
||||
**Type Detection:**
|
||||
- Keywords "bug", "fix", "error" -> Type/Bug
|
||||
- Keywords "feature", "add", "implement" -> Type/Feature
|
||||
- Keywords "refactor", "extract", "restructure" -> Type/Refactor
|
||||
...
|
||||
```
|
||||
**Git remote not found**
|
||||
- Ensure you're running in a directory with a git repository
|
||||
- Check that the `origin` remote is configured
|
||||
|
||||
## When to Run
|
||||
|
||||
Run `/labels-sync` when:
|
||||
- Setting up the plugin for the first time
|
||||
- You notice missing labels in suggestions
|
||||
- New labels are added to Gitea (announced by team)
|
||||
- Quarterly maintenance (check for changes)
|
||||
- New labels are added to Gitea
|
||||
- After major taxonomy updates
|
||||
|
||||
## Integration with Other Commands
|
||||
|
||||
The updated taxonomy is used by:
|
||||
- `/sprint-plan` - Planner agent uses `suggest_labels` with current taxonomy
|
||||
- All commands that create or update issues
|
||||
|
||||
## Example Usage
|
||||
|
||||
```
|
||||
User: /labels-sync
|
||||
|
||||
Validating repository organization...
|
||||
Repository: bandit/your-repo-name
|
||||
|
||||
Fetching labels from Gitea...
|
||||
|
||||
Current Label Taxonomy:
|
||||
- Organization Labels: 28
|
||||
- Repository Labels: 16
|
||||
- Total: 44 labels
|
||||
|
||||
Comparing with local reference...
|
||||
|
||||
No changes detected. Label taxonomy is up to date.
|
||||
|
||||
Last synced: 2025-01-18 14:30 UTC
|
||||
```
|
||||
|
||||
```
|
||||
User: /labels-sync
|
||||
|
||||
Fetching labels from Gitea...
|
||||
|
||||
Changes Detected:
|
||||
NEW: Type/Performance
|
||||
NEW: Tech/Redis
|
||||
|
||||
Required Labels Check:
|
||||
MISSING: Complexity/Simple
|
||||
MISSING: Complexity/Medium
|
||||
MISSING: Complexity/Complex
|
||||
|
||||
Would you like me to create the missing required labels? [Y/n] y
|
||||
|
||||
Creating missing labels...
|
||||
Created: Complexity/Simple
|
||||
Created: Complexity/Medium
|
||||
Created: Complexity/Complex
|
||||
|
||||
Update local reference file? [Y/n] y
|
||||
|
||||
Label taxonomy updated successfully!
|
||||
Suggestion logic updated with new labels
|
||||
|
||||
New labels available for use:
|
||||
- Type/Performance
|
||||
- Tech/Redis
|
||||
- Complexity/Simple
|
||||
- Complexity/Medium
|
||||
- Complexity/Complex
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**Error: Cannot fetch labels from Gitea**
|
||||
- Check your Gitea configuration in `~/.config/claude/gitea.env`
|
||||
- Verify your API token has `read:org` and `repo` permissions
|
||||
- Ensure you're connected to the network
|
||||
|
||||
**Error: Repository is not under an organization**
|
||||
- This plugin requires repositories to belong to an organization
|
||||
- Transfer the repository to an organization or create one
|
||||
|
||||
**Error: Permission denied to update reference file**
|
||||
- Check file permissions on `skills/label-taxonomy/labels-reference.md`
|
||||
- Ensure you have write access to the plugin directory
|
||||
|
||||
**No changes detected but labels seem wrong**
|
||||
- The reference file may be manually edited - review it
|
||||
- Try forcing a re-sync by deleting the reference file first
|
||||
- Check if you're comparing against the correct repository
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Sync at sprint start** - Ensure labels are current before planning
|
||||
2. **Review changes** - Always review what changed before confirming
|
||||
3. **Create missing required labels** - Don't skip this step
|
||||
4. **Update planning** - After sync, consider if new labels affect current sprint
|
||||
5. **Communicate changes** - Let team know when new labels are available
|
||||
|
||||
218
plugins/projman/commands/project-init.md
Normal file
218
plugins/projman/commands/project-init.md
Normal file
@@ -0,0 +1,218 @@
|
||||
---
|
||||
description: Quick project setup - configures only project-level settings (assumes system setup is complete)
|
||||
---
|
||||
|
||||
# Project Initialization
|
||||
|
||||
Fast setup for a new project when system-level configuration is already complete.
|
||||
|
||||
**Use this when:**
|
||||
- You've already run `/initial-setup` on this machine
|
||||
- You're starting work on a new project/repository
|
||||
- You just need to create the project `.env` file
|
||||
|
||||
**Use `/initial-setup` instead if:**
|
||||
- This is your first time using the plugin
|
||||
- MCP tools aren't working (might need system setup)
|
||||
|
||||
---
|
||||
|
||||
## Pre-Flight Check
|
||||
|
||||
### Step 1: Verify System Configuration Exists
|
||||
|
||||
Quickly verify system setup is complete:
|
||||
|
||||
```bash
|
||||
cat ~/.config/claude/gitea.env 2>/dev/null | grep -v "^#" | grep -v "PASTE_YOUR" | grep "GITEA_API_TOKEN=" && echo "SYSTEM_OK" || echo "SYSTEM_MISSING"
|
||||
```
|
||||
|
||||
**If SYSTEM_MISSING:**
|
||||
|
||||
Display this message and stop:
|
||||
|
||||
---
|
||||
|
||||
**System configuration not found or incomplete.**
|
||||
|
||||
It looks like the system-level setup hasn't been completed yet. Please run:
|
||||
|
||||
```
|
||||
/initial-setup
|
||||
```
|
||||
|
||||
This will configure both system credentials and this project.
|
||||
|
||||
---
|
||||
|
||||
**If SYSTEM_OK:** Continue to project setup.
|
||||
|
||||
---
|
||||
|
||||
## Project Setup
|
||||
|
||||
### Step 2: Verify Current Directory
|
||||
|
||||
```bash
|
||||
pwd && git rev-parse --show-toplevel 2>/dev/null || echo "NOT_A_GIT_REPO"
|
||||
```
|
||||
|
||||
If not a git repo, ask:
|
||||
|
||||
Use AskUserQuestion:
|
||||
- Question: "This doesn't appear to be a git repository. Continue anyway?"
|
||||
- Header: "Directory"
|
||||
- Options:
|
||||
- "Yes, continue here"
|
||||
- "No, I'll navigate to the correct directory"
|
||||
|
||||
### Step 3: Check for Existing Configuration
|
||||
|
||||
```bash
|
||||
cat .env 2>/dev/null | grep "GITEA_REPO=" || echo "NOT_CONFIGURED"
|
||||
```
|
||||
|
||||
**If already configured:**
|
||||
|
||||
Use AskUserQuestion:
|
||||
- Question: "This project already has GITEA_ORG and GITEA_REPO configured. What would you like to do?"
|
||||
- Header: "Existing"
|
||||
- Options:
|
||||
- "Keep existing configuration"
|
||||
- "Reconfigure (replace current settings)"
|
||||
|
||||
**If "Keep":** End with success message.
|
||||
|
||||
### Step 4: Detect Organization and Repository
|
||||
|
||||
Try to auto-detect from git remote:
|
||||
|
||||
```bash
|
||||
git remote get-url origin 2>/dev/null
|
||||
```
|
||||
|
||||
Extract organization:
|
||||
```bash
|
||||
git remote get-url origin 2>/dev/null | sed 's/.*[:/]\([^/]*\)\/[^/]*$/\1/'
|
||||
```
|
||||
|
||||
Extract repository:
|
||||
```bash
|
||||
git remote get-url origin 2>/dev/null | sed 's/.*[:/]\([^/]*\)\.git$/\1/' | sed 's/.*\/\([^/]*\)$/\1/'
|
||||
```
|
||||
|
||||
### Step 5: Validate Repository via Gitea API
|
||||
|
||||
Verify the repository exists and is accessible:
|
||||
|
||||
```bash
|
||||
source ~/.config/claude/gitea.env
|
||||
curl -s -o /dev/null -w "%{http_code}" -H "Authorization: token $GITEA_API_TOKEN" "$GITEA_API_URL/repos/<detected-org>/<detected-repo>"
|
||||
```
|
||||
|
||||
| HTTP Code | Action |
|
||||
|-----------|--------|
|
||||
| **200** | Auto-fill - display "Verified: <org>/<repo> exists" and skip to Step 8 |
|
||||
| **404** | Repository not found - proceed to Step 6 |
|
||||
| **401/403** | Permission issue - warn and proceed to Step 6 |
|
||||
|
||||
### Step 6: Confirm Organization (only if API validation failed)
|
||||
|
||||
Use AskUserQuestion:
|
||||
- Question: "Repository not found. Is '<detected-org>' the correct organization?"
|
||||
- Header: "Organization"
|
||||
- Options:
|
||||
- "Yes, that's correct"
|
||||
- "No, let me specify"
|
||||
|
||||
If "No", ask user to type the correct organization name.
|
||||
|
||||
### Step 7: Confirm Repository Name (only if API validation failed)
|
||||
|
||||
Use AskUserQuestion:
|
||||
- Question: "Is '<detected-repo-name>' the correct repository name?"
|
||||
- Header: "Repository"
|
||||
- Options:
|
||||
- "Yes, that's correct"
|
||||
- "No, let me specify"
|
||||
|
||||
If "No", ask user to type the correct name.
|
||||
|
||||
**After corrections, re-validate via API (Step 5).**
|
||||
|
||||
### Step 8: Create/Update Project Configuration
|
||||
|
||||
**If `.env` exists:**
|
||||
Check if it already has other content and append:
|
||||
|
||||
```bash
|
||||
echo "" >> .env
|
||||
echo "# Added by /project-init" >> .env
|
||||
echo "GITEA_ORG=<ORG_NAME>" >> .env
|
||||
echo "GITEA_REPO=<REPO_NAME>" >> .env
|
||||
```
|
||||
|
||||
**If `.env` doesn't exist:**
|
||||
|
||||
```bash
|
||||
cat > .env << 'EOF'
|
||||
# Project Configuration for projman
|
||||
# Generated by /project-init
|
||||
|
||||
GITEA_ORG=<ORG_NAME>
|
||||
GITEA_REPO=<REPO_NAME>
|
||||
EOF
|
||||
```
|
||||
|
||||
### Step 9: Check .gitignore
|
||||
|
||||
```bash
|
||||
grep -q "^\.env$" .gitignore 2>/dev/null && echo "GITIGNORE_OK" || echo "GITIGNORE_MISSING"
|
||||
```
|
||||
|
||||
**If GITIGNORE_MISSING:**
|
||||
|
||||
Use AskUserQuestion:
|
||||
- Question: "`.env` is not in `.gitignore`. Add it to prevent committing secrets?"
|
||||
- Header: "gitignore"
|
||||
- Options:
|
||||
- "Yes, add .env to .gitignore (Recommended)"
|
||||
- "No, I'll handle it manually"
|
||||
|
||||
If yes:
|
||||
```bash
|
||||
echo ".env" >> .gitignore
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Complete
|
||||
|
||||
Display success message:
|
||||
|
||||
```
|
||||
╔══════════════════════════════════════════════════════════════╗
|
||||
║ PROJECT CONFIGURED ║
|
||||
╠══════════════════════════════════════════════════════════════╣
|
||||
║ Organization: <ORG_NAME> ║
|
||||
║ Repository: <REPO_NAME> ║
|
||||
║ Config file: ./.env ║
|
||||
╚══════════════════════════════════════════════════════════════╝
|
||||
|
||||
You're ready to use projman commands:
|
||||
• /sprint-plan - Start sprint planning
|
||||
• /sprint-status - Check progress
|
||||
• /labels-sync - Sync label taxonomy
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**MCP tools not working?**
|
||||
- Run `/initial-setup` for full setup including MCP server
|
||||
- Restart your Claude Code session after setup
|
||||
|
||||
**Wrong repository configured?**
|
||||
- Edit `.env` directly: `nano .env`
|
||||
- Or run `/project-init` again and choose "Reconfigure"
|
||||
196
plugins/projman/commands/project-sync.md
Normal file
196
plugins/projman/commands/project-sync.md
Normal file
@@ -0,0 +1,196 @@
|
||||
---
|
||||
description: Sync project configuration with current git remote - use after changing repository location or organization
|
||||
---
|
||||
|
||||
# Project Sync
|
||||
|
||||
Updates project configuration when the git remote URL has changed (repository moved, renamed, or organization changed).
|
||||
|
||||
**Use this when:**
|
||||
- You moved the repository to a different organization
|
||||
- You renamed the repository
|
||||
- You changed the git remote URL
|
||||
- The SessionStart hook detected a mismatch
|
||||
|
||||
---
|
||||
|
||||
## Step 1: Verify System Configuration
|
||||
|
||||
```bash
|
||||
cat ~/.config/claude/gitea.env 2>/dev/null | grep -v "^#" | grep -v "PASTE_YOUR" | grep "GITEA_API_TOKEN=" && echo "SYSTEM_OK" || echo "SYSTEM_MISSING"
|
||||
```
|
||||
|
||||
**If SYSTEM_MISSING:** Stop and instruct user to run `/initial-setup` first.
|
||||
|
||||
---
|
||||
|
||||
## Step 2: Read Current Configuration
|
||||
|
||||
Read the current .env values:
|
||||
|
||||
```bash
|
||||
cat .env 2>/dev/null
|
||||
```
|
||||
|
||||
Extract current values:
|
||||
- `CURRENT_ORG` from `GITEA_ORG=...`
|
||||
- `CURRENT_REPO` from `GITEA_REPO=...`
|
||||
|
||||
**If .env doesn't exist or has no GITEA values:** Redirect to `/project-init`.
|
||||
|
||||
---
|
||||
|
||||
## Step 3: Detect Git Remote Values
|
||||
|
||||
Get the current git remote:
|
||||
|
||||
```bash
|
||||
git remote get-url origin 2>/dev/null
|
||||
```
|
||||
|
||||
Extract organization:
|
||||
```bash
|
||||
git remote get-url origin 2>/dev/null | sed 's/.*[:/]\([^/]*\)\/[^/]*$/\1/'
|
||||
```
|
||||
|
||||
Extract repository:
|
||||
```bash
|
||||
git remote get-url origin 2>/dev/null | sed 's/.*[:/]\([^/]*\)\.git$/\1/' | sed 's/.*\/\([^/]*\)$/\1/'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 4: Compare Values
|
||||
|
||||
Compare current .env values with detected git remote values:
|
||||
|
||||
| Scenario | Action |
|
||||
|----------|--------|
|
||||
| **Both match** | Display "Configuration is in sync" and exit |
|
||||
| **Organization changed** | Proceed to Step 5 |
|
||||
| **Repository changed** | Proceed to Step 5 |
|
||||
| **Both changed** | Proceed to Step 5 |
|
||||
|
||||
**If already in sync:**
|
||||
|
||||
```
|
||||
╔══════════════════════════════════════════════════════════════╗
|
||||
║ CONFIGURATION IN SYNC ║
|
||||
╠══════════════════════════════════════════════════════════════╣
|
||||
║ Organization: <ORG_NAME> ║
|
||||
║ Repository: <REPO_NAME> ║
|
||||
║ Git Remote: matches .env ║
|
||||
╚══════════════════════════════════════════════════════════════╝
|
||||
```
|
||||
|
||||
Exit here if in sync.
|
||||
|
||||
---
|
||||
|
||||
## Step 5: Show Detected Changes
|
||||
|
||||
Display the detected changes to the user:
|
||||
|
||||
```
|
||||
╔══════════════════════════════════════════════════════════════╗
|
||||
║ REPOSITORY CHANGE DETECTED ║
|
||||
╠══════════════════════════════════════════════════════════════╣
|
||||
║ Current .env │ Git Remote ║
|
||||
║ Organization: <OLD_ORG> │ <NEW_ORG> ║
|
||||
║ Repository: <OLD_REPO> │ <NEW_REPO> ║
|
||||
╚══════════════════════════════════════════════════════════════╝
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 6: Validate New Repository via Gitea API
|
||||
|
||||
Verify the new repository exists and is accessible:
|
||||
|
||||
```bash
|
||||
source ~/.config/claude/gitea.env
|
||||
curl -s -o /dev/null -w "%{http_code}" -H "Authorization: token $GITEA_API_TOKEN" "$GITEA_API_URL/repos/<NEW_ORG>/<NEW_REPO>"
|
||||
```
|
||||
|
||||
| HTTP Code | Action |
|
||||
|-----------|--------|
|
||||
| **200** | Repository verified - proceed to Step 7 |
|
||||
| **404** | Repository not found - ask user to confirm (Step 6a) |
|
||||
| **401/403** | Permission issue - warn and ask to confirm |
|
||||
|
||||
### Step 6a: Confirm if API Validation Failed
|
||||
|
||||
Use AskUserQuestion:
|
||||
- Question: "The new repository '<NEW_ORG>/<NEW_REPO>' was not found via API. Update configuration anyway?"
|
||||
- Header: "Not Found"
|
||||
- Options:
|
||||
- "Yes, update anyway (I'll fix the remote later)"
|
||||
- "No, let me fix the git remote first"
|
||||
- "Let me specify different values"
|
||||
|
||||
**If "specify different values":** Ask for correct org and repo, then re-validate.
|
||||
|
||||
---
|
||||
|
||||
## Step 7: Confirm Update
|
||||
|
||||
Use AskUserQuestion:
|
||||
- Question: "Update project configuration to match git remote?"
|
||||
- Header: "Confirm"
|
||||
- Options:
|
||||
- "Yes, update .env (Recommended)"
|
||||
- "No, keep current configuration"
|
||||
|
||||
**If "No":** Exit without changes.
|
||||
|
||||
---
|
||||
|
||||
## Step 8: Update Configuration
|
||||
|
||||
Update the .env file with new values:
|
||||
|
||||
```bash
|
||||
# Update GITEA_ORG
|
||||
sed -i 's/^GITEA_ORG=.*/GITEA_ORG=<NEW_ORG>/' .env
|
||||
|
||||
# Update GITEA_REPO
|
||||
sed -i 's/^GITEA_REPO=.*/GITEA_REPO=<NEW_REPO>/' .env
|
||||
```
|
||||
|
||||
Alternatively, if sed doesn't work well, read the file, replace values, and write back.
|
||||
|
||||
---
|
||||
|
||||
## Step 9: Verify Update
|
||||
|
||||
Read the updated .env and display confirmation:
|
||||
|
||||
```
|
||||
╔══════════════════════════════════════════════════════════════╗
|
||||
║ CONFIGURATION UPDATED ║
|
||||
╠══════════════════════════════════════════════════════════════╣
|
||||
║ Organization: <NEW_ORG> ║
|
||||
║ Repository: <NEW_REPO> ║
|
||||
║ Status: In sync with git remote ║
|
||||
╚══════════════════════════════════════════════════════════════╝
|
||||
|
||||
Your project configuration has been updated.
|
||||
MCP tools will now use the new repository.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**"Repository not found" but it exists:**
|
||||
- Check your Gitea token has access to the new organization
|
||||
- Verify the repository name matches exactly (case-sensitive)
|
||||
- Ensure your token has `repo` permissions
|
||||
|
||||
**Git remote URL is wrong:**
|
||||
- Fix it first: `git remote set-url origin <correct-url>`
|
||||
- Then run `/project-sync` again
|
||||
|
||||
**Want to revert the change:**
|
||||
- Edit `.env` manually: `nano .env`
|
||||
- Or run `/project-sync` after fixing the git remote
|
||||
10
plugins/projman/hooks/hooks.json
Normal file
10
plugins/projman/hooks/hooks.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"hooks": {
|
||||
"SessionStart": [
|
||||
{
|
||||
"type": "prompt",
|
||||
"prompt": "Perform silent startup checks:\n\n1. Check if MCP venvs exist at the installed marketplace location. If the marketplace is installed but venvs are missing, warn the user to run setup.sh from that location.\n\n2. Check if the project git remote matches .env configuration (GITEA_ORG/GITEA_REPO). If mismatch, warn about /project-sync.\n\nStay silent if all checks pass or not applicable. Be quick and non-blocking."
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ description: Dynamic reference for Gitea label taxonomy (organization + reposito
|
||||
|
||||
**Status:** ✅ Synced with Gitea
|
||||
**Last synced:** 2025-11-21 (via automated testing)
|
||||
**Source:** Gitea (personal-projects/support-claude-mktplace)
|
||||
**Source:** Gitea (personal-projects/leo-claude-mktplace)
|
||||
|
||||
## Overview
|
||||
|
||||
|
||||
37
scripts/check-venv.sh
Executable file
37
scripts/check-venv.sh
Executable file
@@ -0,0 +1,37 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# check-venv.sh - Check if MCP server venvs exist in installed marketplace
|
||||
#
|
||||
# Usage: ./scripts/check-venv.sh
|
||||
#
|
||||
# Exit codes:
|
||||
# 0 - All venvs exist (or not installed via marketplace)
|
||||
# 1 - Venvs missing, needs setup
|
||||
#
|
||||
# This script is designed to be called from SessionStart hooks
|
||||
# to enable self-healing MCP server setup.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Installed marketplace location
|
||||
MKTPLACE="$HOME/.claude/plugins/marketplaces/leo-claude-mktplace"
|
||||
|
||||
# If not installed via marketplace, exit silently
|
||||
if [[ ! -d "$MKTPLACE" ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Check if gitea venv exists
|
||||
if [[ ! -f "$MKTPLACE/mcp-servers/gitea/.venv/bin/python" ]]; then
|
||||
echo "SETUP_NEEDED"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if netbox venv exists
|
||||
if [[ ! -f "$MKTPLACE/mcp-servers/netbox/.venv/bin/python" ]]; then
|
||||
echo "SETUP_NEEDED"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# All good
|
||||
exit 0
|
||||
@@ -1,6 +1,17 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# setup.sh - Initial setup for lm-claude-plugins
|
||||
# setup.sh - Automated setup for Leo Claude Marketplace
|
||||
#
|
||||
# ============================================================================
|
||||
# NOTE: For interactive setup, use the /initial-setup command in Claude Code
|
||||
# instead of this script. The command provides a guided wizard experience.
|
||||
#
|
||||
# This script is intended for:
|
||||
# - CI/CD pipelines
|
||||
# - Automated deployments
|
||||
# - Bulk machine provisioning
|
||||
# - Fallback when Claude Code is not available
|
||||
# ============================================================================
|
||||
#
|
||||
# Usage: ./scripts/setup.sh
|
||||
#
|
||||
@@ -123,10 +134,10 @@ setup_config_templates() {
|
||||
cat > "$config_dir/gitea.env" << 'EOF'
|
||||
# Gitea API Configuration
|
||||
# Update these values with your Gitea instance details
|
||||
# Note: GITEA_ORG is configured per-project in .env
|
||||
|
||||
GITEA_URL=https://gitea.example.com
|
||||
GITEA_TOKEN=your_gitea_token_here
|
||||
GITEA_ORG=your_organization_name
|
||||
GITEA_API_URL=https://gitea.example.com/api/v1
|
||||
GITEA_API_TOKEN=your_gitea_token_here
|
||||
EOF
|
||||
chmod 600 "$config_dir/gitea.env"
|
||||
log_success "gitea.env template created"
|
||||
@@ -141,8 +152,8 @@ EOF
|
||||
# NetBox API Configuration
|
||||
# Update these values with your NetBox instance details
|
||||
|
||||
NETBOX_URL=https://netbox.example.com
|
||||
NETBOX_TOKEN=your_netbox_token_here
|
||||
NETBOX_API_URL=https://netbox.example.com/api
|
||||
NETBOX_API_TOKEN=your_netbox_token_here
|
||||
EOF
|
||||
chmod 600 "$config_dir/netbox.env"
|
||||
log_success "netbox.env template created"
|
||||
@@ -178,8 +189,8 @@ validate_config() {
|
||||
# Check Gitea config has real values
|
||||
if [[ -f "$config_dir/gitea.env" ]]; then
|
||||
source "$config_dir/gitea.env"
|
||||
if [[ "${GITEA_TOKEN:-}" == "your_gitea_token_here" ]] || [[ -z "${GITEA_TOKEN:-}" ]]; then
|
||||
log_todo "Update GITEA_TOKEN in ~/.config/claude/gitea.env"
|
||||
if [[ "${GITEA_API_TOKEN:-}" == "your_gitea_token_here" ]] || [[ -z "${GITEA_API_TOKEN:-}" ]]; then
|
||||
log_todo "Update GITEA_API_TOKEN in ~/.config/claude/gitea.env"
|
||||
else
|
||||
log_success "Gitea configuration appears valid"
|
||||
fi
|
||||
@@ -188,8 +199,8 @@ validate_config() {
|
||||
# Check NetBox config has real values
|
||||
if [[ -f "$config_dir/netbox.env" ]]; then
|
||||
source "$config_dir/netbox.env"
|
||||
if [[ "${NETBOX_TOKEN:-}" == "your_netbox_token_here" ]] || [[ -z "${NETBOX_TOKEN:-}" ]]; then
|
||||
log_todo "Update NETBOX_TOKEN in ~/.config/claude/netbox.env"
|
||||
if [[ "${NETBOX_API_TOKEN:-}" == "your_netbox_token_here" ]] || [[ -z "${NETBOX_API_TOKEN:-}" ]]; then
|
||||
log_todo "Update NETBOX_API_TOKEN in ~/.config/claude/netbox.env"
|
||||
else
|
||||
log_success "NetBox configuration appears valid"
|
||||
fi
|
||||
@@ -265,7 +276,7 @@ print_report() {
|
||||
# --- Main ---
|
||||
main() {
|
||||
echo "=============================================="
|
||||
echo " lm-claude-plugins Setup (v3.0.0)"
|
||||
echo " Leo Claude Marketplace Setup (v3.0.0)"
|
||||
echo "=============================================="
|
||||
echo ""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user