Skip to content
Agent Orchestration
Skill

/software-factory

Set up an OpenHands "software factory" on GitHub fast: ask only for the repositories and where tickets live (GitHub issues, Jira or Linear), create a working issue-to-PR and PR-review pipeline from the automation catalog with defaults, show what runs, then let the user stop or

BOOST
From plugin
extensions
17185 skills4 commands
Install
$ npx -y skills add openhands/extensions --skill software-factory --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/software-factory

Context preview

The summary Claude sees to decide when to auto-load this skill.

Set up an OpenHands "software factory" on GitHub fast: ask only for the repositories and where tickets live (GitHub issues, Jira or Linear), create a working issue-to-PR and PR-review pipeline from the automation catalog with defaults, show what runs, then let the user stop or

SKILL.md

software-factory.SKILL.md
name: software-factory
description: >
  Set up an OpenHands "software factory" on GitHub fast: ask only for the
  repositories and where tickets live (GitHub issues, Jira or Linear), create a working issue-to-PR and PR-review pipeline from the
  automation catalog with defaults, show what runs, then let the user stop or
  extend it one step at a time (tune settings, AGENTS.md maintainer,
  auto-merge, stale-CI and QA add-ons).
triggers:
  - /software-factory
  - software factory

Software Factory

Build a GitHub software factory from unmodified automation catalog bundles (`automations/catalog/<id>/manifest.json`); a Jira or Linear station is created by its own skill. This skill adds no automation logic.

Two phases: **Phase 1** gets a working factory after one question. **Phase 2** extends it in short rounds, only as far as the user wants. After Phase 1 and after every round, the **Checkpoint** shows what exists and lets the user stop.

Code lives on GitHub. Tickets can come from GitHub issues (default), Jira or Linear: only the issue to PR station changes (see "Ticket source"). GitLab and Bitbucket code hosts are not part of this flow.

Stations

| Station | Catalog id | Phase | Needs agent profile | |---|---|---|---| | Issue to PR | `github-issue-to-pr`, or the Jira or Linear station | 1 | yes (GitHub issues only) | | PR reviewer | `github-pr-reviewer` | 1 | yes | | Issue triage | `github-issue-triage`, or `linear-triage-assistant` | 1 | yes (GitHub issues only) | | AGENTS.md maintainer | `github-agents-md-maintainer` | add-on | no | | Auto-merge watchdog | `github-delivery-watchdog` | add-on | no | | Stale-CI PR closer | `github-stale-ci-pr-closer` | add-on | no | | QA changes | `qa-changes` | add-on | no |

Helper script

`scripts/factory.py` in this skill's directory does every catalog and API step and prints one JSON document; it exits non-zero with `{"error": ...}` on failure. Its usage is below: do not read its source, and do not load the `openhands-automation` skill for Phase 1.

Set `OPENHANDS_HOST` to the **Ingress** URL in `<RUNTIME_SERVICES>` on a local Agent Canvas (it serves both `/api/automation` and `/api`; the automation backend URL does not), or to `<HOST>` on OpenHands Cloud. Run every command as:

GITHUB_PERSONAL_ACCESS_TOKEN="$GITHUB_PERSONAL_ACCESS_TOKEN" \
OPENHANDS_AUTOMATION_API_KEY="$OPENHANDS_AUTOMATION_API_KEY" \
OPENHANDS_API_KEY="$OPENHANDS_API_KEY" \
python3 <this skill's directory>/scripts/factory.py <command> ...

`$F` below stands for that whole line. Keep the secret names in it: the agent server passes a saved secret into a command only when the command names it. The script reads the token and never prints it.

| Command | Does | |---|---| | `$F preflight --repos a/b,c/d` | Which stations this deployment supports, the agent profile, the GitHub login, push access per repository. | | `$F create --repos a/b --ids ID,ID [--set FIELD=VALUE] [--set ID.FIELD=VALUE]` | Fills each station's form (answers, then derived values, then manifest defaults), uploads the bundle and creates it disabled. `FIELD=VALUE` applies to every listed station with that field. Stations that already exist are reported under `existing`, not recreated. | | `$F tune --repos a/b --ids ID,ID [--set FIELD=VALUE] [--set ID.FIELD=VALUE]` | Applies new settings to an existing station by updating it in place. Use this to change a value that is fixed at creation. | | `$F verify ID... [--no-wait ID...]` | Dispatches once, enables the ones whose run `COMPLETED` and disables the rest, reporting their `error_detail`. `--no-wait` enables without waiting. | | `$F status ID...` | The latest run of each. | | `$F prs --repos a/b [--branch-prefix P]` | Open pull requests whose branch starts with `P` (default `openhands/agents-md`, the AGENTS.md maintainer's). | | `$F reset-token` | Deletes the saved `GITHUB_PERSONAL_ACCESS_TOKEN` (local Agent Canvas), so `request_secret` opens its form again. |

`create` and `verify` return each automation's `url`, its page in Agent Canvas. Trust the script's output: do not open pages in the browser to check them, and do not use the task tracker for this flow.

Add `--profile NAME` to `preflight` or `create` to use a profile other than the active one.

Rules

  • **Supported stations**: create only those `preflight` reports `ok`; say why

the others are skipped.

  • **Derived values** (the script fills them; never ask): every

`githubTokenSecret` is `GITHUB_PERSONAL_ACCESS_TOKEN`. The watchdog's `branchPrefix` must equal issue to PR's: when it was changed, pass `--set github-delivery-watchdog.branchPrefix=<same value>`.

  • **Agent profile**: if `preflight` reports a profile error, skip the stations

that need one and point the user to the station's catalog card in Agent Canvas (Automations), which has a profile picker.

  • **Token**: never ask for its value in chat, echo it, or put it in a tool

argument or file.

  • **Failures**: if `create` fails, its output lists the stations it already

created; report them with the error and ask whether to retry or delete them (`DELETE ${OPENHANDS_HOST}/api/automation/v1/{id}`).

  • **Existing stations**: a station `create` reports under `existing` was already

set up by an earlier run and was left unchanged. Say so rather than presenting it as new, and change it with `$F tune` if the user wants different settings.

Phase 1 - Working factory

1. Ask, in one message: "Which GitHub repositories (`owner/repo`)? Where do tickets live: GitHub issues (default), Jira or Linear?" Say that everything else uses defaults that can be changed afterwards. If the answer names only repositories, use GitHub issues; do not ask again. 2. Run `$F preflight --repos <repos>`. Drop repositories without `push`, and say which. 3. If `github_login` is null, act on `token_error`:

  • `not_set`, and the `request_secret` tool is available: call it once with

`name: "GITHUB_PERSONAL_ACCESS_TOKEN"` and a `re

Read more
Ships withextensions

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:

Get the whole plugin

Other skills on extensions.