Your app needs Stacks data that no public API has — your contract, your schema, your uptime. Today that means writing an indexer.
Secondlayer is the runtime instead: decoded chain data in your own database, backfilled from genesis, reorg-safe, kept current. Get tables and a REST API out of the box, or stream rows into your own schema — Postgres, SQLite, or anything you already run — and serve them however you already serve things.
The instance itself is Postgres plus one container, on your hardware.
See STRATEGY.md.
curl "http://127.0.0.1:3800/v1/index/events?event_type=ft_transfer&limit=5"bun add -g @secondlayer/cli
secondlayer init --network mainnet
cd docker/oss && docker compose up -d
secondlayer observer --mode indexer --endpoint secondlayer:3700
secondlayer bootstrap --against <manifest>
secondlayer verify all --against <manifest>
# Index a contract into a typed, queryable Postgres table
export SL_API_URL=http://127.0.0.1:3800
secondlayer subgraphs scaffold SP1234ABCD.my-contract -o subgraphs/my-contract.ts
secondlayer subgraphs deploy subgraphs/my-contract.ts --start-block <recent-block>
secondlayer subgraphs query my-contract <table> --sort _block_height --order descA chain subscription fires on raw events with no subgraph:
secondlayer subscriptions create amm-swaps \
--url https://my-app.com/webhook \
--trigger '{"type":"contract_call","contractId":"SP....amm","functionName":"swap-*"}'Docs → self-host · CLI → packages/cli/README.md.
SDK default is http://127.0.0.1:3800 (or SL_API_URL).
import { SecondLayer } from "@secondlayer/sdk";
const sl = new SecondLayer();
const { rows, next_cursor, tip } = await sl.subgraphs.rows("my-contract", "<table>", {
order: "desc",
limit: 25,
});curl "http://127.0.0.1:3800/v1/subgraphs/my-contract/<table>?_limit=25"Pages are _id-keyset: pass ?cursor=<next_cursor> to resume, _order=asc|desc
for direction.
MCP — bunx -p @secondlayer/mcp secondlayer-mcp (default local API).
Set SL_API_KEY to the INSTANCE_TOKEN from secondlayer init for writes.
enable writes (deploy/manage). See MCP README.
Two TypeScript SDKs, one chooser: @secondlayer/sdk talks to this instance
(query subgraphs, manage webhooks); @secondlayer/stacks is low-level
chain primitives (Clarity decoding, reads). Most apps only need sdk.
| Package | Description |
|---|---|
@secondlayer/cli |
secondlayer binary — init, bootstrap, verify, deploy |
@secondlayer/sdk |
TypeScript SDK — Streams, Index, subgraphs, webhooks |
@secondlayer/mcp |
MCP server — instance tools for agents |
@secondlayer/stacks |
viem-style Stacks client — public/wallet, BNS |
@secondlayer/subgraphs |
defineSubgraph() — schema, triggers, handlers |
@secondlayer/shared |
Shared db, schemas, crypto helpers |
@secondlayer/api |
REST API for the instance |
git clone https://github.com/ryanwaits/secondlayer
cd secondlayer/docker/oss
secondlayer init --network mainnet
docker compose up -dbun install && bun run build && bun run testReleases flow through Changesets:
bun run version to bump, bun run release to publish.
MIT