Skip to content
spockIt’s only logical !
Non-normative guide. This page shows how to use Spock; the v0 specification governs where they disagree. Spock is pre-1.0 and interfaces may change β€” see project status.

CLI

The toolchain is one binary named spock. It serves two shapes of work: a framework project β€” a directory composed by a spock.toml manifest β€” and a standalone program β€” one explicit .spock file. Commands that accept a PATH resolve the nearest enclosing project; commands that accept a FILE operate on exactly the file you name.

Invocation

npx spock runs the toolchain without a global install; npm i -g spock makes the bare spock command available. Platform requirements and the distribution model live on the install page.

The version transcript below is the current published package. It includes the strict Uhura 0.4 checker/runtime, Editor, Play, and explicit web-app@1 profile. Releases 0.5.0 through 0.5.3 have the same framework command names but embed the retired client frontend.

Terminal window
$ spock --version
spock 0.5.4

-V is the short form. Every command supports --help.

spock check [PATH]

Prove a target loads, without binding a listener or touching named state. The command is polymorphic on its target.

An explicit .spock path selects the standalone one-file proof β€” the mode is chosen by the path’s shape, so a missing .spock file fails as a standalone target rather than falling back to project discovery. This is a full load proof, not a parse: the contract is compiled, the schema is materialized in an in-memory database, fn bodies and validator checks are executed against it, defaults are proven, and the seed is replayed through the ordinary write path. Everything spock run would reject before serving, check rejects here. The summary counts what the contract declares, including its escape ledger:

$ spock check blog.spock
ok: 2 table(s), 0 record(s), 1 fn(s) (1 unchecked escapes), 2 seed row(s)

No target, or a directory target, resolves the nearest spock.toml β€” walking from the working directory (or the named directory) toward the filesystem root β€” and checks the whole framework project: manifest, backend, client when one is configured, and the links between them that are currently provable.

$ spock check
ok: project `demo` β€” 0 table(s), 0 record(s), 0 fn(s), 0 seed row(s), 2 preview(s), 1 replay-derived preview(s), 1 unchecked link(s), 1 warning(s)
warning: link: application-owned provider adapter code remains unchecked

An explicit spock.toml path selects exactly that manifest’s directory, with no walk.

spock new NAME [β€”backend-only]

Create a new framework project as a child directory of the working directory. The default scaffold is full-stack; --backend-only omits the Uhura client. The full-stack inventory:

demo/
β”œβ”€β”€ spock.toml
β”œβ”€β”€ backend/
β”‚ └── app.spock
└── client/
β”œβ”€β”€ uhura.toml
β”œβ”€β”€ host.toml
β”œβ”€β”€ machine.uhura
β”œβ”€β”€ ui.uhura
└── evidence.uhura

The starter deliberately uses one explicit machine presentation. Larger Web clients may opt into Uhura’s web-app@1 profile in uhura.toml; that profile discovers its conventional page/component/surface tree and generates a checked route table and root application presentation without changing these Spock commands.

new is create-new-only: the destination must not exist, and a conflicting entry fails the whole plan before any write. NAME must be a single safe path component β€” an invalid name fails with, for example:

error: invalid project name `nested/name`: nested paths are not allowed; NAME must be one safe path component

On success the command prints what it created and the next step: next: run spock dev from the project directory above.

spock init [PATH]

Adopt an existing directory as a framework project, in place. Unlike discovery, init never walks to a parent: it inventories exactly the selected directory (the working directory when PATH is omitted), finds the one .spock backend candidate and the one uhura.toml client candidate, and writes a manifest that points at them. Existing sources are never moved or rewritten. Two .spock files is an ambiguity error before any write:

error: SPP015: found multiple Spock backend candidates; choose one explicitly
note: one.spock
note: two.spock

A directory with only an Uhura client gets the required backend added: init creates backend/app.spock with the empty-authority placeholder, because a framework project always has a backend even before the authority is designed. A directory that already contains spock.toml is already adopted, and init refuses.

spock start [PATH] [β€”port 4000] [β€”db FILE]

Check a framework project once, then serve one fixed generation of it. The server binds 127.0.0.1 only β€” the port is local, and the actor seam it exposes is a development surface. --db FILE names a disposable database file; disposable means it is reconstructed from source and seed on every process start, never migrated (seed replay is the only state model).

start and dev refuse an explicit .spock target rather than silently reinterpreting it as a project:

$ spock start blog.spock
error: `blog.spock` selects standalone `.spock` file mode; run `spock run` with that file instead

spock dev [PATH] [β€”port 4000] [β€”db FILE]

Serve a framework project with live client publication. Target resolution, binding, and --db semantics match start; the difference is that dev observes source changes. Its reload semantics are deliberately asymmetric β€” see reload semantics below. At startup it states the policy plainly:

warning: backend inputs (including referenced seed assets) and spock.toml topology changes are observed but not applied; restart `spock dev` to reconstruct backend state from seed

spock run FILE [β€”port 4000] [β€”db FILE]

Compile, materialize, seed, and serve one standalone program. Without --db the database is in-memory; with it, the named file is recreated on every run. The startup line reports the load and the seed replay:

spock v0 β€” contract loaded: 2 table(s), 1 fn(s), 2 seed row(s) replayed
listening on http://127.0.0.1:4000

spock build FILE [-o FILE]

Compile a standalone program to its contract β€” the compiled JSON artifact the runtime serves verbatim at GET /~contract. The JSON goes to stdout, or to the file named by -o/--out.

spock gen

Generate derived artifacts from a standalone program. Both subcommands print to stdout or write to -o/--out.

spock gen types FILE [-o FILE]

TypeScript types: one interface per table row, insert and update shapes, and the error-code unions the contract declares.

spock gen graphql-schema FILE [-o FILE]

The exact GraphQL SDL the runtime serves for this program, for offline schema tooling. Seed data does not gate this artifact β€” the schema is derived from the contract alone.

Reload semantics under dev

spock dev treats the two languages differently, on purpose: client publication is safe to do live, while backend state is disposable by doctrine and must only ever be reconstructed, never patched in place.

  • Valid client saves publish live. Each save is reported as a building and then published revision.

  • Invalid client saves keep the last-known-good Play generation serving while Editor diagnostics report the rejection. When no valid generation has existed yet, /~project/status reports the client as cold_invalid.

  • Backend edits β€” the .spock entry, referenced seed assets, and topology-affecting spock.toml saves β€” are observed but never applied. A running database is never reseeded, migrated, or replaced under a live process. The server reports:

    backend: restart required; active state remains pinned (changed: backend/app.spock)

    Restarting dev reconstructs backend state from seed. The open design for richer development-state reload is RFD 0023.

Diagnostic format

Compile-time diagnostics render as path:line:col: error[CODE]: message, and the codes are stable:

broken.spock:3:9: error[E003]: unknown type `texxt` (not a builtin, not a declared table)
error: 1 diagnostic(s), contract not produced

Project-layer failures β€” manifest, discovery, and scaffold planning β€” carry their own stable SPP codes, rendered as error: SPP015: message with note: lines for detail. The full code tables live in error codes.

Endpoints printed at listen

Framework serving (start and dev) prints its surface at bind time:

EndpointServes
GET / and GET /playUhura Editor and Play, when a client is configured
GET /~studioSpock Studio
GET /~contractthe active contract, as data
GET /~project/statusframework generation status
GET /~healthaggregate readiness
* /rest/v1/*authority REST and RPC
POST /graphql/v1GraphQL, when the contract is non-empty

Standalone run prints the same authority surface plus Studio, and * /storage/v1/object when the program uses storage. The full protocol β€” REST operators, GraphQL binding, the storage plane, and wire statuses β€” is the HTTP API reference.