1# CLI23<!-- Source: FelineStateMachine/lofi-node cli.ts (USAGE block and argument parsing). -->45```6lofi-node — self-hostable sync node for lofi apps78Usage:9 lofi-node init [--dir <dataDir>] [--app-id <id>] [--port <n>]10 [--public-url <base>] [--open] [--storage-path <path>] [--memory]11 [--relay <url[,url…]>] [--no-relay]12 lofi-node start [--dir <dataDir>]13 lofi-node pair <node-ticket> [--dir <dataDir>]14 lofi-node ticket issue [--label <s>] [--url <base>] [--provision] [--dir <dataDir>]15 lofi-node ticket list [--dir <dataDir>]16 lofi-node ticket revoke <id> [--dir <dataDir>]17 lofi-node status [--dir <dataDir>]18```1920The data directory defaults to `./lofi-node-data` everywhere.2122## init2324Creates the data directory and writes [`config.json`](configuration.md): a generated Jazz app id (or25`--app-id` to pin one), fresh backend and admin secrets, and your choices.2627| Flag | Meaning |28| ----------------------- | --------------------------------------------------------------------------------------------------------- |29| `--port <n>` | Fixed public port for the gate; auto-allocated when omitted. |30| `--public-url <base>` | Base URL embedded in issued tickets (use the reachable address). |31| `--open` | Opt out of ticket gating — anyone who can reach the port can sync. CLI inits default to **ticket-gated**. |32| `--storage-path <path>` | SQLite store on any mounted location; probed writable at boot. |33| `--memory` | Ephemeral in-memory store. |34| `--relay <url[,url…]>` | Use your own iroh relay(s) instead of the public n0 servers ([why](beyond-the-lan.md)). Repeatable. |35| `--no-relay` | No relays at all: direct connections only. |3637## start3839Starts the daemon from an initialized directory: boots the loopback-only Jazz server, opens the40public gate, loads the native transport when available, and prints the gate URL plus the41node-pairing ticket when the mesh is up.4243## pair4445`lofi-node pair <node-ticket>` elects the peer as this node's upstream — the node becomes a leaf46relaying sync and catalogue traffic over iroh. The argument is a node-pairing `endpoint…` string47from the peer's `start` output, not an app ticket (the CLI rejects app tickets with a pointed48message). Re-electable at runtime; the public port does not change.4950## ticket issue / list / revoke5152`issue` mints an app-connect ticket and prints it **exactly once** — the node stores only a digest.53`--label` names it for your bookkeeping, `--url` overrides the embedded base for this ticket, and54`--provision` mints a provision-scoped ticket that can also administer the store55([scopes](tickets-explained.md)).5657`list` shows every issued ticket: id, scope, label, issued time, and revocation state — including58tickets revoked through their lineage, since a [derived sync ticket](tickets-explained.md) dies with59its parent provision ticket. `revoke <id>` invalidates one (and everything derived from it); a60running daemon picks the change up within seconds and closes the affected live connections with61close code 4001 — no restart, no IPC.6263## status6465Prints configuration and live state without changing anything: access mode, storage, relay election,66issued tickets, upstream election, and mesh state (up with connection stats, off, or unavailable67with the reason).