From 43b2add336506e079602c35856ae2546af87934f Mon Sep 17 00:00:00 2001 From: openhands Date: Wed, 8 Jul 2026 13:28:58 +0000 Subject: [PATCH 1/3] fix: make root marketplace catalog real files (not symlinks) raw.githubusercontent.com does not dereference git symlinks through directory paths, so the double symlink chain (.claude-plugin -> .plugin -> ../marketplaces/openhands-extensions.json) made the catalog unreachable at the standard .claude-plugin/marketplace.json path. Consumers using github://openhands/extensions (e.g. openhands/plugin-directory) got a 404 or the literal symlink body and saw an empty Plugin Directory. Replace the root vendor symlinks with real marketplace.json copies that mirror the canonical marketplaces/openhands-extensions.json byte-for-byte. Add a root-marketplace sync task to scripts/sync_extensions.py to keep them in sync (and CI --check enforces it), plus tests. Closes #394 Co-authored-by: openhands --- .claude-plugin | 1 - .claude-plugin/marketplace.json | 752 +++++++++++++++++++++++++++++++ .codex-plugin | 1 - .codex-plugin/marketplace.json | 752 +++++++++++++++++++++++++++++++ .plugin/marketplace.json | 753 +++++++++++++++++++++++++++++++- AGENTS.md | 3 +- scripts/sync_extensions.py | 94 +++- tests/test_sync_extensions.py | 123 ++++++ 8 files changed, 2474 insertions(+), 5 deletions(-) delete mode 120000 .claude-plugin create mode 100644 .claude-plugin/marketplace.json delete mode 120000 .codex-plugin create mode 100644 .codex-plugin/marketplace.json mode change 120000 => 100644 .plugin/marketplace.json diff --git a/.claude-plugin b/.claude-plugin deleted file mode 120000 index 665797f0..00000000 --- a/.claude-plugin +++ /dev/null @@ -1 +0,0 @@ -.plugin \ No newline at end of file diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json new file mode 100644 index 00000000..55dbe082 --- /dev/null +++ b/.claude-plugin/marketplace.json @@ -0,0 +1,752 @@ +{ + "metadata": { + "description": "Official skills and plugins for OpenHands — the open-source AI software engineer.", + "homepage": "https://github.com/OpenHands/extensions", + "maintainer": "OpenHands" + }, + "name": "openhands-extensions", + "owner": { + "email": "contact@all-hands.dev", + "name": "OpenHands" + }, + "plugins": [ + { + "category": "development", + "description": "Create file-based sub-agents as Markdown files — no Python code required. Guides the user through a structured interview and generates a ready-to-deploy .md agent file following the OpenHands SDK specification.", + "keywords": [ + "agent", + "sub-agent", + "file-based", + "markdown", + "no-code", + "create" + ], + "name": "agent-creator", + "source": "./skills/agent-creator" + }, + { + "category": "productivity", + "description": "Add (import) an OpenHands skill from a GitHub repository into the current workspace.", + "keywords": [ + "skill", + "import", + "github", + "sparse-checkout" + ], + "name": "add-skill", + "source": "./skills/add-skill" + }, + { + "category": "productivity", + "description": "Persist and retrieve repository-specific knowledge using AGENTS.md files. Use when you want to save important information about a codebase (build commands, code style, workflows) for future sessions.", + "keywords": [ + "memory", + "knowledge", + "persistence", + "agents" + ], + "name": "agent-memory", + "source": "./skills/agent-memory" + }, + { + "category": "development", + "description": "Guided workflow for building custom AI agents using the OpenHands Software Agent SDK. Use when you want to create a new agent through an interactive interview process that gathers requirements and generates implementation plans.", + "keywords": [ + "agent", + "sdk", + "builder", + "openhands" + ], + "name": "agent-sdk-builder", + "source": "./skills/agent-sdk-builder" + }, + { + "category": "development", + "description": "Simplifies and refines code across three dimensions - code reuse, code quality, and efficiency - while preserving all functionality. Analyzes recently modified code and provides actionable improvement suggestions.", + "keywords": [ + "simplify", + "refine", + "cleanup", + "code-quality", + "reuse", + "efficiency", + "refactor" + ], + "name": "code-simplifier", + "source": "./skills/code-simplifier" + }, + { + "category": "integration", + "description": "Create and manage OpenHands automations - scheduled tasks that run in sandboxes. Use the prompt preset to create automations from natural language, or manage existing automations.", + "keywords": [ + "automation", + "cron", + "scheduled-task", + "sandbox", + "openhands" + ], + "name": "openhands-automation", + "source": "./skills/openhands-automation" + }, + { + "category": "development", + "description": "Work effectively inside a local Agent Canvas environment, including local agent-server auth, safe workspace hygiene, and local conversation delegation.", + "keywords": [ + "agent-canvas", + "openhands", + "local", + "conversation", + "delegation" + ], + "name": "agent-canvas-environment", + "source": "./skills/agent-canvas-environment" + }, + { + "category": "development", + "description": "Reference skill for the OpenHands Software Agent SDK - build AI agents with custom tools, LLM configuration, conversations, sub-agent delegation, MCP integration, security, and persistence.", + "keywords": [ + "sdk", + "agent", + "openhands", + "tools", + "llm", + "conversation" + ], + "name": "openhands-sdk", + "source": "./skills/openhands-sdk" + }, + { + "category": "integration", + "description": "Interact with Azure DevOps repositories, pull requests, and APIs using the AZURE_DEVOPS_TOKEN environment variable. Use when working with code hosted on Azure DevOps or managing Azure DevOps resources.", + "keywords": [ + "azure", + "devops", + "git", + "pull-request" + ], + "name": "azure-devops", + "source": "./skills/azure-devops" + }, + { + "category": "integration", + "description": "Bitbucket integration hub. Detects whether the repository is on Bitbucket Cloud or Bitbucket Data Center and directs you to the matching detailed skill (bitbucket-cloud or bitbucket-data-center). Use for any Bitbucket repository or pull request task.", + "keywords": [ + "bitbucket", + "git", + "pull-request" + ], + "name": "bitbucket", + "source": "./skills/bitbucket" + }, + { + "category": "integration", + "description": "Bitbucket Cloud (bitbucket.org) specifics — authenticate with BITBUCKET_TOKEN, use the REST API v2, workspace/repo_slug repositories, and the create_bitbucket_pr tool. Loaded on demand by the bitbucket skill once a Cloud environment is detected.", + "keywords": [ + "bitbucket", + "bitbucket-cloud", + "git", + "pull-request" + ], + "name": "bitbucket-cloud", + "source": "./skills/bitbucket-cloud" + }, + { + "category": "integration", + "description": "Bitbucket Data Center (self-hosted Bitbucket Server) specifics — authenticate with BITBUCKET_DATA_CENTER_TOKEN, use the REST API 1.0, PROJECT/repo_slug repositories, scm/ git remotes, and the create_bitbucket_data_center_pr tool. Loaded on demand by the bitbucket skill once a Data Center environment is detected.", + "keywords": [ + "bitbucket", + "bitbucket-data-center", + "bitbucket-server", + "git", + "pull-request" + ], + "name": "bitbucket-data-center", + "source": "./skills/bitbucket-data-center" + }, + { + "category": "utilities", + "description": "Get current weather, time, and precipitation forecast for any city using the free Open-Meteo API. Provides slash command /city-weather:now .", + "keywords": [ + "weather", + "time", + "forecast", + "temperature", + "precipitation", + "sample" + ], + "name": "city-weather", + "source": "./plugins/city-weather" + }, + { + "category": "code-quality", + "description": "Rigorous code review focusing on data structures, simplicity, security, pragmatism, and risk/safety evaluation. Provides brutally honest, actionable feedback on pull requests or merge requests, including a risk assessment for every review. Use when reviewing code changes.", + "keywords": [ + "code-review", + "quality", + "security", + "style", + "risk" + ], + "name": "code-review", + "source": "./skills/code-review" + }, + { + "category": "monitoring", + "description": "Query and analyze Datadog logs, metrics, APM traces, and monitors using the Datadog API. Use when debugging production issues, monitoring application performance, or investigating alerts.", + "keywords": [ + "datadog", + "monitoring", + "logs", + "metrics", + "apm" + ], + "name": "datadog", + "source": "./skills/datadog" + }, + { + "category": "development", + "description": "Common project operations using Deno (tasks, run/test/lint/fmt, and dependency management).", + "keywords": [ + "deno", + "typescript", + "javascript", + "runtime" + ], + "name": "deno", + "source": "./skills/deno" + }, + { + "category": "integration", + "description": "Build and automate Discord integrations (bots, webhooks, slash commands, and REST API workflows). Use when the user mentions Discord, a Discord server/guild, channels, webhooks, bot tokens, slash commands/application commands, discord.js, or discord.py.", + "keywords": [ + "discord", + "bot", + "webhook", + "automation" + ], + "name": "discord", + "source": "./skills/discord" + }, + { + "category": "infrastructure", + "description": "Run Docker commands within a container environment, including starting the Docker daemon and managing containers. Use when building, running, or managing Docker containers and images.", + "keywords": [ + "docker", + "container", + "images" + ], + "name": "docker", + "source": "./skills/docker" + }, + { + "category": "testing", + "description": "A test skill that responds to the magic word 'flarglebargle' with a compliment. Use for testing skill activation and trigger functionality.", + "keywords": [ + "test", + "demo" + ], + "name": "flarglebargle", + "source": "./skills/flarglebargle" + }, + { + "category": "design", + "description": "Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts, posters, or applications. Generates creative, polished code and UI design that avoids generic AI aesthetics.", + "keywords": [ + "frontend", + "design", + "ui", + "web", + "react", + "html", + "css" + ], + "name": "frontend-design", + "source": "./skills/frontend-design" + }, + { + "category": "integration", + "description": "Interact with GitHub repositories, pull requests, issues, and workflows using the GITHUB_TOKEN environment variable and GitHub CLI. Use when working with code hosted on GitHub or managing GitHub resources.", + "keywords": [ + "github", + "git", + "pull-request", + "issues", + "workflows" + ], + "name": "github", + "source": "./skills/github" + }, + { + "category": "integration", + "description": "Create, debug, and test GitHub Actions workflows and custom actions. Use when building CI/CD pipelines, automating workflows, or troubleshooting GitHub Actions.", + "keywords": [ + "github-actions", + "workflows", + "ci-cd", + "automation", + "actions" + ], + "name": "github-actions", + "source": "./skills/github-actions" + }, + { + "category": "code-quality", + "description": "Post structured PR reviews to GitHub with inline comments/suggestions in a single API call.", + "keywords": [ + "github", + "pull-request", + "review", + "code-review" + ], + "name": "github-pr-review", + "source": "./skills/github-pr-review" + }, + { + "category": "productivity", + "description": "Create a cron automation that polls a GitHub repository for issue and PR comments containing a configurable trigger phrase (@OpenHands by default). Starts an OpenHands conversation with full issue/PR context, posts acknowledgement comments with a conversation link, and summarises results back to the issue/PR when the agent finishes.", + "keywords": [ + "github", + "monitor", + "issues", + "pull-requests", + "trigger", + "cron", + "automation", + "integration" + ], + "name": "github-repo-monitor", + "source": "./skills/github-repo-monitor" + }, + { + "category": "integration", + "description": "Interact with GitLab repositories, merge requests, and APIs using the GITLAB_TOKEN environment variable. Use when working with code hosted on GitLab or managing GitLab resources.", + "keywords": [ + "gitlab", + "git", + "merge-request" + ], + "name": "gitlab", + "source": "./skills/gitlab" + }, + { + "category": "data-science", + "description": "Read, modify, execute, and convert Jupyter notebooks programmatically. Use when working with .ipynb files for data science workflows, including editing cells, clearing outputs, or converting to other formats.", + "keywords": [ + "jupyter", + "notebook", + "ipynb", + "data-science" + ], + "name": "jupyter", + "source": "./skills/jupyter" + }, + { + "category": "infrastructure", + "description": "Set up and manage local Kubernetes clusters using KIND (Kubernetes IN Docker). Use when testing Kubernetes applications locally or developing cloud-native workloads.", + "keywords": [ + "kubernetes", + "k8s", + "kind", + "cloud-native" + ], + "name": "kubernetes", + "source": "./skills/kubernetes" + }, + { + "category": "code-quality", + "description": "Distill code review feedback from GitHub PRs into reusable skills and guidelines. Use when users ask to learn from code reviews, extract review patterns, or generate coding standards from historical PR feedback.", + "keywords": [ + "code-review", + "learning", + "skills", + "guidelines", + "pr-feedback" + ], + "name": "learn-from-code-review", + "source": "./skills/learn-from-code-review" + }, + { + "category": "integration", + "description": "Interact with Linear project management - query issues, update status, create tickets using the Linear GraphQL API.", + "keywords": [ + "linear", + "ticket", + "issue", + "project-management", + "graphql" + ], + "name": "linear", + "source": "./skills/linear" + }, + { + "category": "testing", + "description": "A simple test plugin for verifying plugin loading. Triggers on magic words (alakazam, abracadabra) and returns a specific phrase to confirm plugins are working.", + "keywords": [ + "test", + "magic", + "plugin", + "verification", + "sample" + ], + "name": "magic-test", + "source": "./plugins/magic-test" + }, + { + "category": "productivity", + "description": "Create, search, and update Notion pages/databases using the Notion API. Use for documenting work, generating runbooks, and automating knowledge base updates.", + "keywords": [ + "notion", + "documentation", + "knowledge-base" + ], + "name": "notion", + "source": "./skills/notion" + }, + { + "category": "development", + "description": "Handle npm package installation in non-interactive environments by piping confirmations. Use when installing Node.js packages that require user confirmation prompts.", + "keywords": [ + "npm", + "nodejs", + "packages" + ], + "name": "npm", + "source": "./skills/npm" + }, + { + "category": "productivity", + "description": "Assess repository agent-readiness across five pillars, propose high-impact fixes, and generate repo-specific AGENTS.md files.", + "keywords": [ + "onboarding", + "readiness", + "agents-md", + "agent-readiness", + "assessment" + ], + "name": "onboarding", + "source": "./plugins/onboarding" + }, + { + "category": "openhands", + "description": "Unified OpenHands plugin — bundles Cloud CLI, REST API (openhands-api), and Automations (openhands-automation) into a single plugin.", + "keywords": [ + "openhands", + "cloud", + "api", + "automation", + "cli" + ], + "name": "openhands", + "source": "./plugins/openhands" + }, + { + "category": "development", + "description": "Use the OpenHands Cloud REST API (V1) and agent-server APIs to create and manage Cloud or local backend conversations, including multi-conversation delegation workflows. Includes minimal Python and TypeScript clients under scripts/.", + "keywords": [ + "openhands", + "api", + "cloud", + "automation", + "delegation", + "agent-server", + "sandbox", + "conversations" + ], + "name": "openhands-api", + "source": "./skills/openhands-api" + }, + { + "category": "documentation", + "description": "Install and use pdflatex to compile LaTeX documents into PDFs on Linux. Use when generating academic papers, research publications, or any documents written in LaTeX.", + "keywords": [ + "latex", + "pdf", + "academic", + "documents" + ], + "name": "pdflatex", + "source": "./skills/pdflatex" + }, + { + "category": "code-quality", + "description": "Automated PR code review — analyzes diffs and posts inline review comments via the GitHub API.", + "keywords": [ + "pr-review", + "code-review", + "github", + "automation" + ], + "name": "pr-review", + "source": "./plugins/pr-review" + }, + { + "category": "quality-assurance", + "description": "Validate pull request changes by actually running the code — setting up the environment, exercising changed behavior, and posting a structured QA report.", + "keywords": [ + "qa", + "testing", + "pull-request", + "validation", + "automation" + ], + "name": "qa-changes", + "source": "./plugins/qa-changes" + }, + { + "category": "productivity", + "description": "Generate a Product Requirements Document (PRD) for a new feature through an interactive clarifying-question workflow. Use when planning a feature, starting a new project, or when asked to create a PRD.", + "keywords": [ + "prd", + "requirements", + "planning", + "product", + "specification" + ], + "name": "prd", + "source": "./skills/prd" + }, + { + "category": "productivity", + "description": "Generate consistent, well-structured release notes from git history. Produces categorized changelog with breaking changes, features, fixes, and contributor attribution.", + "keywords": [ + "release-notes", + "changelog", + "git", + "semver" + ], + "name": "release-notes", + "source": "./plugins/release-notes" + }, + { + "category": "security", + "description": "Security best practices for secure coding, authentication, authorization, and data protection. Use when developing features that handle sensitive data, user authentication, or require security review.", + "keywords": [ + "security", + "authentication", + "authorization", + "encryption" + ], + "name": "security", + "source": "./skills/security" + }, + { + "category": "development", + "description": "Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Claude's capabilities with specialized knowledge, workflows, or tool integrations.", + "keywords": [ + "skill", + "plugin", + "create" + ], + "name": "skill-creator", + "source": "./skills/skill-creator" + }, + { + "category": "productivity", + "description": "Create a cron automation that polls up to 10 Slack channels every minute and starts an OpenHands conversation when a configurable trigger phrase is detected. Forwards thread replies to running conversations and posts summaries back to Slack when the agent finishes.", + "keywords": [ + "slack", + "monitor", + "channel", + "trigger", + "cron", + "automation", + "integration" + ], + "name": "slack-channel-monitor", + "source": "./skills/slack-channel-monitor" + }, + { + "category": "infrastructure", + "description": "Establish and manage SSH connections to remote machines, including key generation, configuration, and file transfers. Use when connecting to remote servers, executing remote commands, or transferring files via SCP.", + "keywords": [ + "ssh", + "remote", + "scp", + "server" + ], + "name": "ssh", + "source": "./skills/ssh" + }, + { + "category": "development", + "description": "Install and configure Swift programming language on Debian Linux for server-side development. Use when building Swift applications on Linux or setting up a Swift development environment.", + "keywords": [ + "swift", + "linux", + "server-side" + ], + "name": "swift-linux", + "source": "./skills/swift-linux" + }, + { + "category": "design", + "description": "Toolkit for styling artifacts with a theme. These artifacts can be slides, docs, reportings, HTML landing pages, etc. There are 10 pre-set themes with colors/fonts that you can apply to any artifact that has been creating, or can generate a new theme on-the-fly.", + "keywords": [ + "theme", + "styling", + "design", + "slides", + "documents" + ], + "name": "theme-factory", + "source": "./skills/theme-factory" + }, + { + "category": "development", + "description": "Common project, dependency, and environment operations using uv.", + "keywords": [ + "uv", + "python", + "dependencies", + "venv" + ], + "name": "uv", + "source": "./skills/uv" + }, + { + "category": "integration", + "description": "Deploy and manage applications on Vercel, including preview deployments and deployment protection.", + "keywords": [ + "vercel", + "deployment", + "preview", + "hosting" + ], + "name": "vercel", + "source": "./skills/vercel" + }, + { + "category": "security", + "description": "Automated security vulnerability scanning and AI-powered remediation. Scans repositories, skips when no issues found, and creates PRs with fixes.", + "keywords": [ + "security", + "vulnerability", + "remediation", + "scanning", + "automation" + ], + "name": "vulnerability-remediation", + "source": "./plugins/vulnerability-remediation" + }, + { + "category": "productivity", + "description": "Iterate on a GitHub pull request — drive it through CI, code review, and QA until merge-ready. Monitors state, fixes failures, addresses review feedback, retries flaky checks, and pushes fixes in one continuous loop.", + "keywords": [ + "github", + "ci", + "review", + "qa", + "pull-request", + "iterate" + ], + "name": "iterate", + "source": "./skills/iterate" + }, + { + "category": "productivity", + "description": "Back factual claims and field values with official, verifiable sources. Use when the user asks to fill fields, answer questions, or make claims that must be supported by an exact quote and an official link.", + "keywords": [ + "evidence", + "citations", + "sources", + "verification", + "documentation", + "official" + ], + "name": "evidence-based-citations", + "source": "./skills/evidence-based-citations" + }, + { + "category": "productivity", + "description": "Create an automation that reviews GitHub pull requests when they are opened or updated. Inspects the diff, changed files, tests, and existing discussion via GitHub MCP, then posts a concise review highlighting risks, security issues, missing tests, and next steps.", + "keywords": [ + "github", + "pull-request", + "review", + "code-review", + "automation", + "integration" + ], + "name": "github-pr-reviewer", + "source": "./skills/github-pr-reviewer" + }, + { + "category": "productivity", + "description": "Create an automation that drafts incident retrospectives by gathering incident-channel messages from Slack, collecting linked tickets from Linear, and publishing a retrospective draft to Notion with timeline, impact summary, root-cause hypotheses, and action items.", + "keywords": [ + "incident", + "retrospective", + "postmortem", + "slack", + "linear", + "notion", + "automation" + ], + "name": "incident-retrospective", + "source": "./skills/incident-retrospective" + }, + { + "category": "productivity", + "description": "Create an automation that triages new Linear issues by inspecting title, description, team, and recent related issues. Suggests labels, priority, likely owner, and potential duplicates, then posts a clarifying comment.", + "keywords": [ + "linear", + "triage", + "issues", + "labels", + "priority", + "automation", + "integration" + ], + "name": "linear-triage", + "source": "./skills/linear-triage" + }, + { + "category": "productivity", + "description": "Create a recurring automation that researches a topic using Tavily web search and publishes a structured brief to Notion with executive summary, key findings, implications, and source citations.", + "keywords": [ + "research", + "brief", + "tavily", + "notion", + "web-search", + "automation" + ], + "name": "research-brief", + "source": "./skills/research-brief" + }, + { + "category": "productivity", + "description": "Create an automation that generates an async standup digest from Slack. Searches selected channels for messages since the previous workday, groups updates by project, highlights blockers and decisions, and posts a summary to a target channel.", + "keywords": [ + "slack", + "standup", + "digest", + "summary", + "daily", + "cron", + "automation" + ], + "name": "slack-standup-digest", + "source": "./skills/slack-standup-digest" + }, + { + "category": "productivity", + "description": "Write and edit clear, accessible prose in a plain English content style: active voice, front-loaded content, sentence case, and accessible formatting.", + "keywords": [ + "plain-english" + ], + "name": "plain-english-content", + "source": "./skills/plain-english-content" + }, + { + "category": "productivity", + "description": "Deploy a cron-based OpenHands automation that watches a Jira Cloud project for issues labeled with a configurable label (default: create-pr) and spawns an agent conversation to create a GitHub pull request for each new issue found. The target GitHub repo is read from the ticket body - no repo parameter required at deploy time.", + "keywords": [ + "jira", + "atlassian" + ], + "name": "jira-issue-to-pr", + "source": "./skills/jira-issue-to-pr" + } + ] +} diff --git a/.codex-plugin b/.codex-plugin deleted file mode 120000 index 665797f0..00000000 --- a/.codex-plugin +++ /dev/null @@ -1 +0,0 @@ -.plugin \ No newline at end of file diff --git a/.codex-plugin/marketplace.json b/.codex-plugin/marketplace.json new file mode 100644 index 00000000..55dbe082 --- /dev/null +++ b/.codex-plugin/marketplace.json @@ -0,0 +1,752 @@ +{ + "metadata": { + "description": "Official skills and plugins for OpenHands — the open-source AI software engineer.", + "homepage": "https://github.com/OpenHands/extensions", + "maintainer": "OpenHands" + }, + "name": "openhands-extensions", + "owner": { + "email": "contact@all-hands.dev", + "name": "OpenHands" + }, + "plugins": [ + { + "category": "development", + "description": "Create file-based sub-agents as Markdown files — no Python code required. Guides the user through a structured interview and generates a ready-to-deploy .md agent file following the OpenHands SDK specification.", + "keywords": [ + "agent", + "sub-agent", + "file-based", + "markdown", + "no-code", + "create" + ], + "name": "agent-creator", + "source": "./skills/agent-creator" + }, + { + "category": "productivity", + "description": "Add (import) an OpenHands skill from a GitHub repository into the current workspace.", + "keywords": [ + "skill", + "import", + "github", + "sparse-checkout" + ], + "name": "add-skill", + "source": "./skills/add-skill" + }, + { + "category": "productivity", + "description": "Persist and retrieve repository-specific knowledge using AGENTS.md files. Use when you want to save important information about a codebase (build commands, code style, workflows) for future sessions.", + "keywords": [ + "memory", + "knowledge", + "persistence", + "agents" + ], + "name": "agent-memory", + "source": "./skills/agent-memory" + }, + { + "category": "development", + "description": "Guided workflow for building custom AI agents using the OpenHands Software Agent SDK. Use when you want to create a new agent through an interactive interview process that gathers requirements and generates implementation plans.", + "keywords": [ + "agent", + "sdk", + "builder", + "openhands" + ], + "name": "agent-sdk-builder", + "source": "./skills/agent-sdk-builder" + }, + { + "category": "development", + "description": "Simplifies and refines code across three dimensions - code reuse, code quality, and efficiency - while preserving all functionality. Analyzes recently modified code and provides actionable improvement suggestions.", + "keywords": [ + "simplify", + "refine", + "cleanup", + "code-quality", + "reuse", + "efficiency", + "refactor" + ], + "name": "code-simplifier", + "source": "./skills/code-simplifier" + }, + { + "category": "integration", + "description": "Create and manage OpenHands automations - scheduled tasks that run in sandboxes. Use the prompt preset to create automations from natural language, or manage existing automations.", + "keywords": [ + "automation", + "cron", + "scheduled-task", + "sandbox", + "openhands" + ], + "name": "openhands-automation", + "source": "./skills/openhands-automation" + }, + { + "category": "development", + "description": "Work effectively inside a local Agent Canvas environment, including local agent-server auth, safe workspace hygiene, and local conversation delegation.", + "keywords": [ + "agent-canvas", + "openhands", + "local", + "conversation", + "delegation" + ], + "name": "agent-canvas-environment", + "source": "./skills/agent-canvas-environment" + }, + { + "category": "development", + "description": "Reference skill for the OpenHands Software Agent SDK - build AI agents with custom tools, LLM configuration, conversations, sub-agent delegation, MCP integration, security, and persistence.", + "keywords": [ + "sdk", + "agent", + "openhands", + "tools", + "llm", + "conversation" + ], + "name": "openhands-sdk", + "source": "./skills/openhands-sdk" + }, + { + "category": "integration", + "description": "Interact with Azure DevOps repositories, pull requests, and APIs using the AZURE_DEVOPS_TOKEN environment variable. Use when working with code hosted on Azure DevOps or managing Azure DevOps resources.", + "keywords": [ + "azure", + "devops", + "git", + "pull-request" + ], + "name": "azure-devops", + "source": "./skills/azure-devops" + }, + { + "category": "integration", + "description": "Bitbucket integration hub. Detects whether the repository is on Bitbucket Cloud or Bitbucket Data Center and directs you to the matching detailed skill (bitbucket-cloud or bitbucket-data-center). Use for any Bitbucket repository or pull request task.", + "keywords": [ + "bitbucket", + "git", + "pull-request" + ], + "name": "bitbucket", + "source": "./skills/bitbucket" + }, + { + "category": "integration", + "description": "Bitbucket Cloud (bitbucket.org) specifics — authenticate with BITBUCKET_TOKEN, use the REST API v2, workspace/repo_slug repositories, and the create_bitbucket_pr tool. Loaded on demand by the bitbucket skill once a Cloud environment is detected.", + "keywords": [ + "bitbucket", + "bitbucket-cloud", + "git", + "pull-request" + ], + "name": "bitbucket-cloud", + "source": "./skills/bitbucket-cloud" + }, + { + "category": "integration", + "description": "Bitbucket Data Center (self-hosted Bitbucket Server) specifics — authenticate with BITBUCKET_DATA_CENTER_TOKEN, use the REST API 1.0, PROJECT/repo_slug repositories, scm/ git remotes, and the create_bitbucket_data_center_pr tool. Loaded on demand by the bitbucket skill once a Data Center environment is detected.", + "keywords": [ + "bitbucket", + "bitbucket-data-center", + "bitbucket-server", + "git", + "pull-request" + ], + "name": "bitbucket-data-center", + "source": "./skills/bitbucket-data-center" + }, + { + "category": "utilities", + "description": "Get current weather, time, and precipitation forecast for any city using the free Open-Meteo API. Provides slash command /city-weather:now .", + "keywords": [ + "weather", + "time", + "forecast", + "temperature", + "precipitation", + "sample" + ], + "name": "city-weather", + "source": "./plugins/city-weather" + }, + { + "category": "code-quality", + "description": "Rigorous code review focusing on data structures, simplicity, security, pragmatism, and risk/safety evaluation. Provides brutally honest, actionable feedback on pull requests or merge requests, including a risk assessment for every review. Use when reviewing code changes.", + "keywords": [ + "code-review", + "quality", + "security", + "style", + "risk" + ], + "name": "code-review", + "source": "./skills/code-review" + }, + { + "category": "monitoring", + "description": "Query and analyze Datadog logs, metrics, APM traces, and monitors using the Datadog API. Use when debugging production issues, monitoring application performance, or investigating alerts.", + "keywords": [ + "datadog", + "monitoring", + "logs", + "metrics", + "apm" + ], + "name": "datadog", + "source": "./skills/datadog" + }, + { + "category": "development", + "description": "Common project operations using Deno (tasks, run/test/lint/fmt, and dependency management).", + "keywords": [ + "deno", + "typescript", + "javascript", + "runtime" + ], + "name": "deno", + "source": "./skills/deno" + }, + { + "category": "integration", + "description": "Build and automate Discord integrations (bots, webhooks, slash commands, and REST API workflows). Use when the user mentions Discord, a Discord server/guild, channels, webhooks, bot tokens, slash commands/application commands, discord.js, or discord.py.", + "keywords": [ + "discord", + "bot", + "webhook", + "automation" + ], + "name": "discord", + "source": "./skills/discord" + }, + { + "category": "infrastructure", + "description": "Run Docker commands within a container environment, including starting the Docker daemon and managing containers. Use when building, running, or managing Docker containers and images.", + "keywords": [ + "docker", + "container", + "images" + ], + "name": "docker", + "source": "./skills/docker" + }, + { + "category": "testing", + "description": "A test skill that responds to the magic word 'flarglebargle' with a compliment. Use for testing skill activation and trigger functionality.", + "keywords": [ + "test", + "demo" + ], + "name": "flarglebargle", + "source": "./skills/flarglebargle" + }, + { + "category": "design", + "description": "Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts, posters, or applications. Generates creative, polished code and UI design that avoids generic AI aesthetics.", + "keywords": [ + "frontend", + "design", + "ui", + "web", + "react", + "html", + "css" + ], + "name": "frontend-design", + "source": "./skills/frontend-design" + }, + { + "category": "integration", + "description": "Interact with GitHub repositories, pull requests, issues, and workflows using the GITHUB_TOKEN environment variable and GitHub CLI. Use when working with code hosted on GitHub or managing GitHub resources.", + "keywords": [ + "github", + "git", + "pull-request", + "issues", + "workflows" + ], + "name": "github", + "source": "./skills/github" + }, + { + "category": "integration", + "description": "Create, debug, and test GitHub Actions workflows and custom actions. Use when building CI/CD pipelines, automating workflows, or troubleshooting GitHub Actions.", + "keywords": [ + "github-actions", + "workflows", + "ci-cd", + "automation", + "actions" + ], + "name": "github-actions", + "source": "./skills/github-actions" + }, + { + "category": "code-quality", + "description": "Post structured PR reviews to GitHub with inline comments/suggestions in a single API call.", + "keywords": [ + "github", + "pull-request", + "review", + "code-review" + ], + "name": "github-pr-review", + "source": "./skills/github-pr-review" + }, + { + "category": "productivity", + "description": "Create a cron automation that polls a GitHub repository for issue and PR comments containing a configurable trigger phrase (@OpenHands by default). Starts an OpenHands conversation with full issue/PR context, posts acknowledgement comments with a conversation link, and summarises results back to the issue/PR when the agent finishes.", + "keywords": [ + "github", + "monitor", + "issues", + "pull-requests", + "trigger", + "cron", + "automation", + "integration" + ], + "name": "github-repo-monitor", + "source": "./skills/github-repo-monitor" + }, + { + "category": "integration", + "description": "Interact with GitLab repositories, merge requests, and APIs using the GITLAB_TOKEN environment variable. Use when working with code hosted on GitLab or managing GitLab resources.", + "keywords": [ + "gitlab", + "git", + "merge-request" + ], + "name": "gitlab", + "source": "./skills/gitlab" + }, + { + "category": "data-science", + "description": "Read, modify, execute, and convert Jupyter notebooks programmatically. Use when working with .ipynb files for data science workflows, including editing cells, clearing outputs, or converting to other formats.", + "keywords": [ + "jupyter", + "notebook", + "ipynb", + "data-science" + ], + "name": "jupyter", + "source": "./skills/jupyter" + }, + { + "category": "infrastructure", + "description": "Set up and manage local Kubernetes clusters using KIND (Kubernetes IN Docker). Use when testing Kubernetes applications locally or developing cloud-native workloads.", + "keywords": [ + "kubernetes", + "k8s", + "kind", + "cloud-native" + ], + "name": "kubernetes", + "source": "./skills/kubernetes" + }, + { + "category": "code-quality", + "description": "Distill code review feedback from GitHub PRs into reusable skills and guidelines. Use when users ask to learn from code reviews, extract review patterns, or generate coding standards from historical PR feedback.", + "keywords": [ + "code-review", + "learning", + "skills", + "guidelines", + "pr-feedback" + ], + "name": "learn-from-code-review", + "source": "./skills/learn-from-code-review" + }, + { + "category": "integration", + "description": "Interact with Linear project management - query issues, update status, create tickets using the Linear GraphQL API.", + "keywords": [ + "linear", + "ticket", + "issue", + "project-management", + "graphql" + ], + "name": "linear", + "source": "./skills/linear" + }, + { + "category": "testing", + "description": "A simple test plugin for verifying plugin loading. Triggers on magic words (alakazam, abracadabra) and returns a specific phrase to confirm plugins are working.", + "keywords": [ + "test", + "magic", + "plugin", + "verification", + "sample" + ], + "name": "magic-test", + "source": "./plugins/magic-test" + }, + { + "category": "productivity", + "description": "Create, search, and update Notion pages/databases using the Notion API. Use for documenting work, generating runbooks, and automating knowledge base updates.", + "keywords": [ + "notion", + "documentation", + "knowledge-base" + ], + "name": "notion", + "source": "./skills/notion" + }, + { + "category": "development", + "description": "Handle npm package installation in non-interactive environments by piping confirmations. Use when installing Node.js packages that require user confirmation prompts.", + "keywords": [ + "npm", + "nodejs", + "packages" + ], + "name": "npm", + "source": "./skills/npm" + }, + { + "category": "productivity", + "description": "Assess repository agent-readiness across five pillars, propose high-impact fixes, and generate repo-specific AGENTS.md files.", + "keywords": [ + "onboarding", + "readiness", + "agents-md", + "agent-readiness", + "assessment" + ], + "name": "onboarding", + "source": "./plugins/onboarding" + }, + { + "category": "openhands", + "description": "Unified OpenHands plugin — bundles Cloud CLI, REST API (openhands-api), and Automations (openhands-automation) into a single plugin.", + "keywords": [ + "openhands", + "cloud", + "api", + "automation", + "cli" + ], + "name": "openhands", + "source": "./plugins/openhands" + }, + { + "category": "development", + "description": "Use the OpenHands Cloud REST API (V1) and agent-server APIs to create and manage Cloud or local backend conversations, including multi-conversation delegation workflows. Includes minimal Python and TypeScript clients under scripts/.", + "keywords": [ + "openhands", + "api", + "cloud", + "automation", + "delegation", + "agent-server", + "sandbox", + "conversations" + ], + "name": "openhands-api", + "source": "./skills/openhands-api" + }, + { + "category": "documentation", + "description": "Install and use pdflatex to compile LaTeX documents into PDFs on Linux. Use when generating academic papers, research publications, or any documents written in LaTeX.", + "keywords": [ + "latex", + "pdf", + "academic", + "documents" + ], + "name": "pdflatex", + "source": "./skills/pdflatex" + }, + { + "category": "code-quality", + "description": "Automated PR code review — analyzes diffs and posts inline review comments via the GitHub API.", + "keywords": [ + "pr-review", + "code-review", + "github", + "automation" + ], + "name": "pr-review", + "source": "./plugins/pr-review" + }, + { + "category": "quality-assurance", + "description": "Validate pull request changes by actually running the code — setting up the environment, exercising changed behavior, and posting a structured QA report.", + "keywords": [ + "qa", + "testing", + "pull-request", + "validation", + "automation" + ], + "name": "qa-changes", + "source": "./plugins/qa-changes" + }, + { + "category": "productivity", + "description": "Generate a Product Requirements Document (PRD) for a new feature through an interactive clarifying-question workflow. Use when planning a feature, starting a new project, or when asked to create a PRD.", + "keywords": [ + "prd", + "requirements", + "planning", + "product", + "specification" + ], + "name": "prd", + "source": "./skills/prd" + }, + { + "category": "productivity", + "description": "Generate consistent, well-structured release notes from git history. Produces categorized changelog with breaking changes, features, fixes, and contributor attribution.", + "keywords": [ + "release-notes", + "changelog", + "git", + "semver" + ], + "name": "release-notes", + "source": "./plugins/release-notes" + }, + { + "category": "security", + "description": "Security best practices for secure coding, authentication, authorization, and data protection. Use when developing features that handle sensitive data, user authentication, or require security review.", + "keywords": [ + "security", + "authentication", + "authorization", + "encryption" + ], + "name": "security", + "source": "./skills/security" + }, + { + "category": "development", + "description": "Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Claude's capabilities with specialized knowledge, workflows, or tool integrations.", + "keywords": [ + "skill", + "plugin", + "create" + ], + "name": "skill-creator", + "source": "./skills/skill-creator" + }, + { + "category": "productivity", + "description": "Create a cron automation that polls up to 10 Slack channels every minute and starts an OpenHands conversation when a configurable trigger phrase is detected. Forwards thread replies to running conversations and posts summaries back to Slack when the agent finishes.", + "keywords": [ + "slack", + "monitor", + "channel", + "trigger", + "cron", + "automation", + "integration" + ], + "name": "slack-channel-monitor", + "source": "./skills/slack-channel-monitor" + }, + { + "category": "infrastructure", + "description": "Establish and manage SSH connections to remote machines, including key generation, configuration, and file transfers. Use when connecting to remote servers, executing remote commands, or transferring files via SCP.", + "keywords": [ + "ssh", + "remote", + "scp", + "server" + ], + "name": "ssh", + "source": "./skills/ssh" + }, + { + "category": "development", + "description": "Install and configure Swift programming language on Debian Linux for server-side development. Use when building Swift applications on Linux or setting up a Swift development environment.", + "keywords": [ + "swift", + "linux", + "server-side" + ], + "name": "swift-linux", + "source": "./skills/swift-linux" + }, + { + "category": "design", + "description": "Toolkit for styling artifacts with a theme. These artifacts can be slides, docs, reportings, HTML landing pages, etc. There are 10 pre-set themes with colors/fonts that you can apply to any artifact that has been creating, or can generate a new theme on-the-fly.", + "keywords": [ + "theme", + "styling", + "design", + "slides", + "documents" + ], + "name": "theme-factory", + "source": "./skills/theme-factory" + }, + { + "category": "development", + "description": "Common project, dependency, and environment operations using uv.", + "keywords": [ + "uv", + "python", + "dependencies", + "venv" + ], + "name": "uv", + "source": "./skills/uv" + }, + { + "category": "integration", + "description": "Deploy and manage applications on Vercel, including preview deployments and deployment protection.", + "keywords": [ + "vercel", + "deployment", + "preview", + "hosting" + ], + "name": "vercel", + "source": "./skills/vercel" + }, + { + "category": "security", + "description": "Automated security vulnerability scanning and AI-powered remediation. Scans repositories, skips when no issues found, and creates PRs with fixes.", + "keywords": [ + "security", + "vulnerability", + "remediation", + "scanning", + "automation" + ], + "name": "vulnerability-remediation", + "source": "./plugins/vulnerability-remediation" + }, + { + "category": "productivity", + "description": "Iterate on a GitHub pull request — drive it through CI, code review, and QA until merge-ready. Monitors state, fixes failures, addresses review feedback, retries flaky checks, and pushes fixes in one continuous loop.", + "keywords": [ + "github", + "ci", + "review", + "qa", + "pull-request", + "iterate" + ], + "name": "iterate", + "source": "./skills/iterate" + }, + { + "category": "productivity", + "description": "Back factual claims and field values with official, verifiable sources. Use when the user asks to fill fields, answer questions, or make claims that must be supported by an exact quote and an official link.", + "keywords": [ + "evidence", + "citations", + "sources", + "verification", + "documentation", + "official" + ], + "name": "evidence-based-citations", + "source": "./skills/evidence-based-citations" + }, + { + "category": "productivity", + "description": "Create an automation that reviews GitHub pull requests when they are opened or updated. Inspects the diff, changed files, tests, and existing discussion via GitHub MCP, then posts a concise review highlighting risks, security issues, missing tests, and next steps.", + "keywords": [ + "github", + "pull-request", + "review", + "code-review", + "automation", + "integration" + ], + "name": "github-pr-reviewer", + "source": "./skills/github-pr-reviewer" + }, + { + "category": "productivity", + "description": "Create an automation that drafts incident retrospectives by gathering incident-channel messages from Slack, collecting linked tickets from Linear, and publishing a retrospective draft to Notion with timeline, impact summary, root-cause hypotheses, and action items.", + "keywords": [ + "incident", + "retrospective", + "postmortem", + "slack", + "linear", + "notion", + "automation" + ], + "name": "incident-retrospective", + "source": "./skills/incident-retrospective" + }, + { + "category": "productivity", + "description": "Create an automation that triages new Linear issues by inspecting title, description, team, and recent related issues. Suggests labels, priority, likely owner, and potential duplicates, then posts a clarifying comment.", + "keywords": [ + "linear", + "triage", + "issues", + "labels", + "priority", + "automation", + "integration" + ], + "name": "linear-triage", + "source": "./skills/linear-triage" + }, + { + "category": "productivity", + "description": "Create a recurring automation that researches a topic using Tavily web search and publishes a structured brief to Notion with executive summary, key findings, implications, and source citations.", + "keywords": [ + "research", + "brief", + "tavily", + "notion", + "web-search", + "automation" + ], + "name": "research-brief", + "source": "./skills/research-brief" + }, + { + "category": "productivity", + "description": "Create an automation that generates an async standup digest from Slack. Searches selected channels for messages since the previous workday, groups updates by project, highlights blockers and decisions, and posts a summary to a target channel.", + "keywords": [ + "slack", + "standup", + "digest", + "summary", + "daily", + "cron", + "automation" + ], + "name": "slack-standup-digest", + "source": "./skills/slack-standup-digest" + }, + { + "category": "productivity", + "description": "Write and edit clear, accessible prose in a plain English content style: active voice, front-loaded content, sentence case, and accessible formatting.", + "keywords": [ + "plain-english" + ], + "name": "plain-english-content", + "source": "./skills/plain-english-content" + }, + { + "category": "productivity", + "description": "Deploy a cron-based OpenHands automation that watches a Jira Cloud project for issues labeled with a configurable label (default: create-pr) and spawns an agent conversation to create a GitHub pull request for each new issue found. The target GitHub repo is read from the ticket body - no repo parameter required at deploy time.", + "keywords": [ + "jira", + "atlassian" + ], + "name": "jira-issue-to-pr", + "source": "./skills/jira-issue-to-pr" + } + ] +} diff --git a/.plugin/marketplace.json b/.plugin/marketplace.json deleted file mode 120000 index adad5692..00000000 --- a/.plugin/marketplace.json +++ /dev/null @@ -1 +0,0 @@ -../marketplaces/openhands-extensions.json \ No newline at end of file diff --git a/.plugin/marketplace.json b/.plugin/marketplace.json new file mode 100644 index 00000000..55dbe082 --- /dev/null +++ b/.plugin/marketplace.json @@ -0,0 +1,752 @@ +{ + "metadata": { + "description": "Official skills and plugins for OpenHands — the open-source AI software engineer.", + "homepage": "https://github.com/OpenHands/extensions", + "maintainer": "OpenHands" + }, + "name": "openhands-extensions", + "owner": { + "email": "contact@all-hands.dev", + "name": "OpenHands" + }, + "plugins": [ + { + "category": "development", + "description": "Create file-based sub-agents as Markdown files — no Python code required. Guides the user through a structured interview and generates a ready-to-deploy .md agent file following the OpenHands SDK specification.", + "keywords": [ + "agent", + "sub-agent", + "file-based", + "markdown", + "no-code", + "create" + ], + "name": "agent-creator", + "source": "./skills/agent-creator" + }, + { + "category": "productivity", + "description": "Add (import) an OpenHands skill from a GitHub repository into the current workspace.", + "keywords": [ + "skill", + "import", + "github", + "sparse-checkout" + ], + "name": "add-skill", + "source": "./skills/add-skill" + }, + { + "category": "productivity", + "description": "Persist and retrieve repository-specific knowledge using AGENTS.md files. Use when you want to save important information about a codebase (build commands, code style, workflows) for future sessions.", + "keywords": [ + "memory", + "knowledge", + "persistence", + "agents" + ], + "name": "agent-memory", + "source": "./skills/agent-memory" + }, + { + "category": "development", + "description": "Guided workflow for building custom AI agents using the OpenHands Software Agent SDK. Use when you want to create a new agent through an interactive interview process that gathers requirements and generates implementation plans.", + "keywords": [ + "agent", + "sdk", + "builder", + "openhands" + ], + "name": "agent-sdk-builder", + "source": "./skills/agent-sdk-builder" + }, + { + "category": "development", + "description": "Simplifies and refines code across three dimensions - code reuse, code quality, and efficiency - while preserving all functionality. Analyzes recently modified code and provides actionable improvement suggestions.", + "keywords": [ + "simplify", + "refine", + "cleanup", + "code-quality", + "reuse", + "efficiency", + "refactor" + ], + "name": "code-simplifier", + "source": "./skills/code-simplifier" + }, + { + "category": "integration", + "description": "Create and manage OpenHands automations - scheduled tasks that run in sandboxes. Use the prompt preset to create automations from natural language, or manage existing automations.", + "keywords": [ + "automation", + "cron", + "scheduled-task", + "sandbox", + "openhands" + ], + "name": "openhands-automation", + "source": "./skills/openhands-automation" + }, + { + "category": "development", + "description": "Work effectively inside a local Agent Canvas environment, including local agent-server auth, safe workspace hygiene, and local conversation delegation.", + "keywords": [ + "agent-canvas", + "openhands", + "local", + "conversation", + "delegation" + ], + "name": "agent-canvas-environment", + "source": "./skills/agent-canvas-environment" + }, + { + "category": "development", + "description": "Reference skill for the OpenHands Software Agent SDK - build AI agents with custom tools, LLM configuration, conversations, sub-agent delegation, MCP integration, security, and persistence.", + "keywords": [ + "sdk", + "agent", + "openhands", + "tools", + "llm", + "conversation" + ], + "name": "openhands-sdk", + "source": "./skills/openhands-sdk" + }, + { + "category": "integration", + "description": "Interact with Azure DevOps repositories, pull requests, and APIs using the AZURE_DEVOPS_TOKEN environment variable. Use when working with code hosted on Azure DevOps or managing Azure DevOps resources.", + "keywords": [ + "azure", + "devops", + "git", + "pull-request" + ], + "name": "azure-devops", + "source": "./skills/azure-devops" + }, + { + "category": "integration", + "description": "Bitbucket integration hub. Detects whether the repository is on Bitbucket Cloud or Bitbucket Data Center and directs you to the matching detailed skill (bitbucket-cloud or bitbucket-data-center). Use for any Bitbucket repository or pull request task.", + "keywords": [ + "bitbucket", + "git", + "pull-request" + ], + "name": "bitbucket", + "source": "./skills/bitbucket" + }, + { + "category": "integration", + "description": "Bitbucket Cloud (bitbucket.org) specifics — authenticate with BITBUCKET_TOKEN, use the REST API v2, workspace/repo_slug repositories, and the create_bitbucket_pr tool. Loaded on demand by the bitbucket skill once a Cloud environment is detected.", + "keywords": [ + "bitbucket", + "bitbucket-cloud", + "git", + "pull-request" + ], + "name": "bitbucket-cloud", + "source": "./skills/bitbucket-cloud" + }, + { + "category": "integration", + "description": "Bitbucket Data Center (self-hosted Bitbucket Server) specifics — authenticate with BITBUCKET_DATA_CENTER_TOKEN, use the REST API 1.0, PROJECT/repo_slug repositories, scm/ git remotes, and the create_bitbucket_data_center_pr tool. Loaded on demand by the bitbucket skill once a Data Center environment is detected.", + "keywords": [ + "bitbucket", + "bitbucket-data-center", + "bitbucket-server", + "git", + "pull-request" + ], + "name": "bitbucket-data-center", + "source": "./skills/bitbucket-data-center" + }, + { + "category": "utilities", + "description": "Get current weather, time, and precipitation forecast for any city using the free Open-Meteo API. Provides slash command /city-weather:now .", + "keywords": [ + "weather", + "time", + "forecast", + "temperature", + "precipitation", + "sample" + ], + "name": "city-weather", + "source": "./plugins/city-weather" + }, + { + "category": "code-quality", + "description": "Rigorous code review focusing on data structures, simplicity, security, pragmatism, and risk/safety evaluation. Provides brutally honest, actionable feedback on pull requests or merge requests, including a risk assessment for every review. Use when reviewing code changes.", + "keywords": [ + "code-review", + "quality", + "security", + "style", + "risk" + ], + "name": "code-review", + "source": "./skills/code-review" + }, + { + "category": "monitoring", + "description": "Query and analyze Datadog logs, metrics, APM traces, and monitors using the Datadog API. Use when debugging production issues, monitoring application performance, or investigating alerts.", + "keywords": [ + "datadog", + "monitoring", + "logs", + "metrics", + "apm" + ], + "name": "datadog", + "source": "./skills/datadog" + }, + { + "category": "development", + "description": "Common project operations using Deno (tasks, run/test/lint/fmt, and dependency management).", + "keywords": [ + "deno", + "typescript", + "javascript", + "runtime" + ], + "name": "deno", + "source": "./skills/deno" + }, + { + "category": "integration", + "description": "Build and automate Discord integrations (bots, webhooks, slash commands, and REST API workflows). Use when the user mentions Discord, a Discord server/guild, channels, webhooks, bot tokens, slash commands/application commands, discord.js, or discord.py.", + "keywords": [ + "discord", + "bot", + "webhook", + "automation" + ], + "name": "discord", + "source": "./skills/discord" + }, + { + "category": "infrastructure", + "description": "Run Docker commands within a container environment, including starting the Docker daemon and managing containers. Use when building, running, or managing Docker containers and images.", + "keywords": [ + "docker", + "container", + "images" + ], + "name": "docker", + "source": "./skills/docker" + }, + { + "category": "testing", + "description": "A test skill that responds to the magic word 'flarglebargle' with a compliment. Use for testing skill activation and trigger functionality.", + "keywords": [ + "test", + "demo" + ], + "name": "flarglebargle", + "source": "./skills/flarglebargle" + }, + { + "category": "design", + "description": "Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts, posters, or applications. Generates creative, polished code and UI design that avoids generic AI aesthetics.", + "keywords": [ + "frontend", + "design", + "ui", + "web", + "react", + "html", + "css" + ], + "name": "frontend-design", + "source": "./skills/frontend-design" + }, + { + "category": "integration", + "description": "Interact with GitHub repositories, pull requests, issues, and workflows using the GITHUB_TOKEN environment variable and GitHub CLI. Use when working with code hosted on GitHub or managing GitHub resources.", + "keywords": [ + "github", + "git", + "pull-request", + "issues", + "workflows" + ], + "name": "github", + "source": "./skills/github" + }, + { + "category": "integration", + "description": "Create, debug, and test GitHub Actions workflows and custom actions. Use when building CI/CD pipelines, automating workflows, or troubleshooting GitHub Actions.", + "keywords": [ + "github-actions", + "workflows", + "ci-cd", + "automation", + "actions" + ], + "name": "github-actions", + "source": "./skills/github-actions" + }, + { + "category": "code-quality", + "description": "Post structured PR reviews to GitHub with inline comments/suggestions in a single API call.", + "keywords": [ + "github", + "pull-request", + "review", + "code-review" + ], + "name": "github-pr-review", + "source": "./skills/github-pr-review" + }, + { + "category": "productivity", + "description": "Create a cron automation that polls a GitHub repository for issue and PR comments containing a configurable trigger phrase (@OpenHands by default). Starts an OpenHands conversation with full issue/PR context, posts acknowledgement comments with a conversation link, and summarises results back to the issue/PR when the agent finishes.", + "keywords": [ + "github", + "monitor", + "issues", + "pull-requests", + "trigger", + "cron", + "automation", + "integration" + ], + "name": "github-repo-monitor", + "source": "./skills/github-repo-monitor" + }, + { + "category": "integration", + "description": "Interact with GitLab repositories, merge requests, and APIs using the GITLAB_TOKEN environment variable. Use when working with code hosted on GitLab or managing GitLab resources.", + "keywords": [ + "gitlab", + "git", + "merge-request" + ], + "name": "gitlab", + "source": "./skills/gitlab" + }, + { + "category": "data-science", + "description": "Read, modify, execute, and convert Jupyter notebooks programmatically. Use when working with .ipynb files for data science workflows, including editing cells, clearing outputs, or converting to other formats.", + "keywords": [ + "jupyter", + "notebook", + "ipynb", + "data-science" + ], + "name": "jupyter", + "source": "./skills/jupyter" + }, + { + "category": "infrastructure", + "description": "Set up and manage local Kubernetes clusters using KIND (Kubernetes IN Docker). Use when testing Kubernetes applications locally or developing cloud-native workloads.", + "keywords": [ + "kubernetes", + "k8s", + "kind", + "cloud-native" + ], + "name": "kubernetes", + "source": "./skills/kubernetes" + }, + { + "category": "code-quality", + "description": "Distill code review feedback from GitHub PRs into reusable skills and guidelines. Use when users ask to learn from code reviews, extract review patterns, or generate coding standards from historical PR feedback.", + "keywords": [ + "code-review", + "learning", + "skills", + "guidelines", + "pr-feedback" + ], + "name": "learn-from-code-review", + "source": "./skills/learn-from-code-review" + }, + { + "category": "integration", + "description": "Interact with Linear project management - query issues, update status, create tickets using the Linear GraphQL API.", + "keywords": [ + "linear", + "ticket", + "issue", + "project-management", + "graphql" + ], + "name": "linear", + "source": "./skills/linear" + }, + { + "category": "testing", + "description": "A simple test plugin for verifying plugin loading. Triggers on magic words (alakazam, abracadabra) and returns a specific phrase to confirm plugins are working.", + "keywords": [ + "test", + "magic", + "plugin", + "verification", + "sample" + ], + "name": "magic-test", + "source": "./plugins/magic-test" + }, + { + "category": "productivity", + "description": "Create, search, and update Notion pages/databases using the Notion API. Use for documenting work, generating runbooks, and automating knowledge base updates.", + "keywords": [ + "notion", + "documentation", + "knowledge-base" + ], + "name": "notion", + "source": "./skills/notion" + }, + { + "category": "development", + "description": "Handle npm package installation in non-interactive environments by piping confirmations. Use when installing Node.js packages that require user confirmation prompts.", + "keywords": [ + "npm", + "nodejs", + "packages" + ], + "name": "npm", + "source": "./skills/npm" + }, + { + "category": "productivity", + "description": "Assess repository agent-readiness across five pillars, propose high-impact fixes, and generate repo-specific AGENTS.md files.", + "keywords": [ + "onboarding", + "readiness", + "agents-md", + "agent-readiness", + "assessment" + ], + "name": "onboarding", + "source": "./plugins/onboarding" + }, + { + "category": "openhands", + "description": "Unified OpenHands plugin — bundles Cloud CLI, REST API (openhands-api), and Automations (openhands-automation) into a single plugin.", + "keywords": [ + "openhands", + "cloud", + "api", + "automation", + "cli" + ], + "name": "openhands", + "source": "./plugins/openhands" + }, + { + "category": "development", + "description": "Use the OpenHands Cloud REST API (V1) and agent-server APIs to create and manage Cloud or local backend conversations, including multi-conversation delegation workflows. Includes minimal Python and TypeScript clients under scripts/.", + "keywords": [ + "openhands", + "api", + "cloud", + "automation", + "delegation", + "agent-server", + "sandbox", + "conversations" + ], + "name": "openhands-api", + "source": "./skills/openhands-api" + }, + { + "category": "documentation", + "description": "Install and use pdflatex to compile LaTeX documents into PDFs on Linux. Use when generating academic papers, research publications, or any documents written in LaTeX.", + "keywords": [ + "latex", + "pdf", + "academic", + "documents" + ], + "name": "pdflatex", + "source": "./skills/pdflatex" + }, + { + "category": "code-quality", + "description": "Automated PR code review — analyzes diffs and posts inline review comments via the GitHub API.", + "keywords": [ + "pr-review", + "code-review", + "github", + "automation" + ], + "name": "pr-review", + "source": "./plugins/pr-review" + }, + { + "category": "quality-assurance", + "description": "Validate pull request changes by actually running the code — setting up the environment, exercising changed behavior, and posting a structured QA report.", + "keywords": [ + "qa", + "testing", + "pull-request", + "validation", + "automation" + ], + "name": "qa-changes", + "source": "./plugins/qa-changes" + }, + { + "category": "productivity", + "description": "Generate a Product Requirements Document (PRD) for a new feature through an interactive clarifying-question workflow. Use when planning a feature, starting a new project, or when asked to create a PRD.", + "keywords": [ + "prd", + "requirements", + "planning", + "product", + "specification" + ], + "name": "prd", + "source": "./skills/prd" + }, + { + "category": "productivity", + "description": "Generate consistent, well-structured release notes from git history. Produces categorized changelog with breaking changes, features, fixes, and contributor attribution.", + "keywords": [ + "release-notes", + "changelog", + "git", + "semver" + ], + "name": "release-notes", + "source": "./plugins/release-notes" + }, + { + "category": "security", + "description": "Security best practices for secure coding, authentication, authorization, and data protection. Use when developing features that handle sensitive data, user authentication, or require security review.", + "keywords": [ + "security", + "authentication", + "authorization", + "encryption" + ], + "name": "security", + "source": "./skills/security" + }, + { + "category": "development", + "description": "Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Claude's capabilities with specialized knowledge, workflows, or tool integrations.", + "keywords": [ + "skill", + "plugin", + "create" + ], + "name": "skill-creator", + "source": "./skills/skill-creator" + }, + { + "category": "productivity", + "description": "Create a cron automation that polls up to 10 Slack channels every minute and starts an OpenHands conversation when a configurable trigger phrase is detected. Forwards thread replies to running conversations and posts summaries back to Slack when the agent finishes.", + "keywords": [ + "slack", + "monitor", + "channel", + "trigger", + "cron", + "automation", + "integration" + ], + "name": "slack-channel-monitor", + "source": "./skills/slack-channel-monitor" + }, + { + "category": "infrastructure", + "description": "Establish and manage SSH connections to remote machines, including key generation, configuration, and file transfers. Use when connecting to remote servers, executing remote commands, or transferring files via SCP.", + "keywords": [ + "ssh", + "remote", + "scp", + "server" + ], + "name": "ssh", + "source": "./skills/ssh" + }, + { + "category": "development", + "description": "Install and configure Swift programming language on Debian Linux for server-side development. Use when building Swift applications on Linux or setting up a Swift development environment.", + "keywords": [ + "swift", + "linux", + "server-side" + ], + "name": "swift-linux", + "source": "./skills/swift-linux" + }, + { + "category": "design", + "description": "Toolkit for styling artifacts with a theme. These artifacts can be slides, docs, reportings, HTML landing pages, etc. There are 10 pre-set themes with colors/fonts that you can apply to any artifact that has been creating, or can generate a new theme on-the-fly.", + "keywords": [ + "theme", + "styling", + "design", + "slides", + "documents" + ], + "name": "theme-factory", + "source": "./skills/theme-factory" + }, + { + "category": "development", + "description": "Common project, dependency, and environment operations using uv.", + "keywords": [ + "uv", + "python", + "dependencies", + "venv" + ], + "name": "uv", + "source": "./skills/uv" + }, + { + "category": "integration", + "description": "Deploy and manage applications on Vercel, including preview deployments and deployment protection.", + "keywords": [ + "vercel", + "deployment", + "preview", + "hosting" + ], + "name": "vercel", + "source": "./skills/vercel" + }, + { + "category": "security", + "description": "Automated security vulnerability scanning and AI-powered remediation. Scans repositories, skips when no issues found, and creates PRs with fixes.", + "keywords": [ + "security", + "vulnerability", + "remediation", + "scanning", + "automation" + ], + "name": "vulnerability-remediation", + "source": "./plugins/vulnerability-remediation" + }, + { + "category": "productivity", + "description": "Iterate on a GitHub pull request — drive it through CI, code review, and QA until merge-ready. Monitors state, fixes failures, addresses review feedback, retries flaky checks, and pushes fixes in one continuous loop.", + "keywords": [ + "github", + "ci", + "review", + "qa", + "pull-request", + "iterate" + ], + "name": "iterate", + "source": "./skills/iterate" + }, + { + "category": "productivity", + "description": "Back factual claims and field values with official, verifiable sources. Use when the user asks to fill fields, answer questions, or make claims that must be supported by an exact quote and an official link.", + "keywords": [ + "evidence", + "citations", + "sources", + "verification", + "documentation", + "official" + ], + "name": "evidence-based-citations", + "source": "./skills/evidence-based-citations" + }, + { + "category": "productivity", + "description": "Create an automation that reviews GitHub pull requests when they are opened or updated. Inspects the diff, changed files, tests, and existing discussion via GitHub MCP, then posts a concise review highlighting risks, security issues, missing tests, and next steps.", + "keywords": [ + "github", + "pull-request", + "review", + "code-review", + "automation", + "integration" + ], + "name": "github-pr-reviewer", + "source": "./skills/github-pr-reviewer" + }, + { + "category": "productivity", + "description": "Create an automation that drafts incident retrospectives by gathering incident-channel messages from Slack, collecting linked tickets from Linear, and publishing a retrospective draft to Notion with timeline, impact summary, root-cause hypotheses, and action items.", + "keywords": [ + "incident", + "retrospective", + "postmortem", + "slack", + "linear", + "notion", + "automation" + ], + "name": "incident-retrospective", + "source": "./skills/incident-retrospective" + }, + { + "category": "productivity", + "description": "Create an automation that triages new Linear issues by inspecting title, description, team, and recent related issues. Suggests labels, priority, likely owner, and potential duplicates, then posts a clarifying comment.", + "keywords": [ + "linear", + "triage", + "issues", + "labels", + "priority", + "automation", + "integration" + ], + "name": "linear-triage", + "source": "./skills/linear-triage" + }, + { + "category": "productivity", + "description": "Create a recurring automation that researches a topic using Tavily web search and publishes a structured brief to Notion with executive summary, key findings, implications, and source citations.", + "keywords": [ + "research", + "brief", + "tavily", + "notion", + "web-search", + "automation" + ], + "name": "research-brief", + "source": "./skills/research-brief" + }, + { + "category": "productivity", + "description": "Create an automation that generates an async standup digest from Slack. Searches selected channels for messages since the previous workday, groups updates by project, highlights blockers and decisions, and posts a summary to a target channel.", + "keywords": [ + "slack", + "standup", + "digest", + "summary", + "daily", + "cron", + "automation" + ], + "name": "slack-standup-digest", + "source": "./skills/slack-standup-digest" + }, + { + "category": "productivity", + "description": "Write and edit clear, accessible prose in a plain English content style: active voice, front-loaded content, sentence case, and accessible formatting.", + "keywords": [ + "plain-english" + ], + "name": "plain-english-content", + "source": "./skills/plain-english-content" + }, + { + "category": "productivity", + "description": "Deploy a cron-based OpenHands automation that watches a Jira Cloud project for issues labeled with a configurable label (default: create-pr) and spawns an agent conversation to create a GitHub pull request for each new issue found. The target GitHub repo is read from the ticket body - no repo parameter required at deploy time.", + "keywords": [ + "jira", + "atlassian" + ], + "name": "jira-issue-to-pr", + "source": "./skills/jira-issue-to-pr" + } + ] +} diff --git a/AGENTS.md b/AGENTS.md index d14211fa..de5e84fd 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -105,7 +105,8 @@ When editing or adding skills in this repo, follow these rules (and add new skil ## CI / validation gotchas - The test suite expects **every directory under `skills/`** to be listed in a marketplace. If you add a new skill (or rebase onto a main branch that added skills), update the appropriate marketplace file or CI will fail with `Skills missing from marketplace: [...]`. -- `scripts/sync_extensions.py` keeps generated artifacts in sync: Claude Code command files, README catalog section, coverage checks, and vendor symlinks. Run `python scripts/sync_extensions.py --check` (or just push — CI runs it) to verify everything is consistent. Run without `--check` to auto-fix. The "Quick Start" section in `README.md` (OpenHands SDK, Claude Code, and Codex setup instructions) is **manually maintained** above the auto-generated catalog markers and is intentionally not generated by the sync script. +- `scripts/sync_extensions.py` keeps generated artifacts in sync: Claude Code command files, README catalog section, coverage checks, vendor symlinks, and root marketplace catalog copies. Run `python scripts/sync_extensions.py --check` (or just push — CI runs it) to verify everything is consistent. Run without `--check` to auto-fix. The "Quick Start" section in `README.md` (OpenHands SDK, Claude Code, and Codex setup instructions) is **manually maintained** above the auto-generated catalog markers and is intentionally not generated by the sync script. +- The repository root exposes the canonical marketplace catalog (`marketplaces/openhands-extensions.json`) as real `marketplace.json` copies under `.claude-plugin/`, `.codex-plugin/`, and `.plugin/` — **not symlinks**. `raw.githubusercontent.com` serves git symlinks as their literal target text and does not traverse symlinked directory paths, so symlinks made the catalog unreachable at the standard `.claude-plugin/marketplace.json` path (used by `github://openhands/extensions` consumers). The `root-marketplace` sync task keeps these copies byte-for-byte in sync with the canonical file; never replace them with symlinks. - The sync script uses PyYAML to parse SKILL.md frontmatter. If you add a skill with a slash trigger (e.g., `triggers: ["/mycommand"]`), the script auto-generates `commands/mycommand.md`. **Note:** Slash triggers in SKILL.md frontmatter are deprecated — prefer adding a `commands/command-name.md` file to the plugin's `commands/` directory instead. Keyword triggers (non-slash) remain the recommended way to activate skills by topic. ## OpenHands SDK documentation policy diff --git a/scripts/sync_extensions.py b/scripts/sync_extensions.py index 040ff241..b181e936 100644 --- a/scripts/sync_extensions.py +++ b/scripts/sync_extensions.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 """Keep the OpenHands extensions registry in sync. -Four sync tasks, runnable individually or all at once: +Five sync tasks, runnable individually or all at once: 1. **commands** — generate Claude Code ``commands/.md`` files from SKILL.md slash-triggers. @@ -10,6 +10,12 @@ marketplace, or a marketplace entry points to a missing directory. 4. **symlinks** — enforce ``.plugin/`` as the canonical manifest directory with vendor symlinks (``.claude-plugin``, ``.codex-plugin``). + 5. **root-marketplace** — keep real ``marketplace.json`` copies at the + repository root under ``.claude-plugin/``, ``.codex-plugin/``, and + ``.plugin/`` so consumers that fetch the catalog over the GitHub raw + URL (e.g. ``github://openhands/extensions``) can read it. Git symlinks + are stored as blobs and ``raw.githubusercontent.com`` does not + dereference them through directory paths, so these must be real files. Usage: python scripts/sync_extensions.py # run all, write changes @@ -18,6 +24,7 @@ python scripts/sync_extensions.py catalog # only regenerate README catalog python scripts/sync_extensions.py coverage # only check marketplace coverage python scripts/sync_extensions.py symlinks # only check/fix vendor symlinks + python scripts/sync_extensions.py root-marketplace # only sync root marketplace copies python scripts/sync_extensions.py commands catalog # combine sub-commands """ @@ -36,6 +43,14 @@ README_PATH = REPO_ROOT / "README.md" SKILL_DIRS = [REPO_ROOT / "skills", REPO_ROOT / "plugins"] MARKETPLACES_DIR = REPO_ROOT / "marketplaces" +# The canonical marketplace catalog that the registry publishes. The +# repository root exposes copies of this file (not symlinks) under the +# vendor directories below so that consumers fetching the catalog over the +# GitHub raw URL (``github://openhands/extensions``) can read it. +PRIMARY_MARKETPLACE = MARKETPLACES_DIR / "openhands-extensions.json" +# Vendor directories at the repository root that must each contain a real +# (non-symlink) ``marketplace.json`` copy of ``PRIMARY_MARKETPLACE``. +ROOT_MARKETPLACE_DIRS = [".claude-plugin", ".codex-plugin", ".plugin"] # Max description length in the catalog table. 120 chars fits GitHub's # diff viewer and rendered Markdown tables without horizontal scroll. MAX_DESC_LEN = 120 @@ -422,6 +437,82 @@ def sync_symlinks(*, check: bool) -> list[str]: return problems +# ── 5. Root marketplace copies ─────────────────────────────────────── + + +def _normalize_marketplace_bytes(raw: bytes) -> bytes: + """Serialize marketplace JSON with sorted keys + 2-space indent. + + Produces a canonical byte string so byte-for-byte equality checks work + regardless of incidental formatting differences in the source file. + """ + return (json.dumps(json.loads(raw), indent=2, ensure_ascii=False, sort_keys=True) + "\n").encode("utf-8") + + +def sync_root_marketplace(*, check: bool) -> list[str]: + """Ensure each root vendor directory has a real marketplace.json copy. + + The registry's canonical catalog lives at + ``marketplaces/openhands-extensions.json``. Historically the root exposed + it through a double symlink chain (``.claude-plugin`` -> ``.plugin`` and + ``.plugin/marketplace.json`` -> the canonical file). ``raw.githubusercontent.com`` + serves git symlinks as their literal target text and does not traverse + symlinked directory paths, so consumers fetching + ``.claude-plugin/marketplace.json`` over the raw URL (e.g. the + plugin-directory with ``MARKETPLACE_SOURCE=github://openhands/extensions``) + received a 404 (or the literal symlink body) and saw an empty catalog. + + This sync replaces those symlinks with real directory + file copies that + mirror the canonical catalog byte-for-byte, so the catalog is reachable + at every standard ``.claude-plugin/marketplace.json`` path while staying + in sync with the single source of truth. + """ + if not PRIMARY_MARKETPLACE.is_file(): + return [f"canonical marketplace missing: {PRIMARY_MARKETPLACE.relative_to(REPO_ROOT)}"] + + canonical = _normalize_marketplace_bytes(PRIMARY_MARKETPLACE.read_bytes()) + problems: list[str] = [] + + for vendor in ROOT_MARKETPLACE_DIRS: + vendor_dir = REPO_ROOT / vendor + target = vendor_dir / "marketplace.json" + rel = target.relative_to(REPO_ROOT) + + # Classify the vendor directory. + dir_ok = vendor_dir.is_dir() and not vendor_dir.is_symlink() + if vendor_dir.is_symlink(): + problems.append(f"symlinked dir: {vendor} -> {vendor_dir.readlink()}") + elif not vendor_dir.exists(): + problems.append(f"missing dir: {vendor}") + elif not dir_ok: + problems.append(f"not a directory: {vendor}") + + # Classify the marketplace.json file (if any). + file_ok = target.is_file() and not target.is_symlink() + if target.is_symlink(): + problems.append(f"symlinked file: {rel} -> {target.readlink()}") + elif target.exists() and not file_ok: + problems.append(f"not a regular file: {rel}") + elif file_ok: + current = _normalize_marketplace_bytes(target.read_bytes()) + if current != canonical: + problems.append(f"out of date: {rel}") + else: + problems.append(f"missing: {rel}") + + if not check: + # Rebuild a real directory + real file from scratch. + if vendor_dir.is_symlink() or (vendor_dir.exists() and not vendor_dir.is_dir()): + vendor_dir.unlink() + vendor_dir.mkdir(parents=True, exist_ok=True) + if target.is_symlink() or (target.exists() and not target.is_file()): + target.unlink() + if not target.exists() or _normalize_marketplace_bytes(target.read_bytes()) != canonical: + target.write_bytes(canonical) + + return problems + + # ── Main ───────────────────────────────────────────────────────────── ALL_SYNCS = { @@ -429,6 +520,7 @@ def sync_symlinks(*, check: bool) -> list[str]: "catalog": sync_catalog, "coverage": sync_coverage, "symlinks": sync_symlinks, + "root-marketplace": sync_root_marketplace, } diff --git a/tests/test_sync_extensions.py b/tests/test_sync_extensions.py index 8dfb703d..1cad1090 100644 --- a/tests/test_sync_extensions.py +++ b/tests/test_sync_extensions.py @@ -9,8 +9,11 @@ from sync_extensions import ( CMD_MARKER, CommandSpec, + PRIMARY_MARKETPLACE, REPO_ROOT, + ROOT_MARKETPLACE_DIRS, _entry_type, + _normalize_marketplace_bytes, build_command_content, collect_needed_commands, generate_catalog, @@ -18,6 +21,7 @@ parse_frontmatter, slash_triggers, sync_commands, + sync_root_marketplace, ) @@ -304,3 +308,122 @@ def test_all_source_paths_exist(self): f"{mp_file.name}: {plugin.get('name', '?')} source " f"'{src}' does not exist at {resolved}" ) + + +# ── root marketplace copies ────────────────────────────────────────── + +class TestRootMarketplace: + """The root vendor marketplace.json files must be real (non-symlink) copies. + + raw.githubusercontent.com does not dereference git symlinks through + directory paths, so consumers using the standard + ``.claude-plugin/marketplace.json`` path (e.g. plugin-directory with + ``MARKETPLACE_SOURCE=github://openhands/extensions``) need real files. + """ + + def test_vendor_dirs_are_real_directories(self): + for vendor in ROOT_MARKETPLACE_DIRS: + vendor_dir = REPO_ROOT / vendor + assert vendor_dir.is_dir(), f"{vendor}/ is not a directory" + assert not vendor_dir.is_symlink(), ( + f"{vendor} is a symlink; raw.githubusercontent.com cannot " + "traverse symlinked directory paths" + ) + + def test_marketplace_json_files_are_real_files(self): + for vendor in ROOT_MARKETPLACE_DIRS: + target = REPO_ROOT / vendor / "marketplace.json" + assert target.is_file(), f"{target} is missing" + assert not target.is_symlink(), ( + f"{target} is a symlink; raw.githubusercontent.com serves " + "symlink blobs as their literal target text, not the catalog" + ) + + def test_marketplace_json_matches_canonical(self): + canonical = _normalize_marketplace_bytes(PRIMARY_MARKETPLACE.read_bytes()) + for vendor in ROOT_MARKETPLACE_DIRS: + target = REPO_ROOT / vendor / "marketplace.json" + current = _normalize_marketplace_bytes(target.read_bytes()) + assert current == canonical, ( + f"{target.relative_to(REPO_ROOT)} is out of sync with " + f"{PRIMARY_MARKETPLACE.relative_to(REPO_ROOT)}" + ) + + def test_marketplace_json_is_valid_catalog(self): + import json + + canonical = json.loads(PRIMARY_MARKETPLACE.read_bytes()) + for vendor in ROOT_MARKETPLACE_DIRS: + target = REPO_ROOT / vendor / "marketplace.json" + data = json.loads(target.read_bytes()) + assert data.get("name") == canonical.get("name") + assert len(data.get("plugins", [])) == len(canonical.get("plugins", [])) + + def test_sync_root_marketplace_detects_and_fixes_symlinks(self, tmp_path, monkeypatch): + """sync_root_marketplace replaces symlinked dirs/files with real copies.""" + import json + + monkeypatch.setattr("sync_extensions.REPO_ROOT", tmp_path) + monkeypatch.setattr("sync_extensions.PRIMARY_MARKETPLACE", tmp_path / "marketplaces" / "openhands-extensions.json") + + # Canonical marketplace source. + mp_dir = tmp_path / "marketplaces" + mp_dir.mkdir() + canonical_data = {"name": "openhands-extensions", "plugins": [{"name": "x", "source": "./skills/x"}]} + canonical_bytes = (json.dumps(canonical_data, indent=2, ensure_ascii=False, sort_keys=True) + "\n").encode() + (mp_dir / "openhands-extensions.json").write_bytes(canonical_bytes) + + # Recreate the broken double-symlink chain from the issue. + plugin_dir = tmp_path / ".plugin" + plugin_dir.mkdir() + (plugin_dir / "marketplace.json").symlink_to("../marketplaces/openhands-extensions.json") + (tmp_path / ".claude-plugin").symlink_to(".plugin") + (tmp_path / ".codex-plugin").symlink_to(".plugin") + + # Check mode must report the symlinks as problems. + problems = sync_root_marketplace(check=True) + assert any("symlinked dir" in p for p in problems) + assert any("symlinked file" in p for p in problems) + + # Write mode fixes them. + sync_root_marketplace(check=False) + for vendor in [".claude-plugin", ".codex-plugin", ".plugin"]: + vendor_dir = tmp_path / vendor + target = vendor_dir / "marketplace.json" + assert vendor_dir.is_dir() and not vendor_dir.is_symlink(), f"{vendor} still a symlink dir" + assert target.is_file() and not target.is_symlink(), f"{target} still a symlink file" + assert _normalize_marketplace_bytes(target.read_bytes()) == canonical_bytes + + # After fixing, check mode is clean. + assert sync_root_marketplace(check=True) == [] + + def test_sync_root_marketplace_detects_stale_copy(self, tmp_path, monkeypatch): + """sync_root_marketplace reports (and fixes) an out-of-date real copy.""" + import json + + monkeypatch.setattr("sync_extensions.REPO_ROOT", tmp_path) + monkeypatch.setattr("sync_extensions.PRIMARY_MARKETPLACE", tmp_path / "marketplaces" / "openhands-extensions.json") + + mp_dir = tmp_path / "marketplaces" + mp_dir.mkdir() + canonical = {"name": "openhands-extensions", "plugins": [{"name": "x", "source": "./skills/x"}]} + canonical_bytes = (json.dumps(canonical, indent=2, ensure_ascii=False, sort_keys=True) + "\n").encode() + (mp_dir / "openhands-extensions.json").write_bytes(canonical_bytes) + + stale = {"name": "openhands-extensions", "plugins": []} + for vendor in [".claude-plugin", ".codex-plugin", ".plugin"]: + (tmp_path / vendor).mkdir() + (tmp_path / vendor / "marketplace.json").write_text(json.dumps(stale)) + + problems = sync_root_marketplace(check=True) + assert len(problems) == 3 + assert all("out of date" in p for p in problems) + + sync_root_marketplace(check=False) + for vendor in [".claude-plugin", ".codex-plugin", ".plugin"]: + assert _normalize_marketplace_bytes((tmp_path / vendor / "marketplace.json").read_bytes()) == canonical_bytes + assert sync_root_marketplace(check=True) == [] + + +if __name__ == "__main__": + pytest.main([__file__, "-v"]) From 640cf14824021e5184f5d979bfee74c4602f3c5b Mon Sep 17 00:00:00 2001 From: openhands Date: Wed, 8 Jul 2026 13:40:56 +0000 Subject: [PATCH 2/3] refactor: publish root catalog only at .plugin/marketplace.json Collapse the three root marketplace copies into a single canonical one at .plugin/marketplace.json (this repo's canonical manifest dir). Drop the root .claude-plugin/ and .codex-plugin/ mirrors entirely - they duplicated the catalog with no raw-URL benefit, since raw.githubusercontent.com cannot dereference symlinks and the real file already lives at .plugin/. Per-skill/per-plugin .claude-plugin and .codex-plugin vendor symlinks (within skills/ and plugins/) are unrelated and remain. Note: openhands/plugin-directory hardcodes .claude-plugin/marketplace.json as its fetch path, so it must be updated to fetch .plugin/marketplace.json for this to resolve #394 on its side. Co-authored-by: openhands --- .claude-plugin/marketplace.json | 752 -------------------------------- .codex-plugin/marketplace.json | 752 -------------------------------- AGENTS.md | 2 +- scripts/sync_extensions.py | 46 +- tests/test_sync_extensions.py | 54 +-- 5 files changed, 57 insertions(+), 1549 deletions(-) delete mode 100644 .claude-plugin/marketplace.json delete mode 100644 .codex-plugin/marketplace.json diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json deleted file mode 100644 index 55dbe082..00000000 --- a/.claude-plugin/marketplace.json +++ /dev/null @@ -1,752 +0,0 @@ -{ - "metadata": { - "description": "Official skills and plugins for OpenHands — the open-source AI software engineer.", - "homepage": "https://github.com/OpenHands/extensions", - "maintainer": "OpenHands" - }, - "name": "openhands-extensions", - "owner": { - "email": "contact@all-hands.dev", - "name": "OpenHands" - }, - "plugins": [ - { - "category": "development", - "description": "Create file-based sub-agents as Markdown files — no Python code required. Guides the user through a structured interview and generates a ready-to-deploy .md agent file following the OpenHands SDK specification.", - "keywords": [ - "agent", - "sub-agent", - "file-based", - "markdown", - "no-code", - "create" - ], - "name": "agent-creator", - "source": "./skills/agent-creator" - }, - { - "category": "productivity", - "description": "Add (import) an OpenHands skill from a GitHub repository into the current workspace.", - "keywords": [ - "skill", - "import", - "github", - "sparse-checkout" - ], - "name": "add-skill", - "source": "./skills/add-skill" - }, - { - "category": "productivity", - "description": "Persist and retrieve repository-specific knowledge using AGENTS.md files. Use when you want to save important information about a codebase (build commands, code style, workflows) for future sessions.", - "keywords": [ - "memory", - "knowledge", - "persistence", - "agents" - ], - "name": "agent-memory", - "source": "./skills/agent-memory" - }, - { - "category": "development", - "description": "Guided workflow for building custom AI agents using the OpenHands Software Agent SDK. Use when you want to create a new agent through an interactive interview process that gathers requirements and generates implementation plans.", - "keywords": [ - "agent", - "sdk", - "builder", - "openhands" - ], - "name": "agent-sdk-builder", - "source": "./skills/agent-sdk-builder" - }, - { - "category": "development", - "description": "Simplifies and refines code across three dimensions - code reuse, code quality, and efficiency - while preserving all functionality. Analyzes recently modified code and provides actionable improvement suggestions.", - "keywords": [ - "simplify", - "refine", - "cleanup", - "code-quality", - "reuse", - "efficiency", - "refactor" - ], - "name": "code-simplifier", - "source": "./skills/code-simplifier" - }, - { - "category": "integration", - "description": "Create and manage OpenHands automations - scheduled tasks that run in sandboxes. Use the prompt preset to create automations from natural language, or manage existing automations.", - "keywords": [ - "automation", - "cron", - "scheduled-task", - "sandbox", - "openhands" - ], - "name": "openhands-automation", - "source": "./skills/openhands-automation" - }, - { - "category": "development", - "description": "Work effectively inside a local Agent Canvas environment, including local agent-server auth, safe workspace hygiene, and local conversation delegation.", - "keywords": [ - "agent-canvas", - "openhands", - "local", - "conversation", - "delegation" - ], - "name": "agent-canvas-environment", - "source": "./skills/agent-canvas-environment" - }, - { - "category": "development", - "description": "Reference skill for the OpenHands Software Agent SDK - build AI agents with custom tools, LLM configuration, conversations, sub-agent delegation, MCP integration, security, and persistence.", - "keywords": [ - "sdk", - "agent", - "openhands", - "tools", - "llm", - "conversation" - ], - "name": "openhands-sdk", - "source": "./skills/openhands-sdk" - }, - { - "category": "integration", - "description": "Interact with Azure DevOps repositories, pull requests, and APIs using the AZURE_DEVOPS_TOKEN environment variable. Use when working with code hosted on Azure DevOps or managing Azure DevOps resources.", - "keywords": [ - "azure", - "devops", - "git", - "pull-request" - ], - "name": "azure-devops", - "source": "./skills/azure-devops" - }, - { - "category": "integration", - "description": "Bitbucket integration hub. Detects whether the repository is on Bitbucket Cloud or Bitbucket Data Center and directs you to the matching detailed skill (bitbucket-cloud or bitbucket-data-center). Use for any Bitbucket repository or pull request task.", - "keywords": [ - "bitbucket", - "git", - "pull-request" - ], - "name": "bitbucket", - "source": "./skills/bitbucket" - }, - { - "category": "integration", - "description": "Bitbucket Cloud (bitbucket.org) specifics — authenticate with BITBUCKET_TOKEN, use the REST API v2, workspace/repo_slug repositories, and the create_bitbucket_pr tool. Loaded on demand by the bitbucket skill once a Cloud environment is detected.", - "keywords": [ - "bitbucket", - "bitbucket-cloud", - "git", - "pull-request" - ], - "name": "bitbucket-cloud", - "source": "./skills/bitbucket-cloud" - }, - { - "category": "integration", - "description": "Bitbucket Data Center (self-hosted Bitbucket Server) specifics — authenticate with BITBUCKET_DATA_CENTER_TOKEN, use the REST API 1.0, PROJECT/repo_slug repositories, scm/ git remotes, and the create_bitbucket_data_center_pr tool. Loaded on demand by the bitbucket skill once a Data Center environment is detected.", - "keywords": [ - "bitbucket", - "bitbucket-data-center", - "bitbucket-server", - "git", - "pull-request" - ], - "name": "bitbucket-data-center", - "source": "./skills/bitbucket-data-center" - }, - { - "category": "utilities", - "description": "Get current weather, time, and precipitation forecast for any city using the free Open-Meteo API. Provides slash command /city-weather:now .", - "keywords": [ - "weather", - "time", - "forecast", - "temperature", - "precipitation", - "sample" - ], - "name": "city-weather", - "source": "./plugins/city-weather" - }, - { - "category": "code-quality", - "description": "Rigorous code review focusing on data structures, simplicity, security, pragmatism, and risk/safety evaluation. Provides brutally honest, actionable feedback on pull requests or merge requests, including a risk assessment for every review. Use when reviewing code changes.", - "keywords": [ - "code-review", - "quality", - "security", - "style", - "risk" - ], - "name": "code-review", - "source": "./skills/code-review" - }, - { - "category": "monitoring", - "description": "Query and analyze Datadog logs, metrics, APM traces, and monitors using the Datadog API. Use when debugging production issues, monitoring application performance, or investigating alerts.", - "keywords": [ - "datadog", - "monitoring", - "logs", - "metrics", - "apm" - ], - "name": "datadog", - "source": "./skills/datadog" - }, - { - "category": "development", - "description": "Common project operations using Deno (tasks, run/test/lint/fmt, and dependency management).", - "keywords": [ - "deno", - "typescript", - "javascript", - "runtime" - ], - "name": "deno", - "source": "./skills/deno" - }, - { - "category": "integration", - "description": "Build and automate Discord integrations (bots, webhooks, slash commands, and REST API workflows). Use when the user mentions Discord, a Discord server/guild, channels, webhooks, bot tokens, slash commands/application commands, discord.js, or discord.py.", - "keywords": [ - "discord", - "bot", - "webhook", - "automation" - ], - "name": "discord", - "source": "./skills/discord" - }, - { - "category": "infrastructure", - "description": "Run Docker commands within a container environment, including starting the Docker daemon and managing containers. Use when building, running, or managing Docker containers and images.", - "keywords": [ - "docker", - "container", - "images" - ], - "name": "docker", - "source": "./skills/docker" - }, - { - "category": "testing", - "description": "A test skill that responds to the magic word 'flarglebargle' with a compliment. Use for testing skill activation and trigger functionality.", - "keywords": [ - "test", - "demo" - ], - "name": "flarglebargle", - "source": "./skills/flarglebargle" - }, - { - "category": "design", - "description": "Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts, posters, or applications. Generates creative, polished code and UI design that avoids generic AI aesthetics.", - "keywords": [ - "frontend", - "design", - "ui", - "web", - "react", - "html", - "css" - ], - "name": "frontend-design", - "source": "./skills/frontend-design" - }, - { - "category": "integration", - "description": "Interact with GitHub repositories, pull requests, issues, and workflows using the GITHUB_TOKEN environment variable and GitHub CLI. Use when working with code hosted on GitHub or managing GitHub resources.", - "keywords": [ - "github", - "git", - "pull-request", - "issues", - "workflows" - ], - "name": "github", - "source": "./skills/github" - }, - { - "category": "integration", - "description": "Create, debug, and test GitHub Actions workflows and custom actions. Use when building CI/CD pipelines, automating workflows, or troubleshooting GitHub Actions.", - "keywords": [ - "github-actions", - "workflows", - "ci-cd", - "automation", - "actions" - ], - "name": "github-actions", - "source": "./skills/github-actions" - }, - { - "category": "code-quality", - "description": "Post structured PR reviews to GitHub with inline comments/suggestions in a single API call.", - "keywords": [ - "github", - "pull-request", - "review", - "code-review" - ], - "name": "github-pr-review", - "source": "./skills/github-pr-review" - }, - { - "category": "productivity", - "description": "Create a cron automation that polls a GitHub repository for issue and PR comments containing a configurable trigger phrase (@OpenHands by default). Starts an OpenHands conversation with full issue/PR context, posts acknowledgement comments with a conversation link, and summarises results back to the issue/PR when the agent finishes.", - "keywords": [ - "github", - "monitor", - "issues", - "pull-requests", - "trigger", - "cron", - "automation", - "integration" - ], - "name": "github-repo-monitor", - "source": "./skills/github-repo-monitor" - }, - { - "category": "integration", - "description": "Interact with GitLab repositories, merge requests, and APIs using the GITLAB_TOKEN environment variable. Use when working with code hosted on GitLab or managing GitLab resources.", - "keywords": [ - "gitlab", - "git", - "merge-request" - ], - "name": "gitlab", - "source": "./skills/gitlab" - }, - { - "category": "data-science", - "description": "Read, modify, execute, and convert Jupyter notebooks programmatically. Use when working with .ipynb files for data science workflows, including editing cells, clearing outputs, or converting to other formats.", - "keywords": [ - "jupyter", - "notebook", - "ipynb", - "data-science" - ], - "name": "jupyter", - "source": "./skills/jupyter" - }, - { - "category": "infrastructure", - "description": "Set up and manage local Kubernetes clusters using KIND (Kubernetes IN Docker). Use when testing Kubernetes applications locally or developing cloud-native workloads.", - "keywords": [ - "kubernetes", - "k8s", - "kind", - "cloud-native" - ], - "name": "kubernetes", - "source": "./skills/kubernetes" - }, - { - "category": "code-quality", - "description": "Distill code review feedback from GitHub PRs into reusable skills and guidelines. Use when users ask to learn from code reviews, extract review patterns, or generate coding standards from historical PR feedback.", - "keywords": [ - "code-review", - "learning", - "skills", - "guidelines", - "pr-feedback" - ], - "name": "learn-from-code-review", - "source": "./skills/learn-from-code-review" - }, - { - "category": "integration", - "description": "Interact with Linear project management - query issues, update status, create tickets using the Linear GraphQL API.", - "keywords": [ - "linear", - "ticket", - "issue", - "project-management", - "graphql" - ], - "name": "linear", - "source": "./skills/linear" - }, - { - "category": "testing", - "description": "A simple test plugin for verifying plugin loading. Triggers on magic words (alakazam, abracadabra) and returns a specific phrase to confirm plugins are working.", - "keywords": [ - "test", - "magic", - "plugin", - "verification", - "sample" - ], - "name": "magic-test", - "source": "./plugins/magic-test" - }, - { - "category": "productivity", - "description": "Create, search, and update Notion pages/databases using the Notion API. Use for documenting work, generating runbooks, and automating knowledge base updates.", - "keywords": [ - "notion", - "documentation", - "knowledge-base" - ], - "name": "notion", - "source": "./skills/notion" - }, - { - "category": "development", - "description": "Handle npm package installation in non-interactive environments by piping confirmations. Use when installing Node.js packages that require user confirmation prompts.", - "keywords": [ - "npm", - "nodejs", - "packages" - ], - "name": "npm", - "source": "./skills/npm" - }, - { - "category": "productivity", - "description": "Assess repository agent-readiness across five pillars, propose high-impact fixes, and generate repo-specific AGENTS.md files.", - "keywords": [ - "onboarding", - "readiness", - "agents-md", - "agent-readiness", - "assessment" - ], - "name": "onboarding", - "source": "./plugins/onboarding" - }, - { - "category": "openhands", - "description": "Unified OpenHands plugin — bundles Cloud CLI, REST API (openhands-api), and Automations (openhands-automation) into a single plugin.", - "keywords": [ - "openhands", - "cloud", - "api", - "automation", - "cli" - ], - "name": "openhands", - "source": "./plugins/openhands" - }, - { - "category": "development", - "description": "Use the OpenHands Cloud REST API (V1) and agent-server APIs to create and manage Cloud or local backend conversations, including multi-conversation delegation workflows. Includes minimal Python and TypeScript clients under scripts/.", - "keywords": [ - "openhands", - "api", - "cloud", - "automation", - "delegation", - "agent-server", - "sandbox", - "conversations" - ], - "name": "openhands-api", - "source": "./skills/openhands-api" - }, - { - "category": "documentation", - "description": "Install and use pdflatex to compile LaTeX documents into PDFs on Linux. Use when generating academic papers, research publications, or any documents written in LaTeX.", - "keywords": [ - "latex", - "pdf", - "academic", - "documents" - ], - "name": "pdflatex", - "source": "./skills/pdflatex" - }, - { - "category": "code-quality", - "description": "Automated PR code review — analyzes diffs and posts inline review comments via the GitHub API.", - "keywords": [ - "pr-review", - "code-review", - "github", - "automation" - ], - "name": "pr-review", - "source": "./plugins/pr-review" - }, - { - "category": "quality-assurance", - "description": "Validate pull request changes by actually running the code — setting up the environment, exercising changed behavior, and posting a structured QA report.", - "keywords": [ - "qa", - "testing", - "pull-request", - "validation", - "automation" - ], - "name": "qa-changes", - "source": "./plugins/qa-changes" - }, - { - "category": "productivity", - "description": "Generate a Product Requirements Document (PRD) for a new feature through an interactive clarifying-question workflow. Use when planning a feature, starting a new project, or when asked to create a PRD.", - "keywords": [ - "prd", - "requirements", - "planning", - "product", - "specification" - ], - "name": "prd", - "source": "./skills/prd" - }, - { - "category": "productivity", - "description": "Generate consistent, well-structured release notes from git history. Produces categorized changelog with breaking changes, features, fixes, and contributor attribution.", - "keywords": [ - "release-notes", - "changelog", - "git", - "semver" - ], - "name": "release-notes", - "source": "./plugins/release-notes" - }, - { - "category": "security", - "description": "Security best practices for secure coding, authentication, authorization, and data protection. Use when developing features that handle sensitive data, user authentication, or require security review.", - "keywords": [ - "security", - "authentication", - "authorization", - "encryption" - ], - "name": "security", - "source": "./skills/security" - }, - { - "category": "development", - "description": "Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Claude's capabilities with specialized knowledge, workflows, or tool integrations.", - "keywords": [ - "skill", - "plugin", - "create" - ], - "name": "skill-creator", - "source": "./skills/skill-creator" - }, - { - "category": "productivity", - "description": "Create a cron automation that polls up to 10 Slack channels every minute and starts an OpenHands conversation when a configurable trigger phrase is detected. Forwards thread replies to running conversations and posts summaries back to Slack when the agent finishes.", - "keywords": [ - "slack", - "monitor", - "channel", - "trigger", - "cron", - "automation", - "integration" - ], - "name": "slack-channel-monitor", - "source": "./skills/slack-channel-monitor" - }, - { - "category": "infrastructure", - "description": "Establish and manage SSH connections to remote machines, including key generation, configuration, and file transfers. Use when connecting to remote servers, executing remote commands, or transferring files via SCP.", - "keywords": [ - "ssh", - "remote", - "scp", - "server" - ], - "name": "ssh", - "source": "./skills/ssh" - }, - { - "category": "development", - "description": "Install and configure Swift programming language on Debian Linux for server-side development. Use when building Swift applications on Linux or setting up a Swift development environment.", - "keywords": [ - "swift", - "linux", - "server-side" - ], - "name": "swift-linux", - "source": "./skills/swift-linux" - }, - { - "category": "design", - "description": "Toolkit for styling artifacts with a theme. These artifacts can be slides, docs, reportings, HTML landing pages, etc. There are 10 pre-set themes with colors/fonts that you can apply to any artifact that has been creating, or can generate a new theme on-the-fly.", - "keywords": [ - "theme", - "styling", - "design", - "slides", - "documents" - ], - "name": "theme-factory", - "source": "./skills/theme-factory" - }, - { - "category": "development", - "description": "Common project, dependency, and environment operations using uv.", - "keywords": [ - "uv", - "python", - "dependencies", - "venv" - ], - "name": "uv", - "source": "./skills/uv" - }, - { - "category": "integration", - "description": "Deploy and manage applications on Vercel, including preview deployments and deployment protection.", - "keywords": [ - "vercel", - "deployment", - "preview", - "hosting" - ], - "name": "vercel", - "source": "./skills/vercel" - }, - { - "category": "security", - "description": "Automated security vulnerability scanning and AI-powered remediation. Scans repositories, skips when no issues found, and creates PRs with fixes.", - "keywords": [ - "security", - "vulnerability", - "remediation", - "scanning", - "automation" - ], - "name": "vulnerability-remediation", - "source": "./plugins/vulnerability-remediation" - }, - { - "category": "productivity", - "description": "Iterate on a GitHub pull request — drive it through CI, code review, and QA until merge-ready. Monitors state, fixes failures, addresses review feedback, retries flaky checks, and pushes fixes in one continuous loop.", - "keywords": [ - "github", - "ci", - "review", - "qa", - "pull-request", - "iterate" - ], - "name": "iterate", - "source": "./skills/iterate" - }, - { - "category": "productivity", - "description": "Back factual claims and field values with official, verifiable sources. Use when the user asks to fill fields, answer questions, or make claims that must be supported by an exact quote and an official link.", - "keywords": [ - "evidence", - "citations", - "sources", - "verification", - "documentation", - "official" - ], - "name": "evidence-based-citations", - "source": "./skills/evidence-based-citations" - }, - { - "category": "productivity", - "description": "Create an automation that reviews GitHub pull requests when they are opened or updated. Inspects the diff, changed files, tests, and existing discussion via GitHub MCP, then posts a concise review highlighting risks, security issues, missing tests, and next steps.", - "keywords": [ - "github", - "pull-request", - "review", - "code-review", - "automation", - "integration" - ], - "name": "github-pr-reviewer", - "source": "./skills/github-pr-reviewer" - }, - { - "category": "productivity", - "description": "Create an automation that drafts incident retrospectives by gathering incident-channel messages from Slack, collecting linked tickets from Linear, and publishing a retrospective draft to Notion with timeline, impact summary, root-cause hypotheses, and action items.", - "keywords": [ - "incident", - "retrospective", - "postmortem", - "slack", - "linear", - "notion", - "automation" - ], - "name": "incident-retrospective", - "source": "./skills/incident-retrospective" - }, - { - "category": "productivity", - "description": "Create an automation that triages new Linear issues by inspecting title, description, team, and recent related issues. Suggests labels, priority, likely owner, and potential duplicates, then posts a clarifying comment.", - "keywords": [ - "linear", - "triage", - "issues", - "labels", - "priority", - "automation", - "integration" - ], - "name": "linear-triage", - "source": "./skills/linear-triage" - }, - { - "category": "productivity", - "description": "Create a recurring automation that researches a topic using Tavily web search and publishes a structured brief to Notion with executive summary, key findings, implications, and source citations.", - "keywords": [ - "research", - "brief", - "tavily", - "notion", - "web-search", - "automation" - ], - "name": "research-brief", - "source": "./skills/research-brief" - }, - { - "category": "productivity", - "description": "Create an automation that generates an async standup digest from Slack. Searches selected channels for messages since the previous workday, groups updates by project, highlights blockers and decisions, and posts a summary to a target channel.", - "keywords": [ - "slack", - "standup", - "digest", - "summary", - "daily", - "cron", - "automation" - ], - "name": "slack-standup-digest", - "source": "./skills/slack-standup-digest" - }, - { - "category": "productivity", - "description": "Write and edit clear, accessible prose in a plain English content style: active voice, front-loaded content, sentence case, and accessible formatting.", - "keywords": [ - "plain-english" - ], - "name": "plain-english-content", - "source": "./skills/plain-english-content" - }, - { - "category": "productivity", - "description": "Deploy a cron-based OpenHands automation that watches a Jira Cloud project for issues labeled with a configurable label (default: create-pr) and spawns an agent conversation to create a GitHub pull request for each new issue found. The target GitHub repo is read from the ticket body - no repo parameter required at deploy time.", - "keywords": [ - "jira", - "atlassian" - ], - "name": "jira-issue-to-pr", - "source": "./skills/jira-issue-to-pr" - } - ] -} diff --git a/.codex-plugin/marketplace.json b/.codex-plugin/marketplace.json deleted file mode 100644 index 55dbe082..00000000 --- a/.codex-plugin/marketplace.json +++ /dev/null @@ -1,752 +0,0 @@ -{ - "metadata": { - "description": "Official skills and plugins for OpenHands — the open-source AI software engineer.", - "homepage": "https://github.com/OpenHands/extensions", - "maintainer": "OpenHands" - }, - "name": "openhands-extensions", - "owner": { - "email": "contact@all-hands.dev", - "name": "OpenHands" - }, - "plugins": [ - { - "category": "development", - "description": "Create file-based sub-agents as Markdown files — no Python code required. Guides the user through a structured interview and generates a ready-to-deploy .md agent file following the OpenHands SDK specification.", - "keywords": [ - "agent", - "sub-agent", - "file-based", - "markdown", - "no-code", - "create" - ], - "name": "agent-creator", - "source": "./skills/agent-creator" - }, - { - "category": "productivity", - "description": "Add (import) an OpenHands skill from a GitHub repository into the current workspace.", - "keywords": [ - "skill", - "import", - "github", - "sparse-checkout" - ], - "name": "add-skill", - "source": "./skills/add-skill" - }, - { - "category": "productivity", - "description": "Persist and retrieve repository-specific knowledge using AGENTS.md files. Use when you want to save important information about a codebase (build commands, code style, workflows) for future sessions.", - "keywords": [ - "memory", - "knowledge", - "persistence", - "agents" - ], - "name": "agent-memory", - "source": "./skills/agent-memory" - }, - { - "category": "development", - "description": "Guided workflow for building custom AI agents using the OpenHands Software Agent SDK. Use when you want to create a new agent through an interactive interview process that gathers requirements and generates implementation plans.", - "keywords": [ - "agent", - "sdk", - "builder", - "openhands" - ], - "name": "agent-sdk-builder", - "source": "./skills/agent-sdk-builder" - }, - { - "category": "development", - "description": "Simplifies and refines code across three dimensions - code reuse, code quality, and efficiency - while preserving all functionality. Analyzes recently modified code and provides actionable improvement suggestions.", - "keywords": [ - "simplify", - "refine", - "cleanup", - "code-quality", - "reuse", - "efficiency", - "refactor" - ], - "name": "code-simplifier", - "source": "./skills/code-simplifier" - }, - { - "category": "integration", - "description": "Create and manage OpenHands automations - scheduled tasks that run in sandboxes. Use the prompt preset to create automations from natural language, or manage existing automations.", - "keywords": [ - "automation", - "cron", - "scheduled-task", - "sandbox", - "openhands" - ], - "name": "openhands-automation", - "source": "./skills/openhands-automation" - }, - { - "category": "development", - "description": "Work effectively inside a local Agent Canvas environment, including local agent-server auth, safe workspace hygiene, and local conversation delegation.", - "keywords": [ - "agent-canvas", - "openhands", - "local", - "conversation", - "delegation" - ], - "name": "agent-canvas-environment", - "source": "./skills/agent-canvas-environment" - }, - { - "category": "development", - "description": "Reference skill for the OpenHands Software Agent SDK - build AI agents with custom tools, LLM configuration, conversations, sub-agent delegation, MCP integration, security, and persistence.", - "keywords": [ - "sdk", - "agent", - "openhands", - "tools", - "llm", - "conversation" - ], - "name": "openhands-sdk", - "source": "./skills/openhands-sdk" - }, - { - "category": "integration", - "description": "Interact with Azure DevOps repositories, pull requests, and APIs using the AZURE_DEVOPS_TOKEN environment variable. Use when working with code hosted on Azure DevOps or managing Azure DevOps resources.", - "keywords": [ - "azure", - "devops", - "git", - "pull-request" - ], - "name": "azure-devops", - "source": "./skills/azure-devops" - }, - { - "category": "integration", - "description": "Bitbucket integration hub. Detects whether the repository is on Bitbucket Cloud or Bitbucket Data Center and directs you to the matching detailed skill (bitbucket-cloud or bitbucket-data-center). Use for any Bitbucket repository or pull request task.", - "keywords": [ - "bitbucket", - "git", - "pull-request" - ], - "name": "bitbucket", - "source": "./skills/bitbucket" - }, - { - "category": "integration", - "description": "Bitbucket Cloud (bitbucket.org) specifics — authenticate with BITBUCKET_TOKEN, use the REST API v2, workspace/repo_slug repositories, and the create_bitbucket_pr tool. Loaded on demand by the bitbucket skill once a Cloud environment is detected.", - "keywords": [ - "bitbucket", - "bitbucket-cloud", - "git", - "pull-request" - ], - "name": "bitbucket-cloud", - "source": "./skills/bitbucket-cloud" - }, - { - "category": "integration", - "description": "Bitbucket Data Center (self-hosted Bitbucket Server) specifics — authenticate with BITBUCKET_DATA_CENTER_TOKEN, use the REST API 1.0, PROJECT/repo_slug repositories, scm/ git remotes, and the create_bitbucket_data_center_pr tool. Loaded on demand by the bitbucket skill once a Data Center environment is detected.", - "keywords": [ - "bitbucket", - "bitbucket-data-center", - "bitbucket-server", - "git", - "pull-request" - ], - "name": "bitbucket-data-center", - "source": "./skills/bitbucket-data-center" - }, - { - "category": "utilities", - "description": "Get current weather, time, and precipitation forecast for any city using the free Open-Meteo API. Provides slash command /city-weather:now .", - "keywords": [ - "weather", - "time", - "forecast", - "temperature", - "precipitation", - "sample" - ], - "name": "city-weather", - "source": "./plugins/city-weather" - }, - { - "category": "code-quality", - "description": "Rigorous code review focusing on data structures, simplicity, security, pragmatism, and risk/safety evaluation. Provides brutally honest, actionable feedback on pull requests or merge requests, including a risk assessment for every review. Use when reviewing code changes.", - "keywords": [ - "code-review", - "quality", - "security", - "style", - "risk" - ], - "name": "code-review", - "source": "./skills/code-review" - }, - { - "category": "monitoring", - "description": "Query and analyze Datadog logs, metrics, APM traces, and monitors using the Datadog API. Use when debugging production issues, monitoring application performance, or investigating alerts.", - "keywords": [ - "datadog", - "monitoring", - "logs", - "metrics", - "apm" - ], - "name": "datadog", - "source": "./skills/datadog" - }, - { - "category": "development", - "description": "Common project operations using Deno (tasks, run/test/lint/fmt, and dependency management).", - "keywords": [ - "deno", - "typescript", - "javascript", - "runtime" - ], - "name": "deno", - "source": "./skills/deno" - }, - { - "category": "integration", - "description": "Build and automate Discord integrations (bots, webhooks, slash commands, and REST API workflows). Use when the user mentions Discord, a Discord server/guild, channels, webhooks, bot tokens, slash commands/application commands, discord.js, or discord.py.", - "keywords": [ - "discord", - "bot", - "webhook", - "automation" - ], - "name": "discord", - "source": "./skills/discord" - }, - { - "category": "infrastructure", - "description": "Run Docker commands within a container environment, including starting the Docker daemon and managing containers. Use when building, running, or managing Docker containers and images.", - "keywords": [ - "docker", - "container", - "images" - ], - "name": "docker", - "source": "./skills/docker" - }, - { - "category": "testing", - "description": "A test skill that responds to the magic word 'flarglebargle' with a compliment. Use for testing skill activation and trigger functionality.", - "keywords": [ - "test", - "demo" - ], - "name": "flarglebargle", - "source": "./skills/flarglebargle" - }, - { - "category": "design", - "description": "Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts, posters, or applications. Generates creative, polished code and UI design that avoids generic AI aesthetics.", - "keywords": [ - "frontend", - "design", - "ui", - "web", - "react", - "html", - "css" - ], - "name": "frontend-design", - "source": "./skills/frontend-design" - }, - { - "category": "integration", - "description": "Interact with GitHub repositories, pull requests, issues, and workflows using the GITHUB_TOKEN environment variable and GitHub CLI. Use when working with code hosted on GitHub or managing GitHub resources.", - "keywords": [ - "github", - "git", - "pull-request", - "issues", - "workflows" - ], - "name": "github", - "source": "./skills/github" - }, - { - "category": "integration", - "description": "Create, debug, and test GitHub Actions workflows and custom actions. Use when building CI/CD pipelines, automating workflows, or troubleshooting GitHub Actions.", - "keywords": [ - "github-actions", - "workflows", - "ci-cd", - "automation", - "actions" - ], - "name": "github-actions", - "source": "./skills/github-actions" - }, - { - "category": "code-quality", - "description": "Post structured PR reviews to GitHub with inline comments/suggestions in a single API call.", - "keywords": [ - "github", - "pull-request", - "review", - "code-review" - ], - "name": "github-pr-review", - "source": "./skills/github-pr-review" - }, - { - "category": "productivity", - "description": "Create a cron automation that polls a GitHub repository for issue and PR comments containing a configurable trigger phrase (@OpenHands by default). Starts an OpenHands conversation with full issue/PR context, posts acknowledgement comments with a conversation link, and summarises results back to the issue/PR when the agent finishes.", - "keywords": [ - "github", - "monitor", - "issues", - "pull-requests", - "trigger", - "cron", - "automation", - "integration" - ], - "name": "github-repo-monitor", - "source": "./skills/github-repo-monitor" - }, - { - "category": "integration", - "description": "Interact with GitLab repositories, merge requests, and APIs using the GITLAB_TOKEN environment variable. Use when working with code hosted on GitLab or managing GitLab resources.", - "keywords": [ - "gitlab", - "git", - "merge-request" - ], - "name": "gitlab", - "source": "./skills/gitlab" - }, - { - "category": "data-science", - "description": "Read, modify, execute, and convert Jupyter notebooks programmatically. Use when working with .ipynb files for data science workflows, including editing cells, clearing outputs, or converting to other formats.", - "keywords": [ - "jupyter", - "notebook", - "ipynb", - "data-science" - ], - "name": "jupyter", - "source": "./skills/jupyter" - }, - { - "category": "infrastructure", - "description": "Set up and manage local Kubernetes clusters using KIND (Kubernetes IN Docker). Use when testing Kubernetes applications locally or developing cloud-native workloads.", - "keywords": [ - "kubernetes", - "k8s", - "kind", - "cloud-native" - ], - "name": "kubernetes", - "source": "./skills/kubernetes" - }, - { - "category": "code-quality", - "description": "Distill code review feedback from GitHub PRs into reusable skills and guidelines. Use when users ask to learn from code reviews, extract review patterns, or generate coding standards from historical PR feedback.", - "keywords": [ - "code-review", - "learning", - "skills", - "guidelines", - "pr-feedback" - ], - "name": "learn-from-code-review", - "source": "./skills/learn-from-code-review" - }, - { - "category": "integration", - "description": "Interact with Linear project management - query issues, update status, create tickets using the Linear GraphQL API.", - "keywords": [ - "linear", - "ticket", - "issue", - "project-management", - "graphql" - ], - "name": "linear", - "source": "./skills/linear" - }, - { - "category": "testing", - "description": "A simple test plugin for verifying plugin loading. Triggers on magic words (alakazam, abracadabra) and returns a specific phrase to confirm plugins are working.", - "keywords": [ - "test", - "magic", - "plugin", - "verification", - "sample" - ], - "name": "magic-test", - "source": "./plugins/magic-test" - }, - { - "category": "productivity", - "description": "Create, search, and update Notion pages/databases using the Notion API. Use for documenting work, generating runbooks, and automating knowledge base updates.", - "keywords": [ - "notion", - "documentation", - "knowledge-base" - ], - "name": "notion", - "source": "./skills/notion" - }, - { - "category": "development", - "description": "Handle npm package installation in non-interactive environments by piping confirmations. Use when installing Node.js packages that require user confirmation prompts.", - "keywords": [ - "npm", - "nodejs", - "packages" - ], - "name": "npm", - "source": "./skills/npm" - }, - { - "category": "productivity", - "description": "Assess repository agent-readiness across five pillars, propose high-impact fixes, and generate repo-specific AGENTS.md files.", - "keywords": [ - "onboarding", - "readiness", - "agents-md", - "agent-readiness", - "assessment" - ], - "name": "onboarding", - "source": "./plugins/onboarding" - }, - { - "category": "openhands", - "description": "Unified OpenHands plugin — bundles Cloud CLI, REST API (openhands-api), and Automations (openhands-automation) into a single plugin.", - "keywords": [ - "openhands", - "cloud", - "api", - "automation", - "cli" - ], - "name": "openhands", - "source": "./plugins/openhands" - }, - { - "category": "development", - "description": "Use the OpenHands Cloud REST API (V1) and agent-server APIs to create and manage Cloud or local backend conversations, including multi-conversation delegation workflows. Includes minimal Python and TypeScript clients under scripts/.", - "keywords": [ - "openhands", - "api", - "cloud", - "automation", - "delegation", - "agent-server", - "sandbox", - "conversations" - ], - "name": "openhands-api", - "source": "./skills/openhands-api" - }, - { - "category": "documentation", - "description": "Install and use pdflatex to compile LaTeX documents into PDFs on Linux. Use when generating academic papers, research publications, or any documents written in LaTeX.", - "keywords": [ - "latex", - "pdf", - "academic", - "documents" - ], - "name": "pdflatex", - "source": "./skills/pdflatex" - }, - { - "category": "code-quality", - "description": "Automated PR code review — analyzes diffs and posts inline review comments via the GitHub API.", - "keywords": [ - "pr-review", - "code-review", - "github", - "automation" - ], - "name": "pr-review", - "source": "./plugins/pr-review" - }, - { - "category": "quality-assurance", - "description": "Validate pull request changes by actually running the code — setting up the environment, exercising changed behavior, and posting a structured QA report.", - "keywords": [ - "qa", - "testing", - "pull-request", - "validation", - "automation" - ], - "name": "qa-changes", - "source": "./plugins/qa-changes" - }, - { - "category": "productivity", - "description": "Generate a Product Requirements Document (PRD) for a new feature through an interactive clarifying-question workflow. Use when planning a feature, starting a new project, or when asked to create a PRD.", - "keywords": [ - "prd", - "requirements", - "planning", - "product", - "specification" - ], - "name": "prd", - "source": "./skills/prd" - }, - { - "category": "productivity", - "description": "Generate consistent, well-structured release notes from git history. Produces categorized changelog with breaking changes, features, fixes, and contributor attribution.", - "keywords": [ - "release-notes", - "changelog", - "git", - "semver" - ], - "name": "release-notes", - "source": "./plugins/release-notes" - }, - { - "category": "security", - "description": "Security best practices for secure coding, authentication, authorization, and data protection. Use when developing features that handle sensitive data, user authentication, or require security review.", - "keywords": [ - "security", - "authentication", - "authorization", - "encryption" - ], - "name": "security", - "source": "./skills/security" - }, - { - "category": "development", - "description": "Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Claude's capabilities with specialized knowledge, workflows, or tool integrations.", - "keywords": [ - "skill", - "plugin", - "create" - ], - "name": "skill-creator", - "source": "./skills/skill-creator" - }, - { - "category": "productivity", - "description": "Create a cron automation that polls up to 10 Slack channels every minute and starts an OpenHands conversation when a configurable trigger phrase is detected. Forwards thread replies to running conversations and posts summaries back to Slack when the agent finishes.", - "keywords": [ - "slack", - "monitor", - "channel", - "trigger", - "cron", - "automation", - "integration" - ], - "name": "slack-channel-monitor", - "source": "./skills/slack-channel-monitor" - }, - { - "category": "infrastructure", - "description": "Establish and manage SSH connections to remote machines, including key generation, configuration, and file transfers. Use when connecting to remote servers, executing remote commands, or transferring files via SCP.", - "keywords": [ - "ssh", - "remote", - "scp", - "server" - ], - "name": "ssh", - "source": "./skills/ssh" - }, - { - "category": "development", - "description": "Install and configure Swift programming language on Debian Linux for server-side development. Use when building Swift applications on Linux or setting up a Swift development environment.", - "keywords": [ - "swift", - "linux", - "server-side" - ], - "name": "swift-linux", - "source": "./skills/swift-linux" - }, - { - "category": "design", - "description": "Toolkit for styling artifacts with a theme. These artifacts can be slides, docs, reportings, HTML landing pages, etc. There are 10 pre-set themes with colors/fonts that you can apply to any artifact that has been creating, or can generate a new theme on-the-fly.", - "keywords": [ - "theme", - "styling", - "design", - "slides", - "documents" - ], - "name": "theme-factory", - "source": "./skills/theme-factory" - }, - { - "category": "development", - "description": "Common project, dependency, and environment operations using uv.", - "keywords": [ - "uv", - "python", - "dependencies", - "venv" - ], - "name": "uv", - "source": "./skills/uv" - }, - { - "category": "integration", - "description": "Deploy and manage applications on Vercel, including preview deployments and deployment protection.", - "keywords": [ - "vercel", - "deployment", - "preview", - "hosting" - ], - "name": "vercel", - "source": "./skills/vercel" - }, - { - "category": "security", - "description": "Automated security vulnerability scanning and AI-powered remediation. Scans repositories, skips when no issues found, and creates PRs with fixes.", - "keywords": [ - "security", - "vulnerability", - "remediation", - "scanning", - "automation" - ], - "name": "vulnerability-remediation", - "source": "./plugins/vulnerability-remediation" - }, - { - "category": "productivity", - "description": "Iterate on a GitHub pull request — drive it through CI, code review, and QA until merge-ready. Monitors state, fixes failures, addresses review feedback, retries flaky checks, and pushes fixes in one continuous loop.", - "keywords": [ - "github", - "ci", - "review", - "qa", - "pull-request", - "iterate" - ], - "name": "iterate", - "source": "./skills/iterate" - }, - { - "category": "productivity", - "description": "Back factual claims and field values with official, verifiable sources. Use when the user asks to fill fields, answer questions, or make claims that must be supported by an exact quote and an official link.", - "keywords": [ - "evidence", - "citations", - "sources", - "verification", - "documentation", - "official" - ], - "name": "evidence-based-citations", - "source": "./skills/evidence-based-citations" - }, - { - "category": "productivity", - "description": "Create an automation that reviews GitHub pull requests when they are opened or updated. Inspects the diff, changed files, tests, and existing discussion via GitHub MCP, then posts a concise review highlighting risks, security issues, missing tests, and next steps.", - "keywords": [ - "github", - "pull-request", - "review", - "code-review", - "automation", - "integration" - ], - "name": "github-pr-reviewer", - "source": "./skills/github-pr-reviewer" - }, - { - "category": "productivity", - "description": "Create an automation that drafts incident retrospectives by gathering incident-channel messages from Slack, collecting linked tickets from Linear, and publishing a retrospective draft to Notion with timeline, impact summary, root-cause hypotheses, and action items.", - "keywords": [ - "incident", - "retrospective", - "postmortem", - "slack", - "linear", - "notion", - "automation" - ], - "name": "incident-retrospective", - "source": "./skills/incident-retrospective" - }, - { - "category": "productivity", - "description": "Create an automation that triages new Linear issues by inspecting title, description, team, and recent related issues. Suggests labels, priority, likely owner, and potential duplicates, then posts a clarifying comment.", - "keywords": [ - "linear", - "triage", - "issues", - "labels", - "priority", - "automation", - "integration" - ], - "name": "linear-triage", - "source": "./skills/linear-triage" - }, - { - "category": "productivity", - "description": "Create a recurring automation that researches a topic using Tavily web search and publishes a structured brief to Notion with executive summary, key findings, implications, and source citations.", - "keywords": [ - "research", - "brief", - "tavily", - "notion", - "web-search", - "automation" - ], - "name": "research-brief", - "source": "./skills/research-brief" - }, - { - "category": "productivity", - "description": "Create an automation that generates an async standup digest from Slack. Searches selected channels for messages since the previous workday, groups updates by project, highlights blockers and decisions, and posts a summary to a target channel.", - "keywords": [ - "slack", - "standup", - "digest", - "summary", - "daily", - "cron", - "automation" - ], - "name": "slack-standup-digest", - "source": "./skills/slack-standup-digest" - }, - { - "category": "productivity", - "description": "Write and edit clear, accessible prose in a plain English content style: active voice, front-loaded content, sentence case, and accessible formatting.", - "keywords": [ - "plain-english" - ], - "name": "plain-english-content", - "source": "./skills/plain-english-content" - }, - { - "category": "productivity", - "description": "Deploy a cron-based OpenHands automation that watches a Jira Cloud project for issues labeled with a configurable label (default: create-pr) and spawns an agent conversation to create a GitHub pull request for each new issue found. The target GitHub repo is read from the ticket body - no repo parameter required at deploy time.", - "keywords": [ - "jira", - "atlassian" - ], - "name": "jira-issue-to-pr", - "source": "./skills/jira-issue-to-pr" - } - ] -} diff --git a/AGENTS.md b/AGENTS.md index de5e84fd..9c874ce2 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -106,7 +106,7 @@ When editing or adding skills in this repo, follow these rules (and add new skil - The test suite expects **every directory under `skills/`** to be listed in a marketplace. If you add a new skill (or rebase onto a main branch that added skills), update the appropriate marketplace file or CI will fail with `Skills missing from marketplace: [...]`. - `scripts/sync_extensions.py` keeps generated artifacts in sync: Claude Code command files, README catalog section, coverage checks, vendor symlinks, and root marketplace catalog copies. Run `python scripts/sync_extensions.py --check` (or just push — CI runs it) to verify everything is consistent. Run without `--check` to auto-fix. The "Quick Start" section in `README.md` (OpenHands SDK, Claude Code, and Codex setup instructions) is **manually maintained** above the auto-generated catalog markers and is intentionally not generated by the sync script. -- The repository root exposes the canonical marketplace catalog (`marketplaces/openhands-extensions.json`) as real `marketplace.json` copies under `.claude-plugin/`, `.codex-plugin/`, and `.plugin/` — **not symlinks**. `raw.githubusercontent.com` serves git symlinks as their literal target text and does not traverse symlinked directory paths, so symlinks made the catalog unreachable at the standard `.claude-plugin/marketplace.json` path (used by `github://openhands/extensions` consumers). The `root-marketplace` sync task keeps these copies byte-for-byte in sync with the canonical file; never replace them with symlinks. +- The repository root publishes the canonical marketplace catalog (`marketplaces/openhands-extensions.json`) as a single real `marketplace.json` copy at `.plugin/marketplace.json` — **not a symlink**, and **not** mirrored under `.claude-plugin/` or `.codex-plugin/` at the repo root. `raw.githubusercontent.com` serves git symlinks as their literal target text and does not dereference them (file or directory), so symlinks made the catalog unreachable over the raw URL (used by `github://openhands/extensions` consumers). `.plugin/` is this repo's canonical manifest directory, so the catalog lives there; consumers must fetch `.plugin/marketplace.json`. The `root-marketplace` sync task keeps this copy byte-for-byte in sync with the canonical file; never replace it with a symlink. (Note: per-skill/per-plugin `.claude-plugin` and `.codex-plugin` vendor symlinks *within* `skills/` and `plugins/` are unrelated and remain, managed by the `symlinks` task.) - The sync script uses PyYAML to parse SKILL.md frontmatter. If you add a skill with a slash trigger (e.g., `triggers: ["/mycommand"]`), the script auto-generates `commands/mycommand.md`. **Note:** Slash triggers in SKILL.md frontmatter are deprecated — prefer adding a `commands/command-name.md` file to the plugin's `commands/` directory instead. Keyword triggers (non-slash) remain the recommended way to activate skills by topic. ## OpenHands SDK documentation policy diff --git a/scripts/sync_extensions.py b/scripts/sync_extensions.py index b181e936..395af17b 100644 --- a/scripts/sync_extensions.py +++ b/scripts/sync_extensions.py @@ -10,12 +10,12 @@ marketplace, or a marketplace entry points to a missing directory. 4. **symlinks** — enforce ``.plugin/`` as the canonical manifest directory with vendor symlinks (``.claude-plugin``, ``.codex-plugin``). - 5. **root-marketplace** — keep real ``marketplace.json`` copies at the - repository root under ``.claude-plugin/``, ``.codex-plugin/``, and - ``.plugin/`` so consumers that fetch the catalog over the GitHub raw - URL (e.g. ``github://openhands/extensions``) can read it. Git symlinks - are stored as blobs and ``raw.githubusercontent.com`` does not - dereference them through directory paths, so these must be real files. + 5. **root-marketplace** — keep a real ``marketplace.json`` copy at the + repository root under ``.plugin/`` so consumers that fetch the catalog + over the GitHub raw URL (e.g. ``github://openhands/extensions``) can + read it. Git symlinks are stored as blobs and + ``raw.githubusercontent.com`` does not dereference them (it serves the + literal target text), so the root catalog must be a real file. Usage: python scripts/sync_extensions.py # run all, write changes @@ -44,13 +44,17 @@ SKILL_DIRS = [REPO_ROOT / "skills", REPO_ROOT / "plugins"] MARKETPLACES_DIR = REPO_ROOT / "marketplaces" # The canonical marketplace catalog that the registry publishes. The -# repository root exposes copies of this file (not symlinks) under the -# vendor directories below so that consumers fetching the catalog over the +# repository root exposes a real (non-symlink) copy of this file at +# ``.plugin/marketplace.json`` so consumers that fetch the catalog over the # GitHub raw URL (``github://openhands/extensions``) can read it. PRIMARY_MARKETPLACE = MARKETPLACES_DIR / "openhands-extensions.json" # Vendor directories at the repository root that must each contain a real # (non-symlink) ``marketplace.json`` copy of ``PRIMARY_MARKETPLACE``. -ROOT_MARKETPLACE_DIRS = [".claude-plugin", ".codex-plugin", ".plugin"] +# ``.plugin/`` is the canonical manifest directory for this repo, so the root +# catalog lives there. Other vendor aliases (``.claude-plugin/``, +# ``.codex-plugin/``) are intentionally NOT mirrored at the repo root — +# consumers must fetch the catalog from ``.plugin/marketplace.json``. +ROOT_MARKETPLACE_DIRS = [".plugin"] # Max description length in the catalog table. 120 chars fits GitHub's # diff viewer and rendered Markdown tables without horizontal scroll. MAX_DESC_LEN = 120 @@ -456,16 +460,20 @@ def sync_root_marketplace(*, check: bool) -> list[str]: ``marketplaces/openhands-extensions.json``. Historically the root exposed it through a double symlink chain (``.claude-plugin`` -> ``.plugin`` and ``.plugin/marketplace.json`` -> the canonical file). ``raw.githubusercontent.com`` - serves git symlinks as their literal target text and does not traverse - symlinked directory paths, so consumers fetching - ``.claude-plugin/marketplace.json`` over the raw URL (e.g. the - plugin-directory with ``MARKETPLACE_SOURCE=github://openhands/extensions``) - received a 404 (or the literal symlink body) and saw an empty catalog. - - This sync replaces those symlinks with real directory + file copies that - mirror the canonical catalog byte-for-byte, so the catalog is reachable - at every standard ``.claude-plugin/marketplace.json`` path while staying - in sync with the single source of truth. + serves git symlinks as their literal target text and does not dereference + them (file or directory), so consumers fetching the catalog over the raw + URL (e.g. the plugin-directory with + ``MARKETPLACE_SOURCE=github://openhands/extensions``) received a 404 (for + symlinked directory paths) or the literal symlink body (for symlinked + files) and saw an empty catalog. + + This sync keeps a single real ``marketplace.json`` copy at + ``.plugin/marketplace.json`` (this repo's canonical manifest directory) + that mirrors the canonical catalog byte-for-byte. The catalog is reachable + at ``.plugin/marketplace.json`` over the raw URL while staying in sync + with the single source of truth. Other vendor aliases + (``.claude-plugin/``, ``.codex-plugin/``) are not mirrored at the repo + root; consumers must fetch ``.plugin/marketplace.json``. """ if not PRIMARY_MARKETPLACE.is_file(): return [f"canonical marketplace missing: {PRIMARY_MARKETPLACE.relative_to(REPO_ROOT)}"] diff --git a/tests/test_sync_extensions.py b/tests/test_sync_extensions.py index 1cad1090..b41762d7 100644 --- a/tests/test_sync_extensions.py +++ b/tests/test_sync_extensions.py @@ -313,12 +313,15 @@ def test_all_source_paths_exist(self): # ── root marketplace copies ────────────────────────────────────────── class TestRootMarketplace: - """The root vendor marketplace.json files must be real (non-symlink) copies. - - raw.githubusercontent.com does not dereference git symlinks through - directory paths, so consumers using the standard - ``.claude-plugin/marketplace.json`` path (e.g. plugin-directory with - ``MARKETPLACE_SOURCE=github://openhands/extensions``) need real files. + """The root catalog lives at .plugin/marketplace.json as a real (non-symlink) file. + + raw.githubusercontent.com serves git symlinks as their literal target + text and does not dereference them, so consumers fetching the catalog + over the raw URL (e.g. plugin-directory with + ``MARKETPLACE_SOURCE=github://openhands/extensions``) need a real file. + .plugin/ is this repo's canonical manifest directory, so the catalog is + published only there (not mirrored under .claude-plugin/ or .codex-plugin/ + at the repo root). """ def test_vendor_dirs_are_real_directories(self): @@ -360,7 +363,7 @@ def test_marketplace_json_is_valid_catalog(self): assert len(data.get("plugins", [])) == len(canonical.get("plugins", [])) def test_sync_root_marketplace_detects_and_fixes_symlinks(self, tmp_path, monkeypatch): - """sync_root_marketplace replaces symlinked dirs/files with real copies.""" + """sync_root_marketplace replaces a symlinked .plugin/marketplace.json with a real copy.""" import json monkeypatch.setattr("sync_extensions.REPO_ROOT", tmp_path) @@ -373,26 +376,21 @@ def test_sync_root_marketplace_detects_and_fixes_symlinks(self, tmp_path, monkey canonical_bytes = (json.dumps(canonical_data, indent=2, ensure_ascii=False, sort_keys=True) + "\n").encode() (mp_dir / "openhands-extensions.json").write_bytes(canonical_bytes) - # Recreate the broken double-symlink chain from the issue. + # Recreate the broken symlink from the issue (.plugin is a real dir, + # but marketplace.json is a symlink to the canonical file). plugin_dir = tmp_path / ".plugin" plugin_dir.mkdir() (plugin_dir / "marketplace.json").symlink_to("../marketplaces/openhands-extensions.json") - (tmp_path / ".claude-plugin").symlink_to(".plugin") - (tmp_path / ".codex-plugin").symlink_to(".plugin") - # Check mode must report the symlinks as problems. + # Check mode must report the symlink as a problem. problems = sync_root_marketplace(check=True) - assert any("symlinked dir" in p for p in problems) assert any("symlinked file" in p for p in problems) - # Write mode fixes them. + # Write mode fixes it. sync_root_marketplace(check=False) - for vendor in [".claude-plugin", ".codex-plugin", ".plugin"]: - vendor_dir = tmp_path / vendor - target = vendor_dir / "marketplace.json" - assert vendor_dir.is_dir() and not vendor_dir.is_symlink(), f"{vendor} still a symlink dir" - assert target.is_file() and not target.is_symlink(), f"{target} still a symlink file" - assert _normalize_marketplace_bytes(target.read_bytes()) == canonical_bytes + target = tmp_path / ".plugin" / "marketplace.json" + assert target.is_file() and not target.is_symlink(), f"{target} still a symlink file" + assert _normalize_marketplace_bytes(target.read_bytes()) == canonical_bytes # After fixing, check mode is clean. assert sync_root_marketplace(check=True) == [] @@ -411,19 +409,25 @@ def test_sync_root_marketplace_detects_stale_copy(self, tmp_path, monkeypatch): (mp_dir / "openhands-extensions.json").write_bytes(canonical_bytes) stale = {"name": "openhands-extensions", "plugins": []} - for vendor in [".claude-plugin", ".codex-plugin", ".plugin"]: - (tmp_path / vendor).mkdir() - (tmp_path / vendor / "marketplace.json").write_text(json.dumps(stale)) + (tmp_path / ".plugin").mkdir() + (tmp_path / ".plugin" / "marketplace.json").write_text(json.dumps(stale)) problems = sync_root_marketplace(check=True) - assert len(problems) == 3 + assert len(problems) == 1 assert all("out of date" in p for p in problems) sync_root_marketplace(check=False) - for vendor in [".claude-plugin", ".codex-plugin", ".plugin"]: - assert _normalize_marketplace_bytes((tmp_path / vendor / "marketplace.json").read_bytes()) == canonical_bytes + assert _normalize_marketplace_bytes((tmp_path / ".plugin" / "marketplace.json").read_bytes()) == canonical_bytes assert sync_root_marketplace(check=True) == [] + def test_no_root_claude_or_codex_vendor_dirs(self): + """Only .plugin/ exposes the root catalog; .claude-plugin/ and .codex-plugin/ must NOT exist at the repo root.""" + for vendor in [".claude-plugin", ".codex-plugin"]: + assert not (REPO_ROOT / vendor).exists(), ( + f"{vendor}/ exists at the repo root; the catalog is published only via " + ".plugin/marketplace.json to keep a single source of truth" + ) + if __name__ == "__main__": pytest.main([__file__, "-v"]) From d69b75886f4b550230d0fbf6fb2d9c4b5d364d5d Mon Sep 17 00:00:00 2001 From: openhands Date: Wed, 8 Jul 2026 13:43:12 +0000 Subject: [PATCH 3/3] Revert "refactor: publish root catalog only at .plugin/marketplace.json" This reverts commit 640cf14824021e5184f5d979bfee74c4602f3c5b. --- .claude-plugin/marketplace.json | 752 ++++++++++++++++++++++++++++++++ .codex-plugin/marketplace.json | 752 ++++++++++++++++++++++++++++++++ AGENTS.md | 2 +- scripts/sync_extensions.py | 46 +- tests/test_sync_extensions.py | 54 ++- 5 files changed, 1549 insertions(+), 57 deletions(-) create mode 100644 .claude-plugin/marketplace.json create mode 100644 .codex-plugin/marketplace.json diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json new file mode 100644 index 00000000..55dbe082 --- /dev/null +++ b/.claude-plugin/marketplace.json @@ -0,0 +1,752 @@ +{ + "metadata": { + "description": "Official skills and plugins for OpenHands — the open-source AI software engineer.", + "homepage": "https://github.com/OpenHands/extensions", + "maintainer": "OpenHands" + }, + "name": "openhands-extensions", + "owner": { + "email": "contact@all-hands.dev", + "name": "OpenHands" + }, + "plugins": [ + { + "category": "development", + "description": "Create file-based sub-agents as Markdown files — no Python code required. Guides the user through a structured interview and generates a ready-to-deploy .md agent file following the OpenHands SDK specification.", + "keywords": [ + "agent", + "sub-agent", + "file-based", + "markdown", + "no-code", + "create" + ], + "name": "agent-creator", + "source": "./skills/agent-creator" + }, + { + "category": "productivity", + "description": "Add (import) an OpenHands skill from a GitHub repository into the current workspace.", + "keywords": [ + "skill", + "import", + "github", + "sparse-checkout" + ], + "name": "add-skill", + "source": "./skills/add-skill" + }, + { + "category": "productivity", + "description": "Persist and retrieve repository-specific knowledge using AGENTS.md files. Use when you want to save important information about a codebase (build commands, code style, workflows) for future sessions.", + "keywords": [ + "memory", + "knowledge", + "persistence", + "agents" + ], + "name": "agent-memory", + "source": "./skills/agent-memory" + }, + { + "category": "development", + "description": "Guided workflow for building custom AI agents using the OpenHands Software Agent SDK. Use when you want to create a new agent through an interactive interview process that gathers requirements and generates implementation plans.", + "keywords": [ + "agent", + "sdk", + "builder", + "openhands" + ], + "name": "agent-sdk-builder", + "source": "./skills/agent-sdk-builder" + }, + { + "category": "development", + "description": "Simplifies and refines code across three dimensions - code reuse, code quality, and efficiency - while preserving all functionality. Analyzes recently modified code and provides actionable improvement suggestions.", + "keywords": [ + "simplify", + "refine", + "cleanup", + "code-quality", + "reuse", + "efficiency", + "refactor" + ], + "name": "code-simplifier", + "source": "./skills/code-simplifier" + }, + { + "category": "integration", + "description": "Create and manage OpenHands automations - scheduled tasks that run in sandboxes. Use the prompt preset to create automations from natural language, or manage existing automations.", + "keywords": [ + "automation", + "cron", + "scheduled-task", + "sandbox", + "openhands" + ], + "name": "openhands-automation", + "source": "./skills/openhands-automation" + }, + { + "category": "development", + "description": "Work effectively inside a local Agent Canvas environment, including local agent-server auth, safe workspace hygiene, and local conversation delegation.", + "keywords": [ + "agent-canvas", + "openhands", + "local", + "conversation", + "delegation" + ], + "name": "agent-canvas-environment", + "source": "./skills/agent-canvas-environment" + }, + { + "category": "development", + "description": "Reference skill for the OpenHands Software Agent SDK - build AI agents with custom tools, LLM configuration, conversations, sub-agent delegation, MCP integration, security, and persistence.", + "keywords": [ + "sdk", + "agent", + "openhands", + "tools", + "llm", + "conversation" + ], + "name": "openhands-sdk", + "source": "./skills/openhands-sdk" + }, + { + "category": "integration", + "description": "Interact with Azure DevOps repositories, pull requests, and APIs using the AZURE_DEVOPS_TOKEN environment variable. Use when working with code hosted on Azure DevOps or managing Azure DevOps resources.", + "keywords": [ + "azure", + "devops", + "git", + "pull-request" + ], + "name": "azure-devops", + "source": "./skills/azure-devops" + }, + { + "category": "integration", + "description": "Bitbucket integration hub. Detects whether the repository is on Bitbucket Cloud or Bitbucket Data Center and directs you to the matching detailed skill (bitbucket-cloud or bitbucket-data-center). Use for any Bitbucket repository or pull request task.", + "keywords": [ + "bitbucket", + "git", + "pull-request" + ], + "name": "bitbucket", + "source": "./skills/bitbucket" + }, + { + "category": "integration", + "description": "Bitbucket Cloud (bitbucket.org) specifics — authenticate with BITBUCKET_TOKEN, use the REST API v2, workspace/repo_slug repositories, and the create_bitbucket_pr tool. Loaded on demand by the bitbucket skill once a Cloud environment is detected.", + "keywords": [ + "bitbucket", + "bitbucket-cloud", + "git", + "pull-request" + ], + "name": "bitbucket-cloud", + "source": "./skills/bitbucket-cloud" + }, + { + "category": "integration", + "description": "Bitbucket Data Center (self-hosted Bitbucket Server) specifics — authenticate with BITBUCKET_DATA_CENTER_TOKEN, use the REST API 1.0, PROJECT/repo_slug repositories, scm/ git remotes, and the create_bitbucket_data_center_pr tool. Loaded on demand by the bitbucket skill once a Data Center environment is detected.", + "keywords": [ + "bitbucket", + "bitbucket-data-center", + "bitbucket-server", + "git", + "pull-request" + ], + "name": "bitbucket-data-center", + "source": "./skills/bitbucket-data-center" + }, + { + "category": "utilities", + "description": "Get current weather, time, and precipitation forecast for any city using the free Open-Meteo API. Provides slash command /city-weather:now .", + "keywords": [ + "weather", + "time", + "forecast", + "temperature", + "precipitation", + "sample" + ], + "name": "city-weather", + "source": "./plugins/city-weather" + }, + { + "category": "code-quality", + "description": "Rigorous code review focusing on data structures, simplicity, security, pragmatism, and risk/safety evaluation. Provides brutally honest, actionable feedback on pull requests or merge requests, including a risk assessment for every review. Use when reviewing code changes.", + "keywords": [ + "code-review", + "quality", + "security", + "style", + "risk" + ], + "name": "code-review", + "source": "./skills/code-review" + }, + { + "category": "monitoring", + "description": "Query and analyze Datadog logs, metrics, APM traces, and monitors using the Datadog API. Use when debugging production issues, monitoring application performance, or investigating alerts.", + "keywords": [ + "datadog", + "monitoring", + "logs", + "metrics", + "apm" + ], + "name": "datadog", + "source": "./skills/datadog" + }, + { + "category": "development", + "description": "Common project operations using Deno (tasks, run/test/lint/fmt, and dependency management).", + "keywords": [ + "deno", + "typescript", + "javascript", + "runtime" + ], + "name": "deno", + "source": "./skills/deno" + }, + { + "category": "integration", + "description": "Build and automate Discord integrations (bots, webhooks, slash commands, and REST API workflows). Use when the user mentions Discord, a Discord server/guild, channels, webhooks, bot tokens, slash commands/application commands, discord.js, or discord.py.", + "keywords": [ + "discord", + "bot", + "webhook", + "automation" + ], + "name": "discord", + "source": "./skills/discord" + }, + { + "category": "infrastructure", + "description": "Run Docker commands within a container environment, including starting the Docker daemon and managing containers. Use when building, running, or managing Docker containers and images.", + "keywords": [ + "docker", + "container", + "images" + ], + "name": "docker", + "source": "./skills/docker" + }, + { + "category": "testing", + "description": "A test skill that responds to the magic word 'flarglebargle' with a compliment. Use for testing skill activation and trigger functionality.", + "keywords": [ + "test", + "demo" + ], + "name": "flarglebargle", + "source": "./skills/flarglebargle" + }, + { + "category": "design", + "description": "Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts, posters, or applications. Generates creative, polished code and UI design that avoids generic AI aesthetics.", + "keywords": [ + "frontend", + "design", + "ui", + "web", + "react", + "html", + "css" + ], + "name": "frontend-design", + "source": "./skills/frontend-design" + }, + { + "category": "integration", + "description": "Interact with GitHub repositories, pull requests, issues, and workflows using the GITHUB_TOKEN environment variable and GitHub CLI. Use when working with code hosted on GitHub or managing GitHub resources.", + "keywords": [ + "github", + "git", + "pull-request", + "issues", + "workflows" + ], + "name": "github", + "source": "./skills/github" + }, + { + "category": "integration", + "description": "Create, debug, and test GitHub Actions workflows and custom actions. Use when building CI/CD pipelines, automating workflows, or troubleshooting GitHub Actions.", + "keywords": [ + "github-actions", + "workflows", + "ci-cd", + "automation", + "actions" + ], + "name": "github-actions", + "source": "./skills/github-actions" + }, + { + "category": "code-quality", + "description": "Post structured PR reviews to GitHub with inline comments/suggestions in a single API call.", + "keywords": [ + "github", + "pull-request", + "review", + "code-review" + ], + "name": "github-pr-review", + "source": "./skills/github-pr-review" + }, + { + "category": "productivity", + "description": "Create a cron automation that polls a GitHub repository for issue and PR comments containing a configurable trigger phrase (@OpenHands by default). Starts an OpenHands conversation with full issue/PR context, posts acknowledgement comments with a conversation link, and summarises results back to the issue/PR when the agent finishes.", + "keywords": [ + "github", + "monitor", + "issues", + "pull-requests", + "trigger", + "cron", + "automation", + "integration" + ], + "name": "github-repo-monitor", + "source": "./skills/github-repo-monitor" + }, + { + "category": "integration", + "description": "Interact with GitLab repositories, merge requests, and APIs using the GITLAB_TOKEN environment variable. Use when working with code hosted on GitLab or managing GitLab resources.", + "keywords": [ + "gitlab", + "git", + "merge-request" + ], + "name": "gitlab", + "source": "./skills/gitlab" + }, + { + "category": "data-science", + "description": "Read, modify, execute, and convert Jupyter notebooks programmatically. Use when working with .ipynb files for data science workflows, including editing cells, clearing outputs, or converting to other formats.", + "keywords": [ + "jupyter", + "notebook", + "ipynb", + "data-science" + ], + "name": "jupyter", + "source": "./skills/jupyter" + }, + { + "category": "infrastructure", + "description": "Set up and manage local Kubernetes clusters using KIND (Kubernetes IN Docker). Use when testing Kubernetes applications locally or developing cloud-native workloads.", + "keywords": [ + "kubernetes", + "k8s", + "kind", + "cloud-native" + ], + "name": "kubernetes", + "source": "./skills/kubernetes" + }, + { + "category": "code-quality", + "description": "Distill code review feedback from GitHub PRs into reusable skills and guidelines. Use when users ask to learn from code reviews, extract review patterns, or generate coding standards from historical PR feedback.", + "keywords": [ + "code-review", + "learning", + "skills", + "guidelines", + "pr-feedback" + ], + "name": "learn-from-code-review", + "source": "./skills/learn-from-code-review" + }, + { + "category": "integration", + "description": "Interact with Linear project management - query issues, update status, create tickets using the Linear GraphQL API.", + "keywords": [ + "linear", + "ticket", + "issue", + "project-management", + "graphql" + ], + "name": "linear", + "source": "./skills/linear" + }, + { + "category": "testing", + "description": "A simple test plugin for verifying plugin loading. Triggers on magic words (alakazam, abracadabra) and returns a specific phrase to confirm plugins are working.", + "keywords": [ + "test", + "magic", + "plugin", + "verification", + "sample" + ], + "name": "magic-test", + "source": "./plugins/magic-test" + }, + { + "category": "productivity", + "description": "Create, search, and update Notion pages/databases using the Notion API. Use for documenting work, generating runbooks, and automating knowledge base updates.", + "keywords": [ + "notion", + "documentation", + "knowledge-base" + ], + "name": "notion", + "source": "./skills/notion" + }, + { + "category": "development", + "description": "Handle npm package installation in non-interactive environments by piping confirmations. Use when installing Node.js packages that require user confirmation prompts.", + "keywords": [ + "npm", + "nodejs", + "packages" + ], + "name": "npm", + "source": "./skills/npm" + }, + { + "category": "productivity", + "description": "Assess repository agent-readiness across five pillars, propose high-impact fixes, and generate repo-specific AGENTS.md files.", + "keywords": [ + "onboarding", + "readiness", + "agents-md", + "agent-readiness", + "assessment" + ], + "name": "onboarding", + "source": "./plugins/onboarding" + }, + { + "category": "openhands", + "description": "Unified OpenHands plugin — bundles Cloud CLI, REST API (openhands-api), and Automations (openhands-automation) into a single plugin.", + "keywords": [ + "openhands", + "cloud", + "api", + "automation", + "cli" + ], + "name": "openhands", + "source": "./plugins/openhands" + }, + { + "category": "development", + "description": "Use the OpenHands Cloud REST API (V1) and agent-server APIs to create and manage Cloud or local backend conversations, including multi-conversation delegation workflows. Includes minimal Python and TypeScript clients under scripts/.", + "keywords": [ + "openhands", + "api", + "cloud", + "automation", + "delegation", + "agent-server", + "sandbox", + "conversations" + ], + "name": "openhands-api", + "source": "./skills/openhands-api" + }, + { + "category": "documentation", + "description": "Install and use pdflatex to compile LaTeX documents into PDFs on Linux. Use when generating academic papers, research publications, or any documents written in LaTeX.", + "keywords": [ + "latex", + "pdf", + "academic", + "documents" + ], + "name": "pdflatex", + "source": "./skills/pdflatex" + }, + { + "category": "code-quality", + "description": "Automated PR code review — analyzes diffs and posts inline review comments via the GitHub API.", + "keywords": [ + "pr-review", + "code-review", + "github", + "automation" + ], + "name": "pr-review", + "source": "./plugins/pr-review" + }, + { + "category": "quality-assurance", + "description": "Validate pull request changes by actually running the code — setting up the environment, exercising changed behavior, and posting a structured QA report.", + "keywords": [ + "qa", + "testing", + "pull-request", + "validation", + "automation" + ], + "name": "qa-changes", + "source": "./plugins/qa-changes" + }, + { + "category": "productivity", + "description": "Generate a Product Requirements Document (PRD) for a new feature through an interactive clarifying-question workflow. Use when planning a feature, starting a new project, or when asked to create a PRD.", + "keywords": [ + "prd", + "requirements", + "planning", + "product", + "specification" + ], + "name": "prd", + "source": "./skills/prd" + }, + { + "category": "productivity", + "description": "Generate consistent, well-structured release notes from git history. Produces categorized changelog with breaking changes, features, fixes, and contributor attribution.", + "keywords": [ + "release-notes", + "changelog", + "git", + "semver" + ], + "name": "release-notes", + "source": "./plugins/release-notes" + }, + { + "category": "security", + "description": "Security best practices for secure coding, authentication, authorization, and data protection. Use when developing features that handle sensitive data, user authentication, or require security review.", + "keywords": [ + "security", + "authentication", + "authorization", + "encryption" + ], + "name": "security", + "source": "./skills/security" + }, + { + "category": "development", + "description": "Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Claude's capabilities with specialized knowledge, workflows, or tool integrations.", + "keywords": [ + "skill", + "plugin", + "create" + ], + "name": "skill-creator", + "source": "./skills/skill-creator" + }, + { + "category": "productivity", + "description": "Create a cron automation that polls up to 10 Slack channels every minute and starts an OpenHands conversation when a configurable trigger phrase is detected. Forwards thread replies to running conversations and posts summaries back to Slack when the agent finishes.", + "keywords": [ + "slack", + "monitor", + "channel", + "trigger", + "cron", + "automation", + "integration" + ], + "name": "slack-channel-monitor", + "source": "./skills/slack-channel-monitor" + }, + { + "category": "infrastructure", + "description": "Establish and manage SSH connections to remote machines, including key generation, configuration, and file transfers. Use when connecting to remote servers, executing remote commands, or transferring files via SCP.", + "keywords": [ + "ssh", + "remote", + "scp", + "server" + ], + "name": "ssh", + "source": "./skills/ssh" + }, + { + "category": "development", + "description": "Install and configure Swift programming language on Debian Linux for server-side development. Use when building Swift applications on Linux or setting up a Swift development environment.", + "keywords": [ + "swift", + "linux", + "server-side" + ], + "name": "swift-linux", + "source": "./skills/swift-linux" + }, + { + "category": "design", + "description": "Toolkit for styling artifacts with a theme. These artifacts can be slides, docs, reportings, HTML landing pages, etc. There are 10 pre-set themes with colors/fonts that you can apply to any artifact that has been creating, or can generate a new theme on-the-fly.", + "keywords": [ + "theme", + "styling", + "design", + "slides", + "documents" + ], + "name": "theme-factory", + "source": "./skills/theme-factory" + }, + { + "category": "development", + "description": "Common project, dependency, and environment operations using uv.", + "keywords": [ + "uv", + "python", + "dependencies", + "venv" + ], + "name": "uv", + "source": "./skills/uv" + }, + { + "category": "integration", + "description": "Deploy and manage applications on Vercel, including preview deployments and deployment protection.", + "keywords": [ + "vercel", + "deployment", + "preview", + "hosting" + ], + "name": "vercel", + "source": "./skills/vercel" + }, + { + "category": "security", + "description": "Automated security vulnerability scanning and AI-powered remediation. Scans repositories, skips when no issues found, and creates PRs with fixes.", + "keywords": [ + "security", + "vulnerability", + "remediation", + "scanning", + "automation" + ], + "name": "vulnerability-remediation", + "source": "./plugins/vulnerability-remediation" + }, + { + "category": "productivity", + "description": "Iterate on a GitHub pull request — drive it through CI, code review, and QA until merge-ready. Monitors state, fixes failures, addresses review feedback, retries flaky checks, and pushes fixes in one continuous loop.", + "keywords": [ + "github", + "ci", + "review", + "qa", + "pull-request", + "iterate" + ], + "name": "iterate", + "source": "./skills/iterate" + }, + { + "category": "productivity", + "description": "Back factual claims and field values with official, verifiable sources. Use when the user asks to fill fields, answer questions, or make claims that must be supported by an exact quote and an official link.", + "keywords": [ + "evidence", + "citations", + "sources", + "verification", + "documentation", + "official" + ], + "name": "evidence-based-citations", + "source": "./skills/evidence-based-citations" + }, + { + "category": "productivity", + "description": "Create an automation that reviews GitHub pull requests when they are opened or updated. Inspects the diff, changed files, tests, and existing discussion via GitHub MCP, then posts a concise review highlighting risks, security issues, missing tests, and next steps.", + "keywords": [ + "github", + "pull-request", + "review", + "code-review", + "automation", + "integration" + ], + "name": "github-pr-reviewer", + "source": "./skills/github-pr-reviewer" + }, + { + "category": "productivity", + "description": "Create an automation that drafts incident retrospectives by gathering incident-channel messages from Slack, collecting linked tickets from Linear, and publishing a retrospective draft to Notion with timeline, impact summary, root-cause hypotheses, and action items.", + "keywords": [ + "incident", + "retrospective", + "postmortem", + "slack", + "linear", + "notion", + "automation" + ], + "name": "incident-retrospective", + "source": "./skills/incident-retrospective" + }, + { + "category": "productivity", + "description": "Create an automation that triages new Linear issues by inspecting title, description, team, and recent related issues. Suggests labels, priority, likely owner, and potential duplicates, then posts a clarifying comment.", + "keywords": [ + "linear", + "triage", + "issues", + "labels", + "priority", + "automation", + "integration" + ], + "name": "linear-triage", + "source": "./skills/linear-triage" + }, + { + "category": "productivity", + "description": "Create a recurring automation that researches a topic using Tavily web search and publishes a structured brief to Notion with executive summary, key findings, implications, and source citations.", + "keywords": [ + "research", + "brief", + "tavily", + "notion", + "web-search", + "automation" + ], + "name": "research-brief", + "source": "./skills/research-brief" + }, + { + "category": "productivity", + "description": "Create an automation that generates an async standup digest from Slack. Searches selected channels for messages since the previous workday, groups updates by project, highlights blockers and decisions, and posts a summary to a target channel.", + "keywords": [ + "slack", + "standup", + "digest", + "summary", + "daily", + "cron", + "automation" + ], + "name": "slack-standup-digest", + "source": "./skills/slack-standup-digest" + }, + { + "category": "productivity", + "description": "Write and edit clear, accessible prose in a plain English content style: active voice, front-loaded content, sentence case, and accessible formatting.", + "keywords": [ + "plain-english" + ], + "name": "plain-english-content", + "source": "./skills/plain-english-content" + }, + { + "category": "productivity", + "description": "Deploy a cron-based OpenHands automation that watches a Jira Cloud project for issues labeled with a configurable label (default: create-pr) and spawns an agent conversation to create a GitHub pull request for each new issue found. The target GitHub repo is read from the ticket body - no repo parameter required at deploy time.", + "keywords": [ + "jira", + "atlassian" + ], + "name": "jira-issue-to-pr", + "source": "./skills/jira-issue-to-pr" + } + ] +} diff --git a/.codex-plugin/marketplace.json b/.codex-plugin/marketplace.json new file mode 100644 index 00000000..55dbe082 --- /dev/null +++ b/.codex-plugin/marketplace.json @@ -0,0 +1,752 @@ +{ + "metadata": { + "description": "Official skills and plugins for OpenHands — the open-source AI software engineer.", + "homepage": "https://github.com/OpenHands/extensions", + "maintainer": "OpenHands" + }, + "name": "openhands-extensions", + "owner": { + "email": "contact@all-hands.dev", + "name": "OpenHands" + }, + "plugins": [ + { + "category": "development", + "description": "Create file-based sub-agents as Markdown files — no Python code required. Guides the user through a structured interview and generates a ready-to-deploy .md agent file following the OpenHands SDK specification.", + "keywords": [ + "agent", + "sub-agent", + "file-based", + "markdown", + "no-code", + "create" + ], + "name": "agent-creator", + "source": "./skills/agent-creator" + }, + { + "category": "productivity", + "description": "Add (import) an OpenHands skill from a GitHub repository into the current workspace.", + "keywords": [ + "skill", + "import", + "github", + "sparse-checkout" + ], + "name": "add-skill", + "source": "./skills/add-skill" + }, + { + "category": "productivity", + "description": "Persist and retrieve repository-specific knowledge using AGENTS.md files. Use when you want to save important information about a codebase (build commands, code style, workflows) for future sessions.", + "keywords": [ + "memory", + "knowledge", + "persistence", + "agents" + ], + "name": "agent-memory", + "source": "./skills/agent-memory" + }, + { + "category": "development", + "description": "Guided workflow for building custom AI agents using the OpenHands Software Agent SDK. Use when you want to create a new agent through an interactive interview process that gathers requirements and generates implementation plans.", + "keywords": [ + "agent", + "sdk", + "builder", + "openhands" + ], + "name": "agent-sdk-builder", + "source": "./skills/agent-sdk-builder" + }, + { + "category": "development", + "description": "Simplifies and refines code across three dimensions - code reuse, code quality, and efficiency - while preserving all functionality. Analyzes recently modified code and provides actionable improvement suggestions.", + "keywords": [ + "simplify", + "refine", + "cleanup", + "code-quality", + "reuse", + "efficiency", + "refactor" + ], + "name": "code-simplifier", + "source": "./skills/code-simplifier" + }, + { + "category": "integration", + "description": "Create and manage OpenHands automations - scheduled tasks that run in sandboxes. Use the prompt preset to create automations from natural language, or manage existing automations.", + "keywords": [ + "automation", + "cron", + "scheduled-task", + "sandbox", + "openhands" + ], + "name": "openhands-automation", + "source": "./skills/openhands-automation" + }, + { + "category": "development", + "description": "Work effectively inside a local Agent Canvas environment, including local agent-server auth, safe workspace hygiene, and local conversation delegation.", + "keywords": [ + "agent-canvas", + "openhands", + "local", + "conversation", + "delegation" + ], + "name": "agent-canvas-environment", + "source": "./skills/agent-canvas-environment" + }, + { + "category": "development", + "description": "Reference skill for the OpenHands Software Agent SDK - build AI agents with custom tools, LLM configuration, conversations, sub-agent delegation, MCP integration, security, and persistence.", + "keywords": [ + "sdk", + "agent", + "openhands", + "tools", + "llm", + "conversation" + ], + "name": "openhands-sdk", + "source": "./skills/openhands-sdk" + }, + { + "category": "integration", + "description": "Interact with Azure DevOps repositories, pull requests, and APIs using the AZURE_DEVOPS_TOKEN environment variable. Use when working with code hosted on Azure DevOps or managing Azure DevOps resources.", + "keywords": [ + "azure", + "devops", + "git", + "pull-request" + ], + "name": "azure-devops", + "source": "./skills/azure-devops" + }, + { + "category": "integration", + "description": "Bitbucket integration hub. Detects whether the repository is on Bitbucket Cloud or Bitbucket Data Center and directs you to the matching detailed skill (bitbucket-cloud or bitbucket-data-center). Use for any Bitbucket repository or pull request task.", + "keywords": [ + "bitbucket", + "git", + "pull-request" + ], + "name": "bitbucket", + "source": "./skills/bitbucket" + }, + { + "category": "integration", + "description": "Bitbucket Cloud (bitbucket.org) specifics — authenticate with BITBUCKET_TOKEN, use the REST API v2, workspace/repo_slug repositories, and the create_bitbucket_pr tool. Loaded on demand by the bitbucket skill once a Cloud environment is detected.", + "keywords": [ + "bitbucket", + "bitbucket-cloud", + "git", + "pull-request" + ], + "name": "bitbucket-cloud", + "source": "./skills/bitbucket-cloud" + }, + { + "category": "integration", + "description": "Bitbucket Data Center (self-hosted Bitbucket Server) specifics — authenticate with BITBUCKET_DATA_CENTER_TOKEN, use the REST API 1.0, PROJECT/repo_slug repositories, scm/ git remotes, and the create_bitbucket_data_center_pr tool. Loaded on demand by the bitbucket skill once a Data Center environment is detected.", + "keywords": [ + "bitbucket", + "bitbucket-data-center", + "bitbucket-server", + "git", + "pull-request" + ], + "name": "bitbucket-data-center", + "source": "./skills/bitbucket-data-center" + }, + { + "category": "utilities", + "description": "Get current weather, time, and precipitation forecast for any city using the free Open-Meteo API. Provides slash command /city-weather:now .", + "keywords": [ + "weather", + "time", + "forecast", + "temperature", + "precipitation", + "sample" + ], + "name": "city-weather", + "source": "./plugins/city-weather" + }, + { + "category": "code-quality", + "description": "Rigorous code review focusing on data structures, simplicity, security, pragmatism, and risk/safety evaluation. Provides brutally honest, actionable feedback on pull requests or merge requests, including a risk assessment for every review. Use when reviewing code changes.", + "keywords": [ + "code-review", + "quality", + "security", + "style", + "risk" + ], + "name": "code-review", + "source": "./skills/code-review" + }, + { + "category": "monitoring", + "description": "Query and analyze Datadog logs, metrics, APM traces, and monitors using the Datadog API. Use when debugging production issues, monitoring application performance, or investigating alerts.", + "keywords": [ + "datadog", + "monitoring", + "logs", + "metrics", + "apm" + ], + "name": "datadog", + "source": "./skills/datadog" + }, + { + "category": "development", + "description": "Common project operations using Deno (tasks, run/test/lint/fmt, and dependency management).", + "keywords": [ + "deno", + "typescript", + "javascript", + "runtime" + ], + "name": "deno", + "source": "./skills/deno" + }, + { + "category": "integration", + "description": "Build and automate Discord integrations (bots, webhooks, slash commands, and REST API workflows). Use when the user mentions Discord, a Discord server/guild, channels, webhooks, bot tokens, slash commands/application commands, discord.js, or discord.py.", + "keywords": [ + "discord", + "bot", + "webhook", + "automation" + ], + "name": "discord", + "source": "./skills/discord" + }, + { + "category": "infrastructure", + "description": "Run Docker commands within a container environment, including starting the Docker daemon and managing containers. Use when building, running, or managing Docker containers and images.", + "keywords": [ + "docker", + "container", + "images" + ], + "name": "docker", + "source": "./skills/docker" + }, + { + "category": "testing", + "description": "A test skill that responds to the magic word 'flarglebargle' with a compliment. Use for testing skill activation and trigger functionality.", + "keywords": [ + "test", + "demo" + ], + "name": "flarglebargle", + "source": "./skills/flarglebargle" + }, + { + "category": "design", + "description": "Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts, posters, or applications. Generates creative, polished code and UI design that avoids generic AI aesthetics.", + "keywords": [ + "frontend", + "design", + "ui", + "web", + "react", + "html", + "css" + ], + "name": "frontend-design", + "source": "./skills/frontend-design" + }, + { + "category": "integration", + "description": "Interact with GitHub repositories, pull requests, issues, and workflows using the GITHUB_TOKEN environment variable and GitHub CLI. Use when working with code hosted on GitHub or managing GitHub resources.", + "keywords": [ + "github", + "git", + "pull-request", + "issues", + "workflows" + ], + "name": "github", + "source": "./skills/github" + }, + { + "category": "integration", + "description": "Create, debug, and test GitHub Actions workflows and custom actions. Use when building CI/CD pipelines, automating workflows, or troubleshooting GitHub Actions.", + "keywords": [ + "github-actions", + "workflows", + "ci-cd", + "automation", + "actions" + ], + "name": "github-actions", + "source": "./skills/github-actions" + }, + { + "category": "code-quality", + "description": "Post structured PR reviews to GitHub with inline comments/suggestions in a single API call.", + "keywords": [ + "github", + "pull-request", + "review", + "code-review" + ], + "name": "github-pr-review", + "source": "./skills/github-pr-review" + }, + { + "category": "productivity", + "description": "Create a cron automation that polls a GitHub repository for issue and PR comments containing a configurable trigger phrase (@OpenHands by default). Starts an OpenHands conversation with full issue/PR context, posts acknowledgement comments with a conversation link, and summarises results back to the issue/PR when the agent finishes.", + "keywords": [ + "github", + "monitor", + "issues", + "pull-requests", + "trigger", + "cron", + "automation", + "integration" + ], + "name": "github-repo-monitor", + "source": "./skills/github-repo-monitor" + }, + { + "category": "integration", + "description": "Interact with GitLab repositories, merge requests, and APIs using the GITLAB_TOKEN environment variable. Use when working with code hosted on GitLab or managing GitLab resources.", + "keywords": [ + "gitlab", + "git", + "merge-request" + ], + "name": "gitlab", + "source": "./skills/gitlab" + }, + { + "category": "data-science", + "description": "Read, modify, execute, and convert Jupyter notebooks programmatically. Use when working with .ipynb files for data science workflows, including editing cells, clearing outputs, or converting to other formats.", + "keywords": [ + "jupyter", + "notebook", + "ipynb", + "data-science" + ], + "name": "jupyter", + "source": "./skills/jupyter" + }, + { + "category": "infrastructure", + "description": "Set up and manage local Kubernetes clusters using KIND (Kubernetes IN Docker). Use when testing Kubernetes applications locally or developing cloud-native workloads.", + "keywords": [ + "kubernetes", + "k8s", + "kind", + "cloud-native" + ], + "name": "kubernetes", + "source": "./skills/kubernetes" + }, + { + "category": "code-quality", + "description": "Distill code review feedback from GitHub PRs into reusable skills and guidelines. Use when users ask to learn from code reviews, extract review patterns, or generate coding standards from historical PR feedback.", + "keywords": [ + "code-review", + "learning", + "skills", + "guidelines", + "pr-feedback" + ], + "name": "learn-from-code-review", + "source": "./skills/learn-from-code-review" + }, + { + "category": "integration", + "description": "Interact with Linear project management - query issues, update status, create tickets using the Linear GraphQL API.", + "keywords": [ + "linear", + "ticket", + "issue", + "project-management", + "graphql" + ], + "name": "linear", + "source": "./skills/linear" + }, + { + "category": "testing", + "description": "A simple test plugin for verifying plugin loading. Triggers on magic words (alakazam, abracadabra) and returns a specific phrase to confirm plugins are working.", + "keywords": [ + "test", + "magic", + "plugin", + "verification", + "sample" + ], + "name": "magic-test", + "source": "./plugins/magic-test" + }, + { + "category": "productivity", + "description": "Create, search, and update Notion pages/databases using the Notion API. Use for documenting work, generating runbooks, and automating knowledge base updates.", + "keywords": [ + "notion", + "documentation", + "knowledge-base" + ], + "name": "notion", + "source": "./skills/notion" + }, + { + "category": "development", + "description": "Handle npm package installation in non-interactive environments by piping confirmations. Use when installing Node.js packages that require user confirmation prompts.", + "keywords": [ + "npm", + "nodejs", + "packages" + ], + "name": "npm", + "source": "./skills/npm" + }, + { + "category": "productivity", + "description": "Assess repository agent-readiness across five pillars, propose high-impact fixes, and generate repo-specific AGENTS.md files.", + "keywords": [ + "onboarding", + "readiness", + "agents-md", + "agent-readiness", + "assessment" + ], + "name": "onboarding", + "source": "./plugins/onboarding" + }, + { + "category": "openhands", + "description": "Unified OpenHands plugin — bundles Cloud CLI, REST API (openhands-api), and Automations (openhands-automation) into a single plugin.", + "keywords": [ + "openhands", + "cloud", + "api", + "automation", + "cli" + ], + "name": "openhands", + "source": "./plugins/openhands" + }, + { + "category": "development", + "description": "Use the OpenHands Cloud REST API (V1) and agent-server APIs to create and manage Cloud or local backend conversations, including multi-conversation delegation workflows. Includes minimal Python and TypeScript clients under scripts/.", + "keywords": [ + "openhands", + "api", + "cloud", + "automation", + "delegation", + "agent-server", + "sandbox", + "conversations" + ], + "name": "openhands-api", + "source": "./skills/openhands-api" + }, + { + "category": "documentation", + "description": "Install and use pdflatex to compile LaTeX documents into PDFs on Linux. Use when generating academic papers, research publications, or any documents written in LaTeX.", + "keywords": [ + "latex", + "pdf", + "academic", + "documents" + ], + "name": "pdflatex", + "source": "./skills/pdflatex" + }, + { + "category": "code-quality", + "description": "Automated PR code review — analyzes diffs and posts inline review comments via the GitHub API.", + "keywords": [ + "pr-review", + "code-review", + "github", + "automation" + ], + "name": "pr-review", + "source": "./plugins/pr-review" + }, + { + "category": "quality-assurance", + "description": "Validate pull request changes by actually running the code — setting up the environment, exercising changed behavior, and posting a structured QA report.", + "keywords": [ + "qa", + "testing", + "pull-request", + "validation", + "automation" + ], + "name": "qa-changes", + "source": "./plugins/qa-changes" + }, + { + "category": "productivity", + "description": "Generate a Product Requirements Document (PRD) for a new feature through an interactive clarifying-question workflow. Use when planning a feature, starting a new project, or when asked to create a PRD.", + "keywords": [ + "prd", + "requirements", + "planning", + "product", + "specification" + ], + "name": "prd", + "source": "./skills/prd" + }, + { + "category": "productivity", + "description": "Generate consistent, well-structured release notes from git history. Produces categorized changelog with breaking changes, features, fixes, and contributor attribution.", + "keywords": [ + "release-notes", + "changelog", + "git", + "semver" + ], + "name": "release-notes", + "source": "./plugins/release-notes" + }, + { + "category": "security", + "description": "Security best practices for secure coding, authentication, authorization, and data protection. Use when developing features that handle sensitive data, user authentication, or require security review.", + "keywords": [ + "security", + "authentication", + "authorization", + "encryption" + ], + "name": "security", + "source": "./skills/security" + }, + { + "category": "development", + "description": "Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Claude's capabilities with specialized knowledge, workflows, or tool integrations.", + "keywords": [ + "skill", + "plugin", + "create" + ], + "name": "skill-creator", + "source": "./skills/skill-creator" + }, + { + "category": "productivity", + "description": "Create a cron automation that polls up to 10 Slack channels every minute and starts an OpenHands conversation when a configurable trigger phrase is detected. Forwards thread replies to running conversations and posts summaries back to Slack when the agent finishes.", + "keywords": [ + "slack", + "monitor", + "channel", + "trigger", + "cron", + "automation", + "integration" + ], + "name": "slack-channel-monitor", + "source": "./skills/slack-channel-monitor" + }, + { + "category": "infrastructure", + "description": "Establish and manage SSH connections to remote machines, including key generation, configuration, and file transfers. Use when connecting to remote servers, executing remote commands, or transferring files via SCP.", + "keywords": [ + "ssh", + "remote", + "scp", + "server" + ], + "name": "ssh", + "source": "./skills/ssh" + }, + { + "category": "development", + "description": "Install and configure Swift programming language on Debian Linux for server-side development. Use when building Swift applications on Linux or setting up a Swift development environment.", + "keywords": [ + "swift", + "linux", + "server-side" + ], + "name": "swift-linux", + "source": "./skills/swift-linux" + }, + { + "category": "design", + "description": "Toolkit for styling artifacts with a theme. These artifacts can be slides, docs, reportings, HTML landing pages, etc. There are 10 pre-set themes with colors/fonts that you can apply to any artifact that has been creating, or can generate a new theme on-the-fly.", + "keywords": [ + "theme", + "styling", + "design", + "slides", + "documents" + ], + "name": "theme-factory", + "source": "./skills/theme-factory" + }, + { + "category": "development", + "description": "Common project, dependency, and environment operations using uv.", + "keywords": [ + "uv", + "python", + "dependencies", + "venv" + ], + "name": "uv", + "source": "./skills/uv" + }, + { + "category": "integration", + "description": "Deploy and manage applications on Vercel, including preview deployments and deployment protection.", + "keywords": [ + "vercel", + "deployment", + "preview", + "hosting" + ], + "name": "vercel", + "source": "./skills/vercel" + }, + { + "category": "security", + "description": "Automated security vulnerability scanning and AI-powered remediation. Scans repositories, skips when no issues found, and creates PRs with fixes.", + "keywords": [ + "security", + "vulnerability", + "remediation", + "scanning", + "automation" + ], + "name": "vulnerability-remediation", + "source": "./plugins/vulnerability-remediation" + }, + { + "category": "productivity", + "description": "Iterate on a GitHub pull request — drive it through CI, code review, and QA until merge-ready. Monitors state, fixes failures, addresses review feedback, retries flaky checks, and pushes fixes in one continuous loop.", + "keywords": [ + "github", + "ci", + "review", + "qa", + "pull-request", + "iterate" + ], + "name": "iterate", + "source": "./skills/iterate" + }, + { + "category": "productivity", + "description": "Back factual claims and field values with official, verifiable sources. Use when the user asks to fill fields, answer questions, or make claims that must be supported by an exact quote and an official link.", + "keywords": [ + "evidence", + "citations", + "sources", + "verification", + "documentation", + "official" + ], + "name": "evidence-based-citations", + "source": "./skills/evidence-based-citations" + }, + { + "category": "productivity", + "description": "Create an automation that reviews GitHub pull requests when they are opened or updated. Inspects the diff, changed files, tests, and existing discussion via GitHub MCP, then posts a concise review highlighting risks, security issues, missing tests, and next steps.", + "keywords": [ + "github", + "pull-request", + "review", + "code-review", + "automation", + "integration" + ], + "name": "github-pr-reviewer", + "source": "./skills/github-pr-reviewer" + }, + { + "category": "productivity", + "description": "Create an automation that drafts incident retrospectives by gathering incident-channel messages from Slack, collecting linked tickets from Linear, and publishing a retrospective draft to Notion with timeline, impact summary, root-cause hypotheses, and action items.", + "keywords": [ + "incident", + "retrospective", + "postmortem", + "slack", + "linear", + "notion", + "automation" + ], + "name": "incident-retrospective", + "source": "./skills/incident-retrospective" + }, + { + "category": "productivity", + "description": "Create an automation that triages new Linear issues by inspecting title, description, team, and recent related issues. Suggests labels, priority, likely owner, and potential duplicates, then posts a clarifying comment.", + "keywords": [ + "linear", + "triage", + "issues", + "labels", + "priority", + "automation", + "integration" + ], + "name": "linear-triage", + "source": "./skills/linear-triage" + }, + { + "category": "productivity", + "description": "Create a recurring automation that researches a topic using Tavily web search and publishes a structured brief to Notion with executive summary, key findings, implications, and source citations.", + "keywords": [ + "research", + "brief", + "tavily", + "notion", + "web-search", + "automation" + ], + "name": "research-brief", + "source": "./skills/research-brief" + }, + { + "category": "productivity", + "description": "Create an automation that generates an async standup digest from Slack. Searches selected channels for messages since the previous workday, groups updates by project, highlights blockers and decisions, and posts a summary to a target channel.", + "keywords": [ + "slack", + "standup", + "digest", + "summary", + "daily", + "cron", + "automation" + ], + "name": "slack-standup-digest", + "source": "./skills/slack-standup-digest" + }, + { + "category": "productivity", + "description": "Write and edit clear, accessible prose in a plain English content style: active voice, front-loaded content, sentence case, and accessible formatting.", + "keywords": [ + "plain-english" + ], + "name": "plain-english-content", + "source": "./skills/plain-english-content" + }, + { + "category": "productivity", + "description": "Deploy a cron-based OpenHands automation that watches a Jira Cloud project for issues labeled with a configurable label (default: create-pr) and spawns an agent conversation to create a GitHub pull request for each new issue found. The target GitHub repo is read from the ticket body - no repo parameter required at deploy time.", + "keywords": [ + "jira", + "atlassian" + ], + "name": "jira-issue-to-pr", + "source": "./skills/jira-issue-to-pr" + } + ] +} diff --git a/AGENTS.md b/AGENTS.md index 9c874ce2..de5e84fd 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -106,7 +106,7 @@ When editing or adding skills in this repo, follow these rules (and add new skil - The test suite expects **every directory under `skills/`** to be listed in a marketplace. If you add a new skill (or rebase onto a main branch that added skills), update the appropriate marketplace file or CI will fail with `Skills missing from marketplace: [...]`. - `scripts/sync_extensions.py` keeps generated artifacts in sync: Claude Code command files, README catalog section, coverage checks, vendor symlinks, and root marketplace catalog copies. Run `python scripts/sync_extensions.py --check` (or just push — CI runs it) to verify everything is consistent. Run without `--check` to auto-fix. The "Quick Start" section in `README.md` (OpenHands SDK, Claude Code, and Codex setup instructions) is **manually maintained** above the auto-generated catalog markers and is intentionally not generated by the sync script. -- The repository root publishes the canonical marketplace catalog (`marketplaces/openhands-extensions.json`) as a single real `marketplace.json` copy at `.plugin/marketplace.json` — **not a symlink**, and **not** mirrored under `.claude-plugin/` or `.codex-plugin/` at the repo root. `raw.githubusercontent.com` serves git symlinks as their literal target text and does not dereference them (file or directory), so symlinks made the catalog unreachable over the raw URL (used by `github://openhands/extensions` consumers). `.plugin/` is this repo's canonical manifest directory, so the catalog lives there; consumers must fetch `.plugin/marketplace.json`. The `root-marketplace` sync task keeps this copy byte-for-byte in sync with the canonical file; never replace it with a symlink. (Note: per-skill/per-plugin `.claude-plugin` and `.codex-plugin` vendor symlinks *within* `skills/` and `plugins/` are unrelated and remain, managed by the `symlinks` task.) +- The repository root exposes the canonical marketplace catalog (`marketplaces/openhands-extensions.json`) as real `marketplace.json` copies under `.claude-plugin/`, `.codex-plugin/`, and `.plugin/` — **not symlinks**. `raw.githubusercontent.com` serves git symlinks as their literal target text and does not traverse symlinked directory paths, so symlinks made the catalog unreachable at the standard `.claude-plugin/marketplace.json` path (used by `github://openhands/extensions` consumers). The `root-marketplace` sync task keeps these copies byte-for-byte in sync with the canonical file; never replace them with symlinks. - The sync script uses PyYAML to parse SKILL.md frontmatter. If you add a skill with a slash trigger (e.g., `triggers: ["/mycommand"]`), the script auto-generates `commands/mycommand.md`. **Note:** Slash triggers in SKILL.md frontmatter are deprecated — prefer adding a `commands/command-name.md` file to the plugin's `commands/` directory instead. Keyword triggers (non-slash) remain the recommended way to activate skills by topic. ## OpenHands SDK documentation policy diff --git a/scripts/sync_extensions.py b/scripts/sync_extensions.py index 395af17b..b181e936 100644 --- a/scripts/sync_extensions.py +++ b/scripts/sync_extensions.py @@ -10,12 +10,12 @@ marketplace, or a marketplace entry points to a missing directory. 4. **symlinks** — enforce ``.plugin/`` as the canonical manifest directory with vendor symlinks (``.claude-plugin``, ``.codex-plugin``). - 5. **root-marketplace** — keep a real ``marketplace.json`` copy at the - repository root under ``.plugin/`` so consumers that fetch the catalog - over the GitHub raw URL (e.g. ``github://openhands/extensions``) can - read it. Git symlinks are stored as blobs and - ``raw.githubusercontent.com`` does not dereference them (it serves the - literal target text), so the root catalog must be a real file. + 5. **root-marketplace** — keep real ``marketplace.json`` copies at the + repository root under ``.claude-plugin/``, ``.codex-plugin/``, and + ``.plugin/`` so consumers that fetch the catalog over the GitHub raw + URL (e.g. ``github://openhands/extensions``) can read it. Git symlinks + are stored as blobs and ``raw.githubusercontent.com`` does not + dereference them through directory paths, so these must be real files. Usage: python scripts/sync_extensions.py # run all, write changes @@ -44,17 +44,13 @@ SKILL_DIRS = [REPO_ROOT / "skills", REPO_ROOT / "plugins"] MARKETPLACES_DIR = REPO_ROOT / "marketplaces" # The canonical marketplace catalog that the registry publishes. The -# repository root exposes a real (non-symlink) copy of this file at -# ``.plugin/marketplace.json`` so consumers that fetch the catalog over the +# repository root exposes copies of this file (not symlinks) under the +# vendor directories below so that consumers fetching the catalog over the # GitHub raw URL (``github://openhands/extensions``) can read it. PRIMARY_MARKETPLACE = MARKETPLACES_DIR / "openhands-extensions.json" # Vendor directories at the repository root that must each contain a real # (non-symlink) ``marketplace.json`` copy of ``PRIMARY_MARKETPLACE``. -# ``.plugin/`` is the canonical manifest directory for this repo, so the root -# catalog lives there. Other vendor aliases (``.claude-plugin/``, -# ``.codex-plugin/``) are intentionally NOT mirrored at the repo root — -# consumers must fetch the catalog from ``.plugin/marketplace.json``. -ROOT_MARKETPLACE_DIRS = [".plugin"] +ROOT_MARKETPLACE_DIRS = [".claude-plugin", ".codex-plugin", ".plugin"] # Max description length in the catalog table. 120 chars fits GitHub's # diff viewer and rendered Markdown tables without horizontal scroll. MAX_DESC_LEN = 120 @@ -460,20 +456,16 @@ def sync_root_marketplace(*, check: bool) -> list[str]: ``marketplaces/openhands-extensions.json``. Historically the root exposed it through a double symlink chain (``.claude-plugin`` -> ``.plugin`` and ``.plugin/marketplace.json`` -> the canonical file). ``raw.githubusercontent.com`` - serves git symlinks as their literal target text and does not dereference - them (file or directory), so consumers fetching the catalog over the raw - URL (e.g. the plugin-directory with - ``MARKETPLACE_SOURCE=github://openhands/extensions``) received a 404 (for - symlinked directory paths) or the literal symlink body (for symlinked - files) and saw an empty catalog. - - This sync keeps a single real ``marketplace.json`` copy at - ``.plugin/marketplace.json`` (this repo's canonical manifest directory) - that mirrors the canonical catalog byte-for-byte. The catalog is reachable - at ``.plugin/marketplace.json`` over the raw URL while staying in sync - with the single source of truth. Other vendor aliases - (``.claude-plugin/``, ``.codex-plugin/``) are not mirrored at the repo - root; consumers must fetch ``.plugin/marketplace.json``. + serves git symlinks as their literal target text and does not traverse + symlinked directory paths, so consumers fetching + ``.claude-plugin/marketplace.json`` over the raw URL (e.g. the + plugin-directory with ``MARKETPLACE_SOURCE=github://openhands/extensions``) + received a 404 (or the literal symlink body) and saw an empty catalog. + + This sync replaces those symlinks with real directory + file copies that + mirror the canonical catalog byte-for-byte, so the catalog is reachable + at every standard ``.claude-plugin/marketplace.json`` path while staying + in sync with the single source of truth. """ if not PRIMARY_MARKETPLACE.is_file(): return [f"canonical marketplace missing: {PRIMARY_MARKETPLACE.relative_to(REPO_ROOT)}"] diff --git a/tests/test_sync_extensions.py b/tests/test_sync_extensions.py index b41762d7..1cad1090 100644 --- a/tests/test_sync_extensions.py +++ b/tests/test_sync_extensions.py @@ -313,15 +313,12 @@ def test_all_source_paths_exist(self): # ── root marketplace copies ────────────────────────────────────────── class TestRootMarketplace: - """The root catalog lives at .plugin/marketplace.json as a real (non-symlink) file. - - raw.githubusercontent.com serves git symlinks as their literal target - text and does not dereference them, so consumers fetching the catalog - over the raw URL (e.g. plugin-directory with - ``MARKETPLACE_SOURCE=github://openhands/extensions``) need a real file. - .plugin/ is this repo's canonical manifest directory, so the catalog is - published only there (not mirrored under .claude-plugin/ or .codex-plugin/ - at the repo root). + """The root vendor marketplace.json files must be real (non-symlink) copies. + + raw.githubusercontent.com does not dereference git symlinks through + directory paths, so consumers using the standard + ``.claude-plugin/marketplace.json`` path (e.g. plugin-directory with + ``MARKETPLACE_SOURCE=github://openhands/extensions``) need real files. """ def test_vendor_dirs_are_real_directories(self): @@ -363,7 +360,7 @@ def test_marketplace_json_is_valid_catalog(self): assert len(data.get("plugins", [])) == len(canonical.get("plugins", [])) def test_sync_root_marketplace_detects_and_fixes_symlinks(self, tmp_path, monkeypatch): - """sync_root_marketplace replaces a symlinked .plugin/marketplace.json with a real copy.""" + """sync_root_marketplace replaces symlinked dirs/files with real copies.""" import json monkeypatch.setattr("sync_extensions.REPO_ROOT", tmp_path) @@ -376,21 +373,26 @@ def test_sync_root_marketplace_detects_and_fixes_symlinks(self, tmp_path, monkey canonical_bytes = (json.dumps(canonical_data, indent=2, ensure_ascii=False, sort_keys=True) + "\n").encode() (mp_dir / "openhands-extensions.json").write_bytes(canonical_bytes) - # Recreate the broken symlink from the issue (.plugin is a real dir, - # but marketplace.json is a symlink to the canonical file). + # Recreate the broken double-symlink chain from the issue. plugin_dir = tmp_path / ".plugin" plugin_dir.mkdir() (plugin_dir / "marketplace.json").symlink_to("../marketplaces/openhands-extensions.json") + (tmp_path / ".claude-plugin").symlink_to(".plugin") + (tmp_path / ".codex-plugin").symlink_to(".plugin") - # Check mode must report the symlink as a problem. + # Check mode must report the symlinks as problems. problems = sync_root_marketplace(check=True) + assert any("symlinked dir" in p for p in problems) assert any("symlinked file" in p for p in problems) - # Write mode fixes it. + # Write mode fixes them. sync_root_marketplace(check=False) - target = tmp_path / ".plugin" / "marketplace.json" - assert target.is_file() and not target.is_symlink(), f"{target} still a symlink file" - assert _normalize_marketplace_bytes(target.read_bytes()) == canonical_bytes + for vendor in [".claude-plugin", ".codex-plugin", ".plugin"]: + vendor_dir = tmp_path / vendor + target = vendor_dir / "marketplace.json" + assert vendor_dir.is_dir() and not vendor_dir.is_symlink(), f"{vendor} still a symlink dir" + assert target.is_file() and not target.is_symlink(), f"{target} still a symlink file" + assert _normalize_marketplace_bytes(target.read_bytes()) == canonical_bytes # After fixing, check mode is clean. assert sync_root_marketplace(check=True) == [] @@ -409,25 +411,19 @@ def test_sync_root_marketplace_detects_stale_copy(self, tmp_path, monkeypatch): (mp_dir / "openhands-extensions.json").write_bytes(canonical_bytes) stale = {"name": "openhands-extensions", "plugins": []} - (tmp_path / ".plugin").mkdir() - (tmp_path / ".plugin" / "marketplace.json").write_text(json.dumps(stale)) + for vendor in [".claude-plugin", ".codex-plugin", ".plugin"]: + (tmp_path / vendor).mkdir() + (tmp_path / vendor / "marketplace.json").write_text(json.dumps(stale)) problems = sync_root_marketplace(check=True) - assert len(problems) == 1 + assert len(problems) == 3 assert all("out of date" in p for p in problems) sync_root_marketplace(check=False) - assert _normalize_marketplace_bytes((tmp_path / ".plugin" / "marketplace.json").read_bytes()) == canonical_bytes + for vendor in [".claude-plugin", ".codex-plugin", ".plugin"]: + assert _normalize_marketplace_bytes((tmp_path / vendor / "marketplace.json").read_bytes()) == canonical_bytes assert sync_root_marketplace(check=True) == [] - def test_no_root_claude_or_codex_vendor_dirs(self): - """Only .plugin/ exposes the root catalog; .claude-plugin/ and .codex-plugin/ must NOT exist at the repo root.""" - for vendor in [".claude-plugin", ".codex-plugin"]: - assert not (REPO_ROOT / vendor).exists(), ( - f"{vendor}/ exists at the repo root; the catalog is published only via " - ".plugin/marketplace.json to keep a single source of truth" - ) - if __name__ == "__main__": pytest.main([__file__, "-v"])