Packages
P2P runtime API
One symmetric library for any app to host and consume permissioned services.
Verified 16 October 2026
Alpha.2 source candidate
This reference describes @unstoppable-stack/p2p 0.6.0-alpha.2 source. Alpha.1 is published; the new /rpc and /db APIs need source or an alpha.2 candidate tarball until publication. Published Personal Node 0.4.0 uses a different API.
Every app can be a node and a client at the same time. createNode owns stable identity, discovery, pairing, grants, capability calls, streaming and shutdown. A Personal Node is optional; two apps can pair and call each other directly.
Connect and serve
- createNode({ storage, profile, capabilities, pairing, limits, reconnect }): configure identity persistence, app-defined handlers, trust and resource bounds.
- ready() initializes the runtime; listen() accepts connections by public key. listen({ topic }) additionally announces a discovery topic.
- pair(inviteCode, { requested }) redeems a scoped invite. connect(publicKey, { requested, reconnect }) dials a selected peer. discover({ topic }) finds a host; the default topic is machine-local.
- joinNetwork(id, { grants, requested, approve }) discovers multiple app instances; leaveNetwork(id) leaves discovery. A guessable network name is not authorization.
- close() cancels work and tears down peers, transport and packs. Local application data must remain usable while peers are offline.
Define a service
import { createNode } from '@unstoppable-stack/p2p'
const host = createNode({
storage: './.echo-host',
capabilities: [{
name: 'echo', version: 1, defaultGrants: [],
methods: { say: async ({ text }) => ({ text: String(text).slice(0, 200) }) }
}]
})
await host.listen()
const invite = await host.createInvite({ grants: { echo: ['say'] }, uses: 1 })
// Share invite.code with the intended peer.
const client = createNode({ storage: './.echo-client' })
try {
const peer = await client.pair(invite.code)
console.log(await peer.call('echo', 'say', { text: 'Hello' }))
} finally {
await client.close()
await host.close()
}A capability pack has a name, version, methods, optional defaultGrants and lifecycle hooks. Unary handlers are async functions; streaming handlers are async generators. Handlers receive params and { peer, appId, grants, signal }. Validate domain parameters and use the authenticated peer key for ownership.
Calls, streams and permissions
- await peer.call(capability, method, params, { timeout, signal }) returns a unary result. for await over peer.stream(capability, method, params, { signal }) consumes incremental output.
- peer.api is built from advertised methods. Await a handle for unary output or iterate it for streaming. Dotted method names use brackets, such as peer.api.sync['manifest.replace'](...).
- Each direction has independent grants. Incoming direct pairing is denied without approval; scoped invitations authorize only their methods. Reconnects cannot exceed persisted grant ceilings.
- setPeerGrants changes access; unpair persists a denial. Grant removal, disconnect and cancellation abort work. Handlers must honor signal; in-process code cannot be forcibly terminated.
- createInvite, listInvites and revokeInvite manage codes. issueInvite writes an invite from a separate process without starting another node on the daemon's identity.
Limits and operational behavior
Defaults bound control peers (128), JSON frames (256 KiB), incoming requests (8 per peer / 64 per node), host request time (120 seconds), stream output (1 MiB) and consumer buffers (64 chunks / 1 MiB). Handle NodeError codes such as NOT_GRANTED, RESOURCE_LIMIT, REQUEST_TIMEOUT and CANCELLED. Local events expose pairing, disconnect and reconnect state; they are not a remote event subscription service.
The root has no QVAC or wallet dependency and does not load replication. The /sync entry adds replication, though npm installs its storage dependencies with the package. Keep networking in the app worker. Mobile validation, complete restore and managed availability remain separate concerns.
Typed RPC
Validated procedures, inferred clients and normal async return values.
Read moreReplication API
Manifests, protection states and caller-scoped storage.
Read moreDatabase prototype
Experimental collaborative writer logs and app-owned views.
Read moreCapability roadmap
Which cloud-like services exist and which remain planned.
Read more