GhostGet

How-to guide · plugin authoring · GhostGet 0.19.0

Write a provider plugin and prove one operation

A new portable plugin starts private and in the capture-required state, with no network access and nothing it can run. It becomes runnable only after its exact provider contract and secret-free fixtures are reviewed, the package passes static and runtime verification, and you explicitly trust that content-addressed bundle.

This guide describes GhostGet v0.19.0.

Two plugin forms share one semantic catalog

A source plugin ships with GhostGet, loads in process, and may implement a reviewed provider transport. It is trusted application code. A portable plugin is independently authored, content-addressed, installed into local state after an explicit code-trust decision, and run through a versioned, denied-by-default child-process protocol.

Neither plugin form can redefine GhostGet's custody rules. The kernel owns input resolution, auth selection, risk, preview and confirmation, bounded owner messaging grants, dispatch journals, recovery, receipts, bounds, redaction, activation, and lifecycle serialization. A plugin owns the exact provider identity, operation descriptors, request and response contracts, account probes, execution, and reconciliation logic.

A source plugin may use local-cli to place an exact reviewed provider executable, including declared patches, behind semantic operations. That binding pins each supported executable and archive digest, isolates ambient CLI and plugin state, and owns fixed argument and output contracts. Portable protocol v1 cannot request native process authority, and neither plugin form exposes a generic command runner.

1. Create the plugin skeleton

ghostget plugin init example-web \
  --display-name "Example" \
  --surface example \
  --origin https://www.example.com \
  --operation feeds.read \
  --output /absolute/private/example-web

The initializer writes a strict ghostget-plugin.json, one self-contained runtime, inert operation metadata, secret-free fixtures, and package-local guidance. capture-required means the operation cannot plan or execute. That is the correct state until authorized evidence proves the full contract.

2. Prove the whole operation contract

Before you mark an operation observed, establish all of the following:

  • One semantic operation and a bounded input schema.
  • The exact transport and any declared HTTPS origin, route, method, or fixed native invocation.
  • A current-account probe and a stable subject identity.
  • Response, target, side-effect, and completion projections.
  • Credential names and the places each credential may be sent.
  • Risk and uncertainty behavior, and what happens when the provider changes.
  • Secret-free fixtures for success and for every relevant rejection or unsettled outcome.

Owner-host permission descriptors must also reject generic dispatch; their catalog presence alone does not prove a runtime can perform the action.

A UI label, route name, or one captured traffic shape is not enough. GhostGet does not treat DOM automation as an execution or recovery fallback.

3. Check, test, pack, and install as separate decisions

ghostget plugin check /absolute/private/example-web --json
ghostget plugin test /absolute/private/example-web --trust-code --json
ghostget plugin pack /absolute/private/example-web \
  --output /absolute/private/example-web.ghostgetplugin --json
ghostget plugin install /absolute/private/example-web.ghostgetplugin \
  --trust-code --json
  1. check parses and validates the package without executing plugin code.
  2. test --trust-code is the first execution boundary. It binds trust to the verified plugin identity and runs declared secret-free fixtures.
  3. pack verifies the fixed file set and produces reproducible, content-addressed package bytes.
  4. install --trust-code records a separate decision to let that exact package run and activates it only after catalog conflict checks.

An update changes package identity and requires a new trust decision. Disable, update, and removal serialize with invocation leases, confirmations, run journals, recovery capsules, and linked-device lifecycles; GhostGet refuses a transition while the old bundle owns live or unknown work.

Portable host capabilities are declared and bounded

  • Exact-origin HTTPS with bounded request and response bodies.
  • Opaque cookie material bound only to its cookie jar and OAuth material bound only to the Authorization header.
  • Content-bound file handles with bounded reads and namespaced JSON state.
  • Bounded diagnostics plus explicit mutation dispatch-begin and verification steps.
  • Declared session-material handles.

The host does not expose a shell, package manager, ambient environment, raw auth locator, unrestricted filesystem, arbitrary redirect, automatic retry, or caller-chosen network primitive. Native code and undeclared module imports are rejected.

This protocol contains ordinary failures but is not a hostile-code sandbox. Plugin code runs with the current account's ambient operating-system authority. Review it before trust and read the security guide for the exact boundary.

Use the public types without triggering runtime state

The package root exports bounded identifier and version validators plus the types used to describe source plugins and portable protocol messages. It is intentionally side-effect-free. Use ghostget plugin check as the authoritative validation of a complete authoring directory and ghostget plugin test --trust-code as the explicit runtime boundary.

The complete source guide lives at docs/plugins.md for v0.19.0. Pinning the tag keeps the prose and protocol tied to the release described here.