agentleFS
colonyopscolonyops/hive/.agents/skills/desktop-devserver/SKILL.md

desktop-devserver

Skill41 starsChanged 7 days agoMITView on GitHub

Drive the local devserver at http://127.0.0.1:7777 to simulate GitHub lifecycle events and webhook deliveries against a running Hive Desktop instance. Use when asked to run a scenario, simulate a PR/issue event (review requested, approved, merged, CI, comment, mention), exercise the feed through the dev proxy, or reproduce a lifecycle bug end to end.

  • Sends data out

The file

We split this skill into the rules it gives an agent

2 rules. About 0 are common, 1 is distinctive, and 1 is very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈1

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 1

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    If /_ctl/health fails, devserver is not running — ask the user to start it with mise run desktop:devserver (leave it running).

    line 39
  2. Distinctive:

    If the list is empty, the connected instance has not polled yet.

    line 56

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Drive the devserver

cmd/desktop/devserver fronts the GitHub API for local development. Beyond caching, it simulates events two ways, and you drive both over its JSON control API under /_ctl/ at http://127.0.0.1:7777:

  • Proxy overlays rewrite what GitHub appears to say about an item — its state, labels, notification reason, draft flag, or presence in search. This is what a sources.github node sees.
  • The webhook pusher injects an event that never came from GitHub at all, delivered to a running instance's sources.webhook listener.

Pick the lever that matches the flow under test: a bug in GitHub classification is a proxy overlay; a bug in webhook ingest is a push.

The action vocabulary is deliberately GitHub's own. The desktop reads exactly four things — state, updatedAt, labels, and a notification reason — so those are the only levers. There is no approve action: GitHub has no such notification reason and the app never reads review state, so an approval reaches it as approval-requested activity on the item. Do not invent a richer vocabulary; it would teach a wrong model of the app.

1. Confirm the setup

# readiness: devserver up, and whether an app has connected + observed items
curl -sf localhost:7777/_ctl/health | jq .   # {devserver, appConnected, requests, itemsObserved, ...}

# is this the build under test? (VCS revision + dirty flag)
curl -s localhost:7777/_ctl/version | jq .    # compare .revision to `git rev-parse HEAD`

If /_ctl/health fails, devserver is not running — ask the user to start it with mise run desktop:devserver (leave it running). Do not start it yourself in a way that would block the session; suggest they run ! mise run desktop:devserver or a background tab. If appConnected is false, no desktop instance has polled yet — start or wait for one before targeting items. If /_ctl/version .revision does not match your working tree, the running proxy is a stale build.

2. Find an item to target

Overlays, actions, and scenarios address an item by repo and num, and only an item the proxy has already observed exists to rewrite. Read the live state and pick one:

curl -s localhost:7777/_ctl/state | jq '.items[] | {repo, num, kind, title, state, overlaid}'

If the list is empty, the connected instance has not polled yet. Let it tick once (its floor is 60s) and read again. For webhook pushes the item is invented by the payload, so no observed item is needed.

3. Drive the right lever

One event

# a quick action from the vocabulary (see .actions in /_ctl/state for the full list)
curl -XPOST localhost:7777/_ctl/action \
  -d '{"repo":"acme/widgets","num":42,"action":"review-requested"}'

# a raw mutation when an action does not fit
curl -XPOST localhost:7777/_ctl/overlay \
  -d '{"repo":"acme/widgets","num":42,"set":{"labels":["needs-review"],"reason":"comment"}}'

Actions and overlays accumulate onto the item; each call merges over the last. updatedAt is auto-stamped, because the classifier ignores a change that does not advance it.

A multi-step scenario (compose it for the test)

Build the exact sequence the test needs and POST it. Steps run in the background; each is an action or a raw set, with an optional wait. A wait should exceed the app's 60s poll floor if each step must land as its own event rather than collapsing into one.

curl -XPOST localhost:7777/_ctl/scenario -d '{"steps":[
  {"repo":"acme/widgets","num":42,"action":"review-requested"},
  {"wait":"70s"},
  {"repo":"acme/widgets","num":42,"action":"approval-requested"},
  {"wait":"70s"},
  {"repo":"acme/widgets","num":42,"set":{"state":"merged","absent":true}}
]}'
# -> {"scenario":"scenario-1","steps":5}

The response returns immediately. Watch it finish in /_ctl/state: an in-flight run appears under .scenarios and disappears when done.

curl -s localhost:7777/_ctl/state | jq '.scenarios'   # [] once the run completes

A bad step (unknown action, invalid repo, both action and set, a step that does nothing) fails the whole request with a 422 naming the step in fields — read it and fix the step rather than retrying blind.

A webhook push

The pusher needs a target. The desktop's webhook port is random per install, so supply it inline as {url, secret}. Read the host/port and path prefix from the app API's /api/status (.webhook.host, .webhook.port, .webhook.pathPrefix — see the desktop-api skill) and append a sources.webhook node's path; secret must match that node's. Inline targets must be loopback.

curl -XPOST localhost:7777/_ctl/webhooks/push -d '{
  "target": {"url":"http://127.0.0.1:24681/hooks/devserver","secret":"dev-secret"},
  "body":   {"id":"evt-1","kind":"PR","repo":"acme/widgets","num":42,
             "title":"Add retry","url":"https://github.com/acme/widgets/pull/42","state":"open"}
}'

A stable top-level id makes a re-push update the same inbox item; drive it to a terminal state (resolved/closed/done) to archive it. Payloads following the canonical item contract (ADR canonical-item-contract) render as first-party feed rows. A configured payload can be used instead of an inline body via "payload":"pr-opened" with optional "overrides":{...}.

4. Verify through the app's MCP tools, then clean up

Confirm the app reacted through its loopback MCP server — do not read desktop-pipeline.db. After a proxy overlay/action/scenario, force a re-poll so you do not wait the 60s floor, then read and retry (the engine commits a moment after the fetch):

# source_refresh reloads now (pull sources), inbox_list reads the result
call source_refresh
call inbox_list '{"profileId":"'"$P"'"}' | jq '.items[] | {title, lifecycle, sourceState, unread}'

A webhook push already appends directly, so skip the refresh and just read + retry. See the desktop-api skill for discovering the port, connecting to /mcp (including the call helper above), the read tools, and the reload → read → retry loop in full. Then reset so the next test starts clean:

curl -XPOST localhost:7777/_ctl/overlay/clear -d '{"repo":"acme/widgets","num":42}'  # one item
curl -XPOST localhost:7777/_ctl/overlays/clear                                       # everything

Guardrails

  • Overlays are global and shared across worktrees. Clearing is global, and every instance pointed at the proxy sees the same overlays. Do not leave a simulation in place after a test — clear it.
  • State is in-memory. A devserver restart drops every overlay and running scenario and returns to what devserver.yaml declares (no overlays). Nothing you set here persists.
  • Loopback only. Inline webhook targets must be a loopback URL; the endpoint rejects anything else.
  • Do not edit devserver.yaml to run a scenario. Scenarios are composed at runtime through /_ctl/scenario; the config no longer defines them.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.