openreachtech/hora-core/hora-addon

Claude Code and agent skill by openreachtech/hora-core

Trust tier 2
  • community
  • ext:[{"type":"plugin","description":"Custom plugin integration"}]
LLM review pending
Source check pending

Checking that the SKILL.md file is still in the repository.

How an add-on extends the hora skills — the Hora Kit range it is built for, the wings every hora skill resolves before it acts, how several add-ons combine where they touch the same section, and the precedence a person may set between them. Read by every hora skill once its version is fixed, and again after a resume or a compacted context. Invoked directly as /hora-addon to set or check that precedence. What an add-on itself decides belongs to that add-on's own skill.

Install

npx vskill@latest install openreachtech/hora-core/hora-addon

Semi-extensibleMentions customization, but needs skill-specific knowledge. Read the extensible skills standard

SKILL.md

hora-addon

The rule every hora skill follows about add-ons. An add-on is a package installed beside Hora Kit that lets the hora skills do what they could not do on their own. This skill says what an add-on may carry, when it takes effect, and what happens where several of them reach the same place. Each add-on describes itself, and the examples here use invented names (alpha-example-addon, beta-example-addon). Hora Kit may name an add-on, public files included. An add-on is protected by its distribution channel — a private package of the npm organization, readable only by the teams that bought it — not by keeping its name out of public files.

An add-on that is not installed changes nothing, and neither does one that is installed but not active. Every rule below starts from the skills as they are written and changes them only where an active add-on says so.


What an add-on carries

An add-on carries skills, wings, or both.

PartWhat it isInstalled at
a skilla skill in its own right, invoked as any other.claude/skills/<skill-name>/
a winga file that extends what an existing skill can do. The skill itself stays as written.hora/wings/<skill-name>/<addon-name>/
its definitionthe add-on's name, when it is active, and the Hora Kit it needs.hora/addons/<addon-name>.json

The name "wing" carries two readings, and both are meant. A wing lets something fly that could not — a skill gains what it could not do. A wing of a building is joined to the original, which stays standing as it was — the skill is never replaced.

Wings and definitions sit under `.hora/`, not `.claude/`. .claude/ holds what Claude Code reads, and both are read only by the hora skills, so they belong in Hora's own directory.

Everything under `.hora/wings/` and `.hora/addons/` is written by the add-on's installer, and nothing else writes there. Hora Kit's own installer never touches either, so reinstalling Hora Kit leaves every add-on in place. Neither is committed: both are regenerated on every install, unlike the records under .hora/.

The definition goes with the wings pass, whether or not the add-on carries any wings. hora-addon-<name> install --only wings, and install with no --only, places it; uninstalling the wings part removes it; --only skills alone leaves it as it is.

The Hora Kit it was built for

Every add-on states the range of `@openreachtech/hora` it was built against, as `horaKit` in its definition, whatever it carries — skills, wings or both. Its definition is read by Hora Kit's resolving, and its wings find their sections by heading. A heading exists in some versions of Hora Kit and not in others, so the range is what says which headings the add-on relies on.

json
"horaKit": "^1.0.0"
  • A condition on the consuming repository, never a dependency. The add-on uses nothing of Hora Kit; Hora Kit's skills read the add-on. As a peer dependency, npm would install Hora Kit into the add-on's own repository as well, where nothing uses it. As a dependency, each add-on could install a Hora Kit of its own, and its wings would be checked against a copy the project never runs.
  • The field is never left out. A forgotten range is not read as any: that would place wings beside a Hora Kit that may carry none of their sections.
  • The range is the one source. Nothing else restates it.
  • The lower bound is the first Hora Kit release carrying every `[wing]` section the add-on's wings extend, and the caret stays. Renaming or removing a [wing] section is a breaking release ("The [wing] sections", below), so every version the caret admits still carries them. While Hora Kit is in beta (`0.x.x`), a range such as `>=0.10.0 <1.0.0` is allowed as an exception, since a caret there stops at the next minor; any 0.x minor may then rename a section the wings extend.
  • The add-on's installer checks the installed Hora Kit against it, before placing anything, and changes nothing where the definition declares no range, or one semver does not read, where no Hora Kit is installed, or where the one installed is outside the range. It resolves @openreachtech/hora/package.json from the consuming repository as Node would, reads its version, and holds it against the range with the semver package. npm never reads the field, so this check is the only one, and a wing installed against headings that are not there does nothing at all, without a word. The cheapest place to stop that is before anything is copied. uninstall checks nothing.
A wing overlays, it never copies

A wing file sits at the same relative path, under its skill's name, as the file it extends, and holds nothing but the [wing] sections it changes.

.claude/skills/hora-plan/SKILL.md the skill as written
.claude/skills/hora/references/asking.md
.hora/wings/hora-plan/alpha-example-addon/SKILL.md overlays hora-plan/SKILL.md
.hora/wings/hora/alpha-example-addon/references/asking.md overlays hora/references/asking.md
  • A wing is looked up by the file it extends, never by the skill reading it. A skill reading a file that holds a [wing] section takes the skill that file belongs to, and looks for a file at the same relative path under .hora/wings/<that skill>/*/. asking.md belongs to /hora, so every skill that reads it finds the same wing.
  • A file that extends no `[wing]` section does not belong under `wings/`. Material an add-on adds of its own goes into the add-on's skills, where a wing may point at it.
  • A wing file whose counterpart does not exist is an error, not an addition. It usually means the skill renamed or moved the file, and the wing no longer reaches anything. Such a wing is reported and left out, and so is one whose heading matches no section; the run goes on. Only two active add-ons that exclude each other stop a run.

Resolving the add-ons

Every hora skill resolves the add-ons as soon as it knows which version it is working on, whatever started it. /hora resolving them does not excuse /hora-plan when /hora starts it: /hora-plan resolves them again at its own start. Resolve them again after a resume and after the context is compacted, because what the conversation remembers about them does not survive either.

1. Read every .hora/addons/<addon-name>.json.
2. For each, decide whether it is active for this version:
activeWhen is "always" -> active whenever it is installed
activeWhen is "declared" -> read the record
.hora/tasks/<version>/_<addon-name>.md
it holds the line <addon-name>: on -> active
it does not, or it does not exist -> not active
activeWhen is missing, or anything else
-> the definition is at fault: not active,
and reported
3. Do two active add-ons exclude each other — either one's exclusiveWith
naming the other? -> stop the run, with neither applied
("Add-ons that are never active
together", below)
4. Where at least one add-on is installed, report the active ones in one line
"add-ons active for 1.0.0: alpha-example-addon"
"add-ons active for 1.0.0: none"
Where none is installed, report nothing.

The line is for catching a mistake before it runs. An add-on a person believes they declared and did not, or one active that nobody remembers declaring, shows in it. `none` is reported too, because an installed add-on that is not active is exactly the case worth seeing. A project with no add-on at all gets no line, since there is nothing it could be mistaken about.

The file decides, never the conversation. A person who says an add-on is on, while its record says otherwise, has not turned it on; the add-on's own skill is what writes the record.

A declaration belongs to one version, and no record declares an add-on for every version. An add-on that is to take effect for every version says so in its definition, as "activeWhen": "always". What happens during one version's run — a stop, an end — is written in the same record, under <version>/.

The definition file
json
{
"name": "alpha-example-addon",
"activeWhen": "declared",
"description": "Active while it is declared on for the version.",
"horaKit": "^1.0.0"
}
FieldHolds
namethe add-on's name, and the directory its wings sit under
activeWhen"declared" — active while its record declares it on. "always" — active whenever it is installed
descriptionone line for whoever lists the add-ons
exclusiveWithoptional: the add-ons this one is never active together with
horaKitthe range of Hora Kit the add-on was built against ("The Hora Kit it was built for", above)

The add-on's source carries its definition as `kit/addon.json`, without `name`. The installer reads the name from the package name, @openreachtech/hora-addon-<name>, and writes it in as the first field, so the definition can never name the add-on differently from its package.

An add-on's record is named after the add-on: `_<addon-name>.md`, declaring itself on with the line `<addon-name>: on`. Its name is already unique among the add-ons, so no two records can claim one file, and a reader of .hora/tasks/<version>/ can tell whose record each one is without opening it. That is why the definition names no record: a record's name that followed from the add-on's and were also written down could disagree with it, the day either is renamed.

`activeWhen` is never left out. An add-on that is to take effect whenever it is installed says so, as "activeWhen": "always". A missing field is not a value: were it to mean always, a definition that simply forgot the field would take the strongest effect there is, and nothing reading it could tell the forgetting from the intent. The add-on's installer refuses a definition without it, or with any value but "declared" and "always", before placing anything.

Add-ons that are never active together

Two add-ons that build different kinds of thing are never active for one version. One building toward a release and one building a proof of concept, say: nothing either decides means anything to the other's product, so no precedence and no judgment could combine them.

json
{
"name": "beta-example-addon",
"activeWhen": "declared",
"exclusiveWith": ["alpha-example-addon"],
"description": "…",
"horaKit": "^1.0.0"
}
  • Naming it on one side is enough. An add-on built later states the relation without the earlier one being changed.
  • Found at resolving, the pair stops the run, with neither add-on's wings applied, reported as ../hora/references/structure.md, "How to close a run", says. The way on is to take one declaration back. Which one is a decision about what the project is building, so it is the person's: no precedence set in .hora/addon/config.json and no judgment decides it.
  • The add-on's own skill refuses first. It does not record a declaration while an add-on it excludes, or one that excludes it, is active for the version. Resolving is the guard behind it.
  • `exclusiveWith` may be left out, unlike activeWhen. Its absence means no exclusion, which is true of most add-ons, and forgetting it grants nothing stronger than what the add-on already had.

The [wing] sections

A skill marks the sections an add-on may change, and only those. A section a skill has not marked cannot be changed by any add-on.

markdown
## [wing] Whether the run may go on past an open blocking question
## [wing] How to decide without asking

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 100 of 100Pattern checks on the skill's files.
  • Model reviewNot runA model review is scheduled for the next rescan.

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
56
7-day trend score
0

Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.

Extension points

  • pluginCustom plugin integration

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/openreachtech/hora-core/hora-addon/badge)](https://verified-skill.com/skills/openreachtech/hora-core/hora-addon)

Something wrong with this skill or its page? Tell us.