s2 apply reads a JSON spec file and ensures the declared basins and streams exist with the specified configuration. Resources that already exist are reconfigured to match the spec, and only the fields present in the spec are updated.
Spec file format
The spec is a JSON file with a top-levelbasins array. Each basin entry has a name, an optional config, and an optional streams array.
IDE setup
Add the$schema key to your spec file to point to the published schema hosted on GitHub to enable inline validation and autocomplete in your editor:
.vscode/settings.json so $schema is not needed in every file:
fileMatch to match your spec files by naming convention.
IntelliJ / JetBrains IDEs — add a schema mapping in the IDE settings:
- Open Settings (
Ctrl+Alt+S/⌘,) → Languages & Frameworks → Schemas and DTDs → JSON Schema Mappings - Click + to add a new mapping
- Give the mapping a name (e.g.
S2 Spec) - Set the schema to
https://raw.githubusercontent.com/s2-streamstore/s2/main/cli/schema.json(or a local path) - Set the Schema version to JSON Schema version 7
- Add file patterns to associate (e.g.
*.s2spec.json)
Basin config fields
| Field | Type | Description |
|---|---|---|
default_stream_config | object | Default stream configuration applied to newly created streams |
create_stream_on_append | boolean | Auto-create a stream on first append using the default config |
create_stream_on_read | boolean | Auto-create a stream on first read using the default config |
Stream config fields
| Field | Type | Description |
|---|---|---|
storage_class | "express" | "standard" | Storage class for recent writes |
retention_policy | "infinite" | humantime string | How long records are retained (e.g. "7days", "1week") |
timestamping | object | Timestamping behavior (see below) |
delete_on_empty | object | Delete the stream automatically when empty |
Timestamping
| Field | Values | Description |
|---|---|---|
mode | "client-prefer" | "client-require" | "arrival" | How record timestamps are resolved |
uncapped | boolean | Allow client timestamps to exceed the server arrival time |
Delete-on-empty
min_age to a humantime duration (e.g. "1day", "2h 30m") to enable automatic deletion of empty streams once they reach that age. The default of "0s" disables delete-on-empty.
Dry run
Preview what would change without making any mutations:| Symbol | Meaning |
|---|---|
+ | Will be created |
~ | Will be reconfigured (shows field-level diffs) |
= | Already matches spec, no change |
Flags
| Flag | Description |
|---|---|
-f, --file | Path to the JSON spec file (required unless --schema is used) |
--dry-run | Preview changes without making any mutations |
--schema | Print the JSON Schema for the spec format to stdout |

