@secondlayer/cli
June 12, 2026 · View on GitHub
The Secondlayer CLI — one binary for Stacks indexing, real-time subgraphs, subscriptions, and Clarity code generation.
bun add -g @secondlayer/cli
sl --version
Auth
Two ways to authenticate:
- Interactive (
sl login) — magic-link email → 6-digit code → session written to~/.secondlayer/session.json. Used for day-to-day CLI work. - Machine / CI — set
SL_API_KEYto an API key created in the platform console at https://secondlayer.tools/platform/api-keys. Keys are prefixedsk-sl_. For a persisted headless login:echo "$SL_API_KEY" | sl login --with-token.
# interactive
sl login
# machine / CI
export SL_API_KEY=sk-sl_xxxxxxxx
sl whoami shows the active account, the effective API URL, and the credential
source (and exits non-zero when not logged in). The global --api-key /
--api-url flags (and SL_API_KEY / SL_API_URL) apply to every command.
During open beta, reads are public (no key needed) — for subgraphs that means
public subgraphs only (managed deploys default public; BYO deploys and all
pre-existing subgraphs are private, readable with your key). Writes — deploying,
publishing, or managing subgraphs and subscriptions — require a session or an
sk-sl_ key.
Quickstart
bun add -g @secondlayer/cli
sl login
sl projects create my-app
sl projects use my-app
# scaffold + deploy a subgraph from a deployed contract
sl subgraphs scaffold SP1234ABCD.my-contract -o subgraphs/my-contract.ts
sl subgraphs deploy subgraphs/my-contract.ts --start-block <recent-block>
sl subgraphs query my-contract <table> --sort _block_height --order desc
# wire a webhook receiver
sl subscriptions create my-hook \
--runtime node \
--subgraph my-contract \
--table <table> \
--url https://<receiver-host>/webhook
sl subgraphs scaffold writes the definition file, creates/updates
package.json, and runs bun install (pass --no-install to skip).
Commands
Auth & project
| Command | What it does |
|---|---|
sl login / sl logout | Start or revoke a session |
sl whoami | Print account, credential source, and active project |
sl keys create --product streams [--name <name>] | Mint a scoped streams/index read key; prints the sk-sl_ key once. Needs an account key in SL_API_KEY |
sl projects create [name] | Create a project |
sl projects list | List projects |
sl projects use <slug> | Bind cwd to a project (writes ./.secondlayer/project) |
sl projects get | Show resolved project + source file |
sl projects delete <slug> (alias rm) | Delete a project (-y to skip confirm) |
Project binding is per-directory: .secondlayer/project in cwd takes
precedence over ~/.secondlayer/config.json:defaultProject. The walk-up stops
at .git.
Key products: an account key (dashboard default) grants both streams:read
and index:read and is the only key that can mint; streams/index keys are
scoped reads and cannot mint (403). Minted keys inherit your plan's tier.
Subgraphs
| Command | What it does |
|---|---|
sl subgraphs create <name> | Scaffold a definition file |
sl subgraphs scaffold <SP...::contract> [-o <path>] [--no-install] | Generate a subgraph from a deployed contract |
sl subgraphs deploy <file> [--start-block <n>] [--visibility public|private] | Deploy; --start-block overrides the definition. Managed deploys default public, BYO default private |
sl subgraphs publish <name> / unpublish <name> | Flip visibility; publish claims the global public name (409 PUBLIC_NAME_TAKEN if claimed) |
sl subgraphs dev <file> | Watch + hot-redeploy |
sl subgraphs query <name> <table> | Query a table with filters, sort, pagination |
sl subgraphs list / status <name> / gaps <name> | Inspect deployments |
sl subgraphs spec <nameOrFile> [--format openapi|agent|markdown] | Export API docs for a deployed subgraph or a local definition file |
sl subgraphs deploy <file> --database-url <url> | BYO: write the subgraph's rows to your own Postgres |
sl subgraphs codegen <file> --target prisma|drizzle [-o <path>] | Generate an ORM schema for the subgraph's tables (BYO DB) |
sl subgraphs client <name> -o <path> | Generate a typed query client for a deployed subgraph |
sl subgraphs reindex/backfill/cancel/delete <name> | Manage processing |
Data products (reads)
| Command | What it does |
|---|---|
sl index ft-transfers / nft-transfers / events --event-type <t> / contract-calls | Decoded Index layer. Anonymous reads OK; free-tier keys rejected (Build+ for keyed) |
sl streams tip / events / consume / reorgs / canonical <h> / pull | Raw chain event firehose. Requires SL_API_KEY |
Reads emit JSON to stdout (--json accepted across all read commands); -o/--output is a file path, not a format.
Subscriptions
| Command | What it does |
|---|---|
sl subscriptions create <name> --runtime <inngest|trigger|cloudflare|node> [--auth-token <token>] [--filter key=value] | Scaffold a receiver wired to a new subscription |
sl subscriptions list / get <id|name> | List or show config + delivery state |
sl subscriptions update <id|name> --url <url> [--filter key.gte=value] | Patch URL, filter, format, retry, etc. |
sl subscriptions pause/resume <id|name> | Stop or restart delivery |
sl subscriptions rotate-secret <id|name> | Rotate signing secret (printed once) |
sl subscriptions deliveries/dead <id|name> | Recent attempts / dead-letter rows |
sl subscriptions requeue <id|name> <outboxId> | Requeue one dead-letter row |
sl subscriptions replay <id|name> --from-block <n> --to-block <n> | Enqueue a historical block range |
sl subscriptions doctor/test <id|name> | Health check / signed fixture |
Read/action commands support --json. Destructive commands prompt unless
-y / --yes. Filters are schema-aware: unknown tables/columns, bad operators,
and non-scalar columns are rejected before the API call.
Subscriptions are polymorphic — subgraph (fires on a subgraph table's rows)
or chain (fires on raw chain events with no subgraph). sl subscriptions create makes subgraph subscriptions only (via the --subgraph/--table
flags). Create chain subscriptions — a webhook on a contract / event / function /
trait — via the SDK, REST, or MCP with a triggers array. Every other
sl subscriptions command (list/get/update/pause/resume/delete/doctor/test/
deliveries/...) operates on both kinds.
Other
| Command | What it does |
|---|---|
sl contracts generate [files...] (alias gen) | Generate TS interfaces from Clarity contracts |
sl context | Print a headless orientation snapshot — account, Streams + Index tips, your subgraphs, subscriptions, and in-flight reindex operations. CLI counterpart to the MCP secondlayer://context resource |
sl init | Scaffold secondlayer.config.ts |
sl doctor / sl status | Reachability + health checks |
sl account get / sl account update | Show or update display name / bio / slug |
sl account billing | Show plan, subscription, trial, discounts |
sl config get/set/reset/delete | Inspect or reset local config |
Environment variables
| Var | Purpose |
|---|---|
SL_API_KEY | An sk-sl_ API key (or session token) for machine/CI use; bypasses platform resolution |
SL_API_URL | Point at an OSS or internal API directly, bypassing the platform |
SL_PLATFORM_API_URL | Override the platform API base (default https://api.secondlayer.tools) |
STACKS_NETWORK | Default network (also via --network <local|testnet|mainnet>) |
HIRO_API_KEY | Used by sl contracts generate for remote contract fetches |
Code generation (sl contracts generate)
Generate type-safe interfaces, functions, and optional React hooks from Clarity
contracts — local .clar files, deployed contracts (network inferred from
address prefix), or globs.
sl contracts generate ./contracts/token.clar -o ./src/generated.ts
sl contracts generate SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.alex-vault -o ./src/generated.ts
sl contracts generate "./contracts/*.clar" -o ./src/generated.ts
Config-driven:
sl init # creates secondlayer.config.ts
sl contracts generate # regenerates from the config
// secondlayer.config.ts
import { defineConfig } from "@secondlayer/cli"
import { clarinet, actions, react } from "@secondlayer/cli/plugins"
export default defineConfig({
out: "src/generated.ts",
plugins: [clarinet(), actions(), react()],
})
| Plugin | What it adds |
|---|---|
clarinet() | Parse local Clarinet project |
actions() | read.* + write.* helpers per contract |
react() | Typed React Query hooks |
testing() | Clarinet SDK test helpers |
import { token } from "./generated/contracts"
// Works with @stacks/transactions directly:
await makeContractCall({
...token.transfer({ amount: 100n, recipient: "SP..." }),
network: "mainnet",
})
// With actions() — read/write helpers + maps/vars/constants:
const balance = await token.read.getBalance({ account: "SP..." })
await token.write.transfer({ amount: 100n, recipient: "SP..." })
const supply = await token.vars.totalSupply.get()
Frozen commands
Local-dev periphery: still functional, hidden from sl --help, no further
investment — may be removed in a future major. The hosted dev loop
(sl subgraphs create/deploy) is the supported path.
sl local up/down/start/stop/restart/status/logs— local stack + dev servicessl local node ...— local Stacks node managementsl local db ...— local source DB inspectionsl devnet connect/down/status/logs— Clarinet devnet integration
Docs
Full reference: https://secondlayer.tools/docs
License
MIT