Skip to content
Skip to content
HCP

Pack classes

Five shapes almost every pack falls into (public read, gated write, linked channel, emit-only, control). Pick one, copy the sample, change four fields.

Do not design a new lattice per CLI. Pick the class, copy the sample, and change the fields; the three files are the same every time.

Picker

If the capability…Class
Needs no login and is a small closed read setPublic read
Needs a connect step, and has writes that must not auto-fireGated write
Is a linked personal or project stream with real push eventsLinked channel
Is ingress or webhook only, with no user commandsEmit-only
Runs under a different Binding than the user runtimeControl, which is a second pack
Is MCP-only with no CLI and no doctorDo not wrap. Ship a CLI first

Public read

No login. Five to twelve closed read commands, such as a discover, plan, show sequence or an equivalent closed set.

Bindingpublic
Landpersonal
Commandsfind · plan · show · status · follow (or equivalent)
SenseOptional. Pull observation until a real push exists
Sampleexamples/packs/transit

follow is a read command an agent may call repeatedly. If the source later pushes, add a stimulus. Do not overload plan.

Gated write

A connect step plus at least one write that must not fire from a hallucinated turn: transfer, send, apply, delete.

Bindinglocal or user, with a credential hub
Landlocal (workspace directory) or personal
Commandssetup.status · setup.apply · connect · status · one read · one confirm write
Sensebinding.degraded when connect health moves
Sampleexamples/packs/ledger
ledger setup status --json           # read, idempotent
ledger setup all -y --json           # write, no wizard on the agent path
ledger connect demo --json           # write, gated by pack.connect
ledger list --json                   # read
ledger transfer 10 --confirm --json  # write + confirm

Proof: the transfer without --confirm returns { "ok": false, "error": "confirm required" }.

Linked channel

A personal or project stream (mail, calendar, chat, tickets) under a shared Binding family. This is the class that uses both loops.

Bindinguser, shared family
Landpersonal or brain
Commandslist / get / send (send is write, usually confirm)
SenseChannel event (new_item) + binding.degraded
Adaptercomposite once the SDK is stable; wrap is a fine bootstrap

Mail, calendar, chat, and tickets are the same class. They differ only in Binding family and payload.

Emit-only

The pack only announces. It needs no user CLI.

Adaptersense_only
Commandsnone
Sensestimulus refs + Policy rows
Bindingnone or public

Do not invent bash to "install a webhook". connect or setup.* exist only if the upstream source needs a registration call.

Control

Admin, fleet, operator, and origin tools. They run under a different Binding than the user runtime, so they are a different pack.

Manifestplane: "control"
Bindingmothership
SenseOptional health. Never a user inbox
RuleSecond pack. Never silently on an end-user Principal

If a domain CLI has both an admin face and a user face, that is two packs sharing a bin and nothing else.

Promotion

Classes are stable; adapters move.

pass_through  ──►  named 5–12 commands + policy.json  ──►  composite for hot paths

Every step keeps pack_id, verb_key, and Policy unchanged.

What not to do

  • A sixth class "because this domain is different"
  • One pack that is both user runtime and operator control
  • A catalog of many packs with no lint, no twin-face check, and no gated-write proof
  • Wrapping an MCP-only SDK that has no CLI