CLI
Deploy subgraphs and webhooks hosted or on your own box, and run the instance, from one terminal.
The binary is secondlayer. sl is a short alias.
Command map
Every top-level secondlayer command, with the page that owns it.
| Command | What it does | Docs |
|---|---|---|
init | Write the instance token and keys to .env.local | Local runtime |
bootstrap | Restore chain history from a verified archive | Local runtime |
observer | Print the node's events_observer stanza | Self-host |
login / logout | Sign in through your browser; logout signs the machine out (--email for an emailed code, --with-token to read a key from stdin) | Keys and billing |
whoami | Show the instance and account targets | Keys and billing |
subgraphs | Create, deploy, query, reindex, and backfill subgraphs | Subgraphs |
webhooks | Create, test, pause, replay, and inspect webhook deliveries | Webhooks |
streams | Read raw chain events, tips, reorgs, and bulk dumps (--chain bitcoin for Runes events) | Streams |
index | Query decoded events, transfers, contract calls, blocks, and Runes (index runes) | Index |
codegen | Generate typed contract clients, prints, and ORM schemas | below |
devnet | Run Secondlayer against a local Clarinet devnet | Local chain |
status | Local instance health | Local runtime |
doctor | Diagnose the full stack | Self-host |
config | Read and write CLI configuration | secondlayer config --help |
context | Print an orientation snapshot of tips, subgraphs, webhooks, and operations | MCP and skills |
verify | Compare local data to a signed archive; prove one block; replay a subgraph | Verify |
repair | Replace local data that diverges from a signed archive | Verified archive |
archive | Price, fetch, verify, and repair against the hosted archive | Verified archive |
credits | Buy, check, and auto-refill your credits | Keys and billing |
backup | Write a restorable bundle of the index and keys | Self-host |
restore | Restore an instance from a backup bundle | Self-host |
uninstall | Stop the stack; the index and keys survive | Self-host |
--api-keyshape-routes hex toINSTANCE_TOKENandsk-sl_*toSECONDLAYER_API_KEY.- Instance commands refuse
api.secondlayer.tools, exceptsecondlayer subgraphsandsecondlayer webhooks, which takeSECONDLAYER_API_KEYagainst the hosted URL (hosted subgraphs). - Credentials: Keys and billing and Instance token.
loginprints a code and opens your browser; approve it and the CLI is signed in untillogout. It never makes an API key; keys are for reading data and live under Keys.login --emailasks for an emailed code instead.
Webhook triggers
webhooks createtakes--trigger/--triggers-file.- SDK and REST accept the same
triggersarray (Triggers).
Local runtime
Write keys, restore history, print the observer stanza.
| Command | Flag | Default | Notes |
|---|---|---|---|
secondlayer init | --network | STACKS_NETWORK or mainnet | mainnet, testnet, or devnet |
--api-url | the local API, port 3800 | Local API | |
--force | off | Overwrite generated values in .env.local | |
secondlayer status | --json | off | Local instance health from /public/status |
secondlayer bootstrap | --against | required | Manifest URL or file |
--to-block | archive tip | Stop early | |
--from-block | genesis | Forward-only: start here, history below is out of scope | |
--verify | all | Post-load digests: all or blocks | |
--public-key | resolved | Pin the signing key | |
-y, --yes | off | Skip confirm | |
--json | off | Machine output | |
secondlayer observer | --mode | indexer | indexer retries; signer-shared does not |
--endpoint | indexer:3700 (loopback :3700 on devnet) | host:port only, no URL | |
--network | STACKS_NETWORK or mainnet | Loopback refused except devnet |
secondlayer bootstraprefuses a non-empty database. Fix an existing instance withsecondlayer repair.- Exit
0restored,1diverged,2refused.
secondlayer verify has three forms:
secondlayer verify [target]compares local data to a signed archive. Target isallorraw(default); the archive has no digests fordecode:<name>orsubgraph:<name>yet.--quickis identity,--deepis semantic,--anchorrequires a verified signature. Flags live on Verified archive.secondlayer verify block <height|index_block_hash>proves one Stacks block from the checkpoint built into the CLI, trusting nothing else. Flags--node,--checkpoint,--rows,--json; exit0proven,1a link is broken,2could not check. Links and output: Verify.secondlayer verify subgraph <name> --replayrecomputes astatesubgraph from proven blocks and compares the served rows.--from/--tonarrow the range. See Check rows.
Signer-shared nodes skip retries
A block the node fails to deliver stays a gap. secondlayer repair fetches it from the archive with credits. The full stanza: Connect your node.
Infers each print topic's payload from indexed history; see print schemas. Anonymous. --table-per-topic emits one table per topic.
secondlayer codegen prints <file>emits a.d.tsnext to the definition.- Incompatible with
--target/--models-only/--env. - Deploy
warningson unobservedevent.datafields are advisory.
Commit your definition before deploying
secondlayer subgraphs deploy checks the source file is committed. An uncommitted deploy leaves the only copy in the database.
- A terminal prompts. Scripts and CI fail.
--allow-uncommittedoverrides and logs the skip.- Outside a git repo, and
--dry-run, skip the check.
Turn Clarity contracts into typed TypeScript: local .clar files, deployed contracts, or a Clarinet project.
Deployed contract ids fetch the ABI (address prefix picks the network). Config-driven projects regenerate with secondlayer codegen contracts:
clarinet: trueloads real ABIs from your Clarinet project via Simnet, including typed clients for[project.requirements]dependency contracts (includeRequirements: falseto opt out).- It skips silently when
Clarinet.tomlis missing.
The output:
- Named aliases per function (
TokenTransferArgs) plus aTypedAbiconst. - Feed it to
getContractfrom@secondlayer/stacks. - Clarinet tests use the simnet transport.
Run the full Secondlayer stack (Postgres, indexer, API, subgraph processor) against your local Clarinet devnet. No cloud, no accounts, no key to read your data.
Coming from Chainhook?
This is the local path; map your predicates over with the Chainhook migration prompt.
Connect
From inside your Clarinet project:
Start the devnet
Start the devnet; it auto-deploys your contracts and streams every block to the indexer.
Prerequisites
- Clarinet and a Clarinet project (a directory with
Clarinet.toml). - Docker (Docker Desktop or OrbStack on macOS).
- The CLI:
bun add -g @secondlayer/cli.
What connect does
- Patches
settings/Devnet.tomlso the devnet node forwards events to the local indexer (stacks_node_events_observers = ["host.docker.internal:3700"]). - Writes
.secondlayer/docker-compose.ymlfor the published OSS images. - Brings the stack up with
docker compose up -d.
Options
| Flag | Default | Purpose |
|---|---|---|
--project <dir> | nearest Clarinet.toml | Clarinet project directory |
--image-tag <tag> | latest | Published image tag to run |
--owner <owner> | Secondlayer namespace | ghcr image owner to pull from |
--no-up | — | Patch config + write compose without starting Docker |
Patch config without starting Docker
Pass --no-up to write settings/Devnet.toml and the compose file without starting containers.
Bring it up yourself with docker compose -f .secondlayer/docker-compose.yml up -d.
Deploy a subgraph against it
Point the CLI at the local API. There is no login: a deploy is a write, and the generated stack ships a fixed local token, dev-instance-token, for exactly that:
It is a local-dev value, not a secret; a real instance gets its own from secondlayer init.
Fire a contract call in your devnet and the matching rows land in your subgraph's tables. Reading them back takes no credential: the compose publishes the API on loopback only, and /v1 reads are keyless whenever the API is reachable from this box alone.
See Instance token.
Watch it work
Add -w to refresh every 2s, or --limit <n> to change how many recent rows show.
Tail logs for the whole stack or one service:
- Services:
indexer,api,subgraph-processor,postgres.
Tear down
These work but get no further investment.
secondlayer codegen subgraph --target prisma|drizzle|kysely: typed ORM schema. See Subgraphs.