build-setup
Set up build environment and test fixtures for COBOL-to-Java migrations. Creates compilation infrastructure for both languages…
Create an automation that implements GitLab issues when a configurable trigger label is applied. Polls one or more projects deterministically, clones the default branch, starts one OpenHands conversation per label event, then commits, pushes, and opens the merge request itself.
$ npx -y skills add openhands/extensions --skill gitlab-issue-to-mr --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/gitlab-issue-to-mrContext preview
The summary Claude sees to decide when to auto-load this skill.
Create an automation that implements GitLab issues when a configurable trigger label is applied. Polls one or more projects deterministically, clones the default branch, starts one OpenHands conversation per label event, then commits, pushes, and opens the merge request itself.
name: gitlab-issue-to-mr description: > Create an automation that implements GitLab issues when a configurable trigger label is applied. Polls one or more projects deterministically, clones the default branch, starts one OpenHands conversation per label event, then commits, pushes, and opens the merge request itself. triggers: - /issue-to-mr:setup
Create a cron automation that watches one or more GitLab projects for issues with a trigger label, starts an OpenHands conversation once per label event with the project's default branch already checked out, and opens a merge request with whatever the agent produced.
The automation script is deterministic: issue discovery, label-event tracking, state persistence, the clone, the branch, the commit, the push, the merge request, the issue comments, and the clone's removal are all handled in Python. The LLM is invoked only to write the code.
The agent is told **which** issue to implement, not what it says. It fetches the description, the discussion, and whatever they link to itself, so nothing in the prompt goes stale between dispatch and the moment the agent reads it.
That needs read access, so the conversation is handed one secret, `GITLAB_TOKEN`. `AGENT_SECRET_NAMES` stays an allow-list: the rest of the deployment's secret store is not reachable from a conversation whose instructions came from an issue. On OpenHands Cloud and Enterprise the conversation runs with the user's own settings instead: the connected GitLab integration's token, or the tools of the connected GitLab MCP server.
The deployment's MCP servers are forwarded whole, matching `github-pr-reviewer`, so a connected GitLab server gives the agent typed tools rather than curl. What those servers reach is reachable from an issue-authored prompt, so connect only servers that may be driven by untrusted text.
The agent also finishes the job: it commits, pushes its branch, and opens the merge request, so the merge request appears when the agent stops rather than on the next poll. The script does not trust that it happened - when the conversation ends it asks GitLab whether the merge request exists, and opens it itself when it does not. `origin` still carries no credential, so every GitLab command the agent runs has to name `GITLAB_TOKEN`; the SDK only puts a secret in the environment of a command that mentions it, and masks it in the output.
---
On OpenHands Cloud and Enterprise, no secret is needed. A connected GitLab MCP server (Settings -> MCP) is used directly, by the poller and by the conversations it starts; a connected GitLab integration (Settings -> Integrations, connected by signing in with GitLab) serves both with its token. With only the MCP server, the conversation commits through its tools and reads a private project through them rather than cloning it.
Calling GitLab MCP directly needs GitLab 19.4 or later, where the branch, commit, repository and work item tools this uses first appear. A token works with any GitLab, so whenever there is one - the token of the user's GitLab sign-in or connected integration, or a `GITLAB_TOKEN` secret - the poller and its conversations use it rather than the MCP server. On an older GitLab, sign in with GitLab or connect it under Settings -> Integrations; a `GITLAB_TOKEN` secret is only needed when neither is possible.
On a local Agent Canvas, or when neither is connected, verify that the following secret is set in **OpenHands Settings -> Secrets**:
| Secret name | Token type | Minimum requirements | |---|---|---| | `GITLAB_TOKEN` | Personal access token | `api` scope, and at least the **Developer** role on every watched project | | `GITLAB_TOKEN` | Project or group access token | `api` scope, role **Developer** or above |
The `api` scope is what GitLab grants read and write on issues, notes, branches, and merge requests through one scope; `read_api` polls happily and then fails at the point of pushing. Developer is the lowest role that can push a branch and open a merge request.
Two things the role does not cover, and which fail the push rather than the poll:
automation never pushes to it. Protect the branch prefix as well and the push is rejected; leave `openhands/issue-*` unprotected.
`.gitlab-ci.yml`. That needs no extra scope, but a project with a protected CI/CD configuration path rejects the push.
When several projects are monitored, the token must cover all of them.
Check with:
curl -s "https://gitlab.com/api/v4/user" \
-H "PRIVATE-TOKEN: $GITLAB_TOKEN" \
| python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('username') or d.get('message'))"If the token is missing or invalid, inform the user and stop.
---
Follow these steps in order.
On OpenHands Cloud and Enterprise, read `GET ${OPENHANDS_HOST}/api/v1/settings` first. `gitlab` in `provider_tokens_set` means the user signed in with GitLab or connected the integration, and its token is used, with any GitLab version: skip the token check and go to Step 2. Otherwise, an entry in `agent_settings.mcp_config` whose `url` is the instance's `/api/v4/mcp` means the poller uses that server: put its key in `gitlab_mcp_server`, or leave it out and the run finds the server itself. Call its `get_mcp_server_version` tool, and on 19.4 or later skip the token check and go to Step 2. Calling GitLab MCP directly needs 19.4 or later, so on an older GitLab tell the user that and ask them to sign in with GitLab or connect it under Settings -> Integrations. Only if they can do neither, ask for a `GITLAB_TOKEN` secret and run the token check below.
Otherwise run the `curl` check above, against the user's instance if it is not `gitlab.com`.
This repository is the public extensions registry for OpenHands. It contains reusable, shareable skills, plugins, and Agent Canvas Apps that customize agent behavior and interfaces. Skills overview docs: SDK skill guide:
Set up build environment and test fixtures for COBOL-to-Java migrations. Creates compilation infrastructure for both languages…
End-to-end COBOL to Java migration workflow. Handles build setup, mainframe dependency removal, and code migration with test…
Create a transformation guide for replacing mainframe-specific COBOL constructs with standard COBOL equivalents. Use when…
Apply mainframe dependency transformations to COBOL code using a pre-generated transformation guide. Converts CICS/VSAM…
Migrate COBOL code to idiomatic Java, preserving business logic while following Java best practices. Use for COBOL modernization…
A test skill that responds to the magic word "alakazam" with a specific phrase