@openagentsinc/pylon
v1.0.5
Published
Headless, CLI-only Pylon contributor node built on Bun and Effect
Downloads
5,168
Readme
Pylon

Tech stack
Launch Package And Version Truth
Stable v1.0 is cut. apps/pylon/package.json and
apps/pylon/src/version.ts are 1.0.0 (kept in sync; the version-sync test
guards both).
The default published Pylon is now @openagentsinc/[email protected] — the
latest dist-tag. A fresh npx @openagentsinc/pylon installs the Bun/Effect
earning-capable node directly from npm. The old 0.2.5 GitHub-asset launcher
(previously latest) is superseded; it predated the Tassadar earning path and
could no longer resolve a runnable release asset on a clean machine (Launch
L-1, #5393).
The v1.0 stable package is published on the latest dist-tag. The owner
authorized the stable cut on 2026-06-18 (#5393), promoting the rc line
(1.0.0-rc.37, no code change) to 1.0.0. Install with
npm install -g @openagentsinc/pylon or run directly via
npx @openagentsinc/pylon. Verify the live dist-tags with
npm view @openagentsinc/pylon dist-tags. Every future release cut must bump
both package.json and src/version.ts. The publish flow is documented in
docs/npm-publishing-runbook.md.
The npm package and the signed standalone auto-update feed are separate
release surfaces. The 1.0.0 npm publish does NOT update
updates.openagents.com/pylon/.../feed.json; that feed only moves when the
signed binary flow in apps/pylon/scripts/build-rc-binaries.sh and the
oa-updates publish path are run. The npm package ships the Bun/Effect source
that runs directly, so the npm publish alone fixes npx.
Running v1.0 from source (testing only)
git clone https://github.com/OpenAgentsInc/openagents
cd openagents && bun install
bun run --cwd apps/pylon start # equivalently: bun apps/pylon/src/index.tsOwner install pin (source-checkout daily driver, #4858)
For owner dogfood that should track the source checkout rather than any
published artifact (rc included), scripts/owner-install-pin.sh installs a
pylon-dev launcher into ~/.local/bin pinned to this source checkout and
writes an inspectable pin manifest (checkout path, pinned commit, dirty
state, installedAt) to ~/.config/openagents/pylon-pin.json. Re-run the
script after pulling to refresh the recorded commit. This is owner-only
dogfood convenience; it does not satisfy the
pylon.local_claude_agent_bridge.v1 packaged-binary blocker, which requires
the published stable binary (#4859).
Non-readiness warnings — read before running:
- This is a release candidate behind open launch gates. Expect breakage, unannounced behavior changes, and TUI/runtime surfaces that are mid-build.
- Nothing about running the RC creates earning expectations: paid work classes, settlement, and marketplace routing are gated by the product-promise registry exactly as for v0.2, and no v1.0-only feature (TUI dashboard, runtime backends, Nostr credentials) may be described publicly as released until the registry says so.
- Run it only with explicit owner approval, on a machine whose owner understands it is pre-release software with wallet-adjacent surfaces. Wallet operations always end in an explicit confirmation dialog, but the posture is: test with sats you can afford to lose, or with none.
- The local gate (
bun run release:gate) is the bar the RC has to pass; if you run the RC and find a gate the suite misses, that report is more valuable than the testing itself - file it or post it on the Forum.
Initial supported operator platforms are macOS and Linux. No other operator platforms are in scope for the first v1.0 launch path.
Runtime Backends
Pylon now carries the former Probe runtime as @openagentsinc/pylon-runtime.
The public pylon binary bundles that runtime source, keeps the OpenTUI node
dashboard as the default, and routes backend/runtime commands through the same
binary:
pylon runtime backend gemini smoke
pylon backend gemini complete --prompt "Summarize the current task."
pylon backend psionic doctor --json
pylon psionic doctor --json
pylon psionic smoke --json
bun run smoke:psionic-qwen -- --base-url http://127.0.0.1:8080
pylon psionic install --channel rc --manifest-url <release-manifest-url> --yes
pylon psionic models install qwen35-0_8b-q8_0 --manifest-url <model-manifest-url> --yes
pylon apple-fm status
pylon apple-fm tool-stream-demoDashboard (TUI)
Running pylon with no subcommand opens the observational dashboard: an
execution-log feed (left), wallet/telemetry/operator panes (right), a repo/AI
context pane on wide terminals, a composer (bottom), and a one-line key-hint
footer.
- Startup is quiet by default; launch with
--verbose(orPYLON_VERBOSE=1) for full service logs, or pressf2to toggle verbosity at runtime. ctrl+kopens the command palette (fuzzy search over every command),f1shows all keybindings,tabswitches focus between the log feed and the composer, andctrl+cexits cleanly.- Wallet operations (
wallet: send sats,wallet: receive,wallet: admit payout target) run from the palette and always end in an explicit confirmation dialog before any money moves. - Keybindings are user-configurable via
keybinds.jsonin the Pylon home directory:{ "bindings": { "palette.open": "ctrl+p" } }. Keys are command names (seef1); values are@opentui/keymapkey strings. Invalid files are reported and ignored. - The composer submits with
meta+returnand streams the selected local adapter into the feed, running in the current working directory by default (PYLON_CODEX_CWDorPYLON_ACTIVE_REPOcan override it). Codex is the default backend; set"dev": { "defaultAdapter": "claude_agent" }or launch with--adapter claudeto use the local Claude Agent SDK instead. Missing SDK/auth readiness is shown as a typed adapter blocker before any session starts. Claude sessions keep their SDK session id locally so follow-up prompts can resume; only hashed session refs appear in the feed. The default Codex composer mode is local boundedworkspace-write;pylon dev --codex-danger,pylon --codex-danger, or"dev": { "codexExecutionMode": "local_supervised_danger" }explicitly switches the local dashboard composer only to SDKdanger-full-accesswithapprovalPolicy: "never"and labels the feed asCodex DANGER. The Claude backend has the same opt-in shape:pylon --claude-dangeror"dev": { "claudeExecutionMode": "local_supervised_danger" }switches the local composer to SDKpermissionMode: "bypassPermissions"with no tool allowlist and labels the feed asClaude DANGER; the default Claude composer mode stays local bounded (tool allowlist +acceptEdits). Both danger flags are rejected with typed blockers on every public command path. Composer streams persist public-safe per-account usage truth under the Pylon home: local session token/cost totals are recorded for Codex and Claude, and provider rate-limit snapshots are captured when the underlying stream exposes Codex/Clauderate_limits/rateLimitspayloads. Account state is keyed by hashed account refs, never by raw credential paths. Submitted prompts persist across restarts: cycle them withctrl+p/ctrl+n, and an unsent draft is stashed on exit and restored on the next launch. pylon dev doctor --jsonreturns the redacted local context projection for the dashboard/dev loop: active repo provider/name, branch, commit, dirty count, instruction/config digest refs, Codex SDK/CLI/auth readiness, Claude/Fable readiness, the active Codex and Claude execution modes (including the Claude permission posture and danger overlay refs), and backend refs. When local usage observations exist, it includes an optional account usage summary with provider-truth/local-session state only. It never prints raw keys, auth file paths, instruction text, changed filenames, or local absolute paths.pylon context --jsonreturns the same public-safe repo, instruction, current-job, and AI-account/adaptor projection that drives the TUI'sRepo & AI Contextpane, including the optional account usage summary when one has been observed. On wide dashboards it renders beside telemetry; on narrow dashboards usef6or the command palette to open the full context view, andContext: refresh repo & AIto re-probe local state.pylon accounts list --jsonreports configured credential homes by provider, readiness state, and hashed home/account refs without raw paths.pylon accounts usage [--account <ref-or-provider>|--provider <codex|claude_agent>|--all] [--refresh] --jsonreports three labeled truth tiers: provider truth (last observed rate-limit snapshot and age/staleness), local session truth (last token/cost totals), and platform truth (currently unavailable unless the future provider-pool proxy is reachable).--account codex,--account chatgpt,--provider codex, and--provider claudetarget the matching unnamed default provider home; registered account refs still target their configured homes.--refreshis explicit because it runs one minimal bounded inference per selected account and may consume paid provider tokens.- Public activity evidence is available without a local node:
pylon activity --json [--since CURSOR] [--filter work,verify,settle],pylon timeline --from <iso> --to <iso> --json,pylon replay --from <iso> --to <iso> [--run <trainingRunRef>] [--window <windowRef>] [--pair <actorA:actorB>] [--format text|json],pylon receipts --run <trainingRunRef> --json, andpylon evidence-pack --run <trainingRunRef> --json. These commands read the documented public OpenAgents APIs only, return dereferenceable source/blocker refs, and are observation-only: they do not spend, settle, deploy, claim work, mutate provider state, or expose local wallet/node status. Use--base-urlorPYLON_OPENAGENTS_BASE_URLto target another public API. pylon dev check --json,pylon dev apply --json, andpylon dev reload --jsonprovide the local supervised check/apply/reload loop.checkemits changed file refs, dirty-state counts, command refs, exit codes, and output digest refs; pass--allow-dirtywhen you intentionally want to inspect an untracked dirty tree. The same actions are exposed in the command palette as Dev commands. They never commit, push, clean, or switch branches.- The sidebar renders a live 3D network view (
@opentui/threeon a native WebGPU device, quantized to terminal glyphs): satellites orbit the market core, wallet status drives color and speed, new feed activity pulses nodes, and a balance increase fires a bitcoin-orange burst. It soft-fails to a placeholder without a GPU, hides on terminals under 32 rows, andPYLON_DISABLE_3D=1turns it off. - Views:
f3dashboard,f4assignments (poll/accept work leases - accept always confirms first),f5wallet (status, readiness, session balance history),f6repo and AI context. All views are also reachable from the palette.
Headless node and attach
pylon noderuns node-core headless: all services, durable feed log, and a loopback control API (default port 4716,PYLON_CONTROL_PORTto change) authenticated by the bearer token in<pylon-home>/control-token.- On a Linux VM, use
scripts/install-cloud-node.shplusdocs/cloud-node-deployment.mdto install the headless node as a systemd service. SetPYLON_ASSIGNMENT_WORKER=1to continuously pick up eligible no-spend owner assignments while the VM stays online. pylon attach [url]opens the dashboard as a client of a running node: it restores the node's scrollback from the connection snapshot, follows live events over SSE (reconnecting with 1s-30s backoff), and routes wallet commands through the node's control API after the usual confirm dialogs. Detaching (ctrl+c) never interrupts the node.- The interactive
pylondashboard also serves the control API, so a second terminal can attach to it. - The same loopback bearer-token control API exposes local session
orchestration for external tools:
session.spawn,session.list,session.events, andsession.cancelon/command, plus per-session SSE at/sessions/<sessionRef>/events. Spawned sessions use bounded Codex/Claude composer execution only, reject local danger modes, accept per-session account/workspace selectors, and retain path-safe artifacts under the Pylon home.
TUI test harness
src/tui/harness.tsx mounts the real dashboard headlessly (no TTY) via
@opentui/solid's testRender: inject keys programmatically, capture
character frames, snapshot them with bun:test, and drive the real
runtime/bridge with fake PylonEvent streams. See
tests/tui-render-harness.test.ts; the harness is importable by the
runtime package's renderer tests as well.
Bootstrap And Status
pylon bootstrap --json
pylon bootstrap --register-openagents --setup-mdk-wallet --pylon-ref <ref> --display-name <name> --resource-mode background_20 --capability-ref <ref> --json
pylon status --json
pylon context --json
pylon accounts list --json
pylon accounts usage --json
pylon accounts usage --account codex --json
pylon accounts usage --provider codex --refresh --json
pylon accounts usage --all --refresh --jsonbootstrap creates the local v1.0 home/cache/release layout and writes a
minimal public-safe config summary. Live registration and MDK mutation are
tracked by later launch gates.
status --json loads or creates the local identity/runtime state and emits a
redacted public-safe projection for headless diagnostics.
Presence commands are available for fake-server and later live endpoint integration:
pylon presence register --base-url https://openagents.com
pylon presence heartbeat --base-url https://openagents.com
pylon presence link-complete --base-url https://openagents.com
pylon presence link-refresh --base-url https://openagents.comWallet readiness commands expose the primary Spark agent wallet without exposing wallet secrets:
pylon wallet status
pylon wallet backup-receive --kind lightning-address
pylon wallet send --rail spark --payment-request <bolt11-or-spark-request> --amount 21 --confirm-send
pylon wallet admit-payout-target --kind bolt12_offer --ref payout.bolt12.<hash>Wallet status reports one agent-facing balance, sourced from the deterministic
Spark wallet derived from the Pylon identity mnemonic. MDK is auxiliary for
treasury/checkouts and legacy compatibility; it is excluded from the displayed
agent balance and public readiness refs. The older wallet receive and MDK
control receive paths remain legacy compatibility until the MDK scope-down issue
removes MDK from the agent receive path.
Spark funds have an explicit spend rail for owner-approved local withdrawals.
Fund movement still requires --confirm-send, and raw payment material stays
local to the node:
pylon wallet send --rail spark --payment-request <bolt11-or-spark-request> --amount 2100 --confirm-send
pylon wallet send --rail spark --lightning-address <[email protected]> --amount 2100 --confirm-sendThe command pays from the node's Spark wallet, not from MDK. Public output and local ledger records contain only digest refs, amount/fee, method, and status; they never print the raw invoice, Lightning Address, mnemonic, API key, or Spark storage path.
Assignment worker commands are available for signed fake-server and live API smokes:
pylon work submit "fix a public failing test" --commit <40-char-sha> --adapter codex --repo OpenAgentsInc/openagents --verify "bun test"
pylon work status <autopilot-work-order-ref> --events
pylon work review <autopilot-work-order-ref> --action request_changes
pylon assignment poll --base-url https://openagents.com
pylon assignment run-no-spend --base-url https://openagents.compylon work submit is the network Autopilot work-order lane. It requires a
real pinned commit, rejects placeholder or unresolvable commits before
submission, and accepts --adapter codex|claude_agent|fable to carry explicit
runner intent into assignment synthesis. Fable is currently a Claude Agent
profile request, not a separate adapter.
run-no-spend polls for a no-spend lease, applies local admission gates,
accepts idempotently, submits progress with artifact/proof refs, and closes the
assignment with settlementState: not_applicable and
payoutClaimAllowed: false. Paid leases are blocked unless wallet send
readiness is explicitly proven.
Local multi-session proof runs
For owner-directed local orchestration, scripts/multi-session-run.ts runs a
bounded JSON plan across multiple Codex/Claude composer sessions. Each entry
selects exactly one workspace (repoRef or worktreePath) and may select an
account by accountRef from dev.accounts in the Pylon config or by a direct
credential home. The runner launches dev-proof-run.ts for each session and
retains per-session proof/failure artifacts, heartbeats.jsonl, and a
path-safe multi-session-summary.json.
{
"sessions": [
{
"id": "codex-a",
"adapter": "codex",
"accountRef": "codex-a",
"worktreePath": "../task-worktrees/codex-a",
"objective": "Fix the focused failing test and keep edits scoped.",
"verify": ["bun", "test", "apps/pylon/tests/multi-session-run.test.ts"]
}
]
}bun apps/pylon/scripts/multi-session-run.ts \
--plan multi-session-plan.json \
--proofs-dir .pylon-proofs/multi-session \
--pylon-home .pylon \
--concurrency 2NIP-90 Provider Loop
GO ONLINE for the NIP-90 provider lane is persisted through the provider command:
pylon provider go-online
pylon provider approve-labor --approved-by-ref operator.public.<ref> --job-type code_task
pylon provider once
pylon provider go-offline
bun run smoke:nip90-providergo-online marks the local runtime online, adds
capability.public.pylon.nip90.text_inference.v0.3 and
capability.public.pylon.labor.local_agent.v0.3, and records the relay and
admission policy that the OpenTUI background loop will use. Labor jobs require
an explicit first-run operator approval record from provider approve-labor
before they execute on a machine. provider once is the headless smoke path
for one relay loop iteration; the default dashboard starts the same loop
automatically only when the persisted lifecycle is online or
assignment-ready.
The provider loop subscribes to the scoped OpenAgents market relay by default,
publishes NIP-89 handler info, admits public kind 5050 text-inference
requests and OpenAgents labor kinds 5934 code task, 5935 review, and
5936 document work, then publishes NIP-90 7000 feedback plus result kinds
6050 or 6934-6936. Text inference executes the local Apple FM runtime.
Labor jobs execute through the contributor's configured local agent path
(codex, opencode, or claude) inside a bounded workspace and return
public-safe artifact refs. It uses the shared @openagentsinc/nip90 package,
which re-exports the local nostr-effect protocol helpers.
Environment controls:
PYLON_NIP90_RELAYS: comma-separated relay URLs; defaults towss://relay.openagents.com.PYLON_NIP90_PRICE_MSATS: price floor and requested invoice amount; defaults to1000.PYLON_NIP90_REQUEST_TTL_SECONDS: request age limit; defaults to one year.PYLON_NIP90_MAX_INFLIGHT: total local inflight admission leases; defaults to1.PYLON_NIP90_PER_BUYER_MAX_INFLIGHT: per-buyer inflight leases; defaults to1.PYLON_LABOR_AGENT: optional local labor agent selector:codex,opencode, orclaude_code. If unset, Pylon detectscodex, thenopencode, thenclaude.PYLON_LABOR_AGENT_COMMAND: optional explicit local command prefix for advanced operators. Pylon appends the generated public-safe labor prompt.
Wallet boundary: the loop may put a raw BOLT 11 invoice into Nostr relay
events because NIP-90 payment-required/result tags require it, but local state,
ledger records, OpenAgents API payloads, logs, and issue evidence must only
carry public-safe receipt refs, amounts, event ids, and readiness refs. See
docs/nip90-provider-loop.md.
Legacy Spark/Breez migration boundary: pylon wallet migrate-spark is a
preflight-first compatibility path for old v0.2.x balances. It reports missing
Breez/Spark credential material as an actionable blocker and only proceeds with
explicit local consent. pylon wallet send --rail spark --confirm-send is the
direct Spark spend/withdraw path for credited Spark wallet funds; it is separate
from accepted-work payout authority and emits public-safe refs only. Users must
never paste a 12-word mnemonic, raw invoice, Lightning Address, API key, or Spark
storage path into GitHub, support threads, logs, or issue comments. See
docs/legacy-spark-wallet-migration.md.
Labor boundary: Pylon rejects labor requests that carry provider-auth-shaped
material, requests outside the bounded workspace, or a policy ref other than
provider.compliant_usage_labor.v1. The contributor's own local provider
accounts or API budgets stay on the contributor machine; OpenAgents pays for
accepted work output only and never resells, proxies, brokers, or transfers
provider credentials, sessions, account access, or consumer subscription
capacity.
The runtime includes:
- Apple Foundation Models bridge support, readiness receipts, streaming tool callbacks, and Program Run evidence.
- Gemini direct API and OpenAgents product surface-brokered Gemini materialization.
- Psionic OpenAI-compatible
/v1/chat/completionsclient with text, tool-call loop, streaming delta tool-call parsing, max round-trip guard, and redacted transcript/tool-call receipts. - Psionic Qwen3.5 model-row admission gates for
0.8Band2B: rows are advertised only after a retained artifact digest or public-safe manifest ref, and coding-agent selection prefers 2B when both rows are ready. - Optional Psionic binary/model installer scaffold with explicit
--yesconsent, macOS/Linux machine checks, release/model manifest verification, SHA-256 verification, and digest-addressed cache placement. This is never part of startup or default package installation. - Psionic training-boundary contracts for signed training release manifests,
digest-verified artifacts, healthy sidecar lifecycle projection, and signed
worker receipt import.
supportsTrainingremains false until that complete boundary is real. Seedocs/psionic-training-boundary.md. - Provider-neutral LLM message/request/tool/usage contracts.
- Blueprint signature lookup, tool-menu planning, Action Submission boundaries, and contribution release gates.
- Retained OpenTUI Markdown rendering helpers and markdown/code streaming fixtures.
- GEPA/Terminal-Bench candidate execution, closeout bundles, token telemetry, runner identity, and OpenAgents product surface grant/account contracts.
- Psionic Qwen3.5 attach-only backend discovery and doctor support with
PYLON_PSIONIC_BASE_URL/PROBE_PSIONIC_BASE_URL, 0.8B and 2B model-row refs, assignment-runner admission, typed unattached refusal, and redacted availability/transcript/tool-call receipts. Seedocs/2026-06-09-pylon-qwen35-local-inference-roadmap.mdanddocs/psionic-qwen-live-smoke.md; this is not a training, bundled-model, startup auto-download, or paid-capacity claim.
GEPA Capability Envelope
src/gepa-capability.ts maps v0.3 assignment leases onto the in-repo benchmark
runtime contracts. The rc envelope is GEPA-first: retained Terminal-Bench
fixtures, Probe runtime backend refs, artifact upload refs, proof/receipt refs,
assignment closeout refs, local sandbox isolation, wall-clock/cost budgets, and
capacity fields are modeled separately from payout readiness.
This does not advertise neural training or Qwen work. Those tracks remain postponed until the GEPA lease, closeout, import, and payment-mode gates are solid.
Host Inventory
pylon inventory --jsonstatus --json and the dashboard include the same host inventory projection:
supported platform, CPU/memory/disk counts, network counts, accelerator class,
backend health refs, model-cache state, and blocker refs. The projection does
not expose interface names, cache paths, env dumps, provider auth, private
topology, or raw local model paths.
Host inventory now includes an optional Psionic Qwen3.5 row. qwen3.5:0.8b
is the lowest-footprint smoke/fallback row and qwen3.5:2b is the first
coding-agent tool-loop quality row. Machines that cannot or do not want to run
local ML keep working with precise Psionic blocker refs and no binary/model
download.
Operator Snapshot
pylon operator snapshot --jsonThe default dashboard includes bounded operate, wallet, inspect, and recovery state. The headless snapshot is for support and service-manager runs: it shows refs, blockers, readiness, and recovery gates without exposing raw wallet material, provider tokens, private repo content, or local cache paths.
Release Gate
bun run release:gateThe local release gate runs tests, JSON smokes, dashboard startup smoke, package
dry-run, and local package install smoke. Public copy must stay inside the
allowed claim matrix in docs/launch-gates-no-overclaim.md.
