Skip to main content

Crate kindling_runtime

Crate kindling_runtime 

Source
Expand description

kindling-runtime — the anvil-first integration facade.

One Cargo dependency that bundles daemon startup, client wiring, and durable emit for Rust downstreams (chiefly anvil) that want one binary and daemon semantics without a separate kindling install.

The runtime composes the existing crates — it does not fork their wire shapes:

kindling stays mechanism, not policy: the runtime owns process lifecycle and client wiring; it does not encode anvil governance.

§Quickstart

use kindling_runtime::{Runtime, RuntimeConfig};
use kindling_runtime::types::{ObservationInput, ObservationKind, ScopeIds};

// Embedded daemon (default), durable spooled emit, default ~/.kindling home.
let runtime = Runtime::start(RuntimeConfig::embedded("/path/to/my/project")).await?;

// Durable append: reaches the daemon, or buffers to the spool on outage.
let input = ObservationInput {
    id: None,
    kind: ObservationKind::Message,
    content: "gate evaluated: pass".to_string(),
    provenance: None,
    ts: None,
    scope_ids: ScopeIds::default(),
    redacted: None,
};
runtime
    .spooled_client()
    .append_observation(input, None, None)
    .await
    .expect("durable append");

runtime.shutdown().await?;

§Attach-or-start

Runtime::start never pre-emptively starts a daemon. It builds a client for the configured socket; the client only spawns when the socket does not answer. So if a daemon (the CLI, a Claude Code hook, or another runtime) is already listening on the same socket, the runtime attaches to it and the embedded spawner is not invoked.

This “attach, don’t spawn” guarantee holds for the sequential case: a daemon that is already bound when start runs is attached to. It is not a cross-process lock. If two cold-starts race on the same socket (neither daemon bound yet), both embedded spawners can briefly fire; the second serve then fails to bind the already-taken socket and its task exits cleanly, leaving exactly one daemon. For v1 anvil (a single binary owning its socket) this window does not arise, so the runtime deliberately ships no socket lock — see the design spec’s “socket lock file” note.

Re-exports§

pub use kindling_types as types;

Structs§

Capsule
Bounded unit of meaning grouping related observations.
Client
A thin async client for the kindling daemon.
ClientConfig
Configuration for a Client.
FlushReport
Result of SpooledClient::flush.
Observation
Atomic, immutable record of an event captured during development.
ObservationInput
Input for creating a new observation. Optional fields are auto-generated.
Pin
Pinned reference to an observation or summary.
RetrieveOptions
Options for a retrieval request.
RetrieveResult
Complete retrieval result: pins, optional current summary, ranked candidates, provenance.
Runtime
A composed kindling integration: a client (and durable-emit spooled client) over a daemon the runtime either started in-process or attached to.
RuntimeConfig
Configuration for a Runtime.
ScopeIds
Scope identifiers for multi-dimensional isolation.
SpooledClient
A durable-emit wrapper around a crate::Client.

Enums§

AppendOutcome
Outcome of SpooledClient::append_observation.
CapsuleStatus
Capsule lifecycle status.
CapsuleType
Types of capsules.
ClientError
Errors returned by Client operations.
ObservationKind
Types of observations that can be captured.
RuntimeError
Errors from Runtime operations.
SpawnStrategy
How the runtime obtains a running daemon when the socket is not answering.
Spawner
How the client starts the daemon when it is not already running.
SpoolError
Errors from SpooledClient operations.
Transport
Which transport the client uses to reach the daemon.

Type Aliases§

Id
Unique identifier for entities. Implementation uses UUIDv4 format.