OPEN SOURCE · MIT

Your own signet.
One call.

Signet Sandbox provisions an isolated Bitcoin chain per team. Bitcoind in signet mode, a custom BIP325 block signer, and the services your application needs. Every call returns a connection bundle. A TTL deletes the environment when time is up.

No sign-up · MIT licensed · Local or self-hosted

Install

01 / CLI

One binary named signet, installed by a shell script. No repository clone.

$ curl -fsSL https://nully0x.github.io/signet-sandbox/install.sh | sh

LINUX · MACOS x86_64 and arm64. Re-run the same line to upgrade.

  • Docker daemon, running: Docker Desktop, colima, or OrbStack
  • Nothing else. You never manage servers or the platform underneath
Read the docs

First environment

02 / FOUR STEPS
  1. 01
    Bootstrap the local stack

    Prepares the local platform, starts the API, and writes a local identity. Pass the host at this step when other machines must reach the endpoints.

    $ signet bootstrap
    $ signet bootstrap --host 192.168.100.2
  2. 02
    Provision

    Waits until the environment is ready. The first run premines 101 blocks. --ui opens the dashboard when ready.

    $ signet up --name my-app --ttl 2h --ui
  3. 03
    Read the bundle

    One object holds every endpoint plus the credentials that open it.

    $ signet get my-app --json
  4. 04
    Fund and tear down

    Fund an address from your wallet, or one the node returns with getnewaddress. Remove the environment and its chain when the work is done.

    $ signet fund my-app tb1qexampleaddress --amount 100000
    $ signet down my-app

01 / THE BUNDLE

Configuration in. Credentials out.

Names resolve on the server, so scripts never track UUIDs. Disabled components are omitted from the object, not returned as null. Lightning entries are keyed by the instance name you chose.

SIGNET / GET MY-APP JSON · JSON-RPC 2.0
{
  "environment_id": "0192f3a1-4c7e-7b2d-9f01-2b6a8d5c1e40",
  "status": "ready",
  "rpc_url": "https://my-app.signet.example/env/0192f3a1/rpc",
  "rpc_auth": "signet:6f1c8a2d4e7b9c03",
  "indexer_endpoint": "tcp://localhost:50001",
  "explorer_url": "https://my-app.signet.example/env/0192f3a1/explorer",
  "faucet_url": "https://my-app.signet.example/env/0192f3a1/faucet",
  "signet_challenge": "512103a4f1e09b…ac",
  "block_policy": "interval_30s",
  "lightning": {
    "ln-alice": {
      "implementation": "lnd",
      "node_id": "02aa55c1f0…7e",
      "node_uri": "02aa55c1f0…7e@localhost:21000",
      "rest_url": "https://localhost:21000",
      "grpc_url": "https://localhost:21001",
      "tls_cert": "2d2d2d2d2d424547494e…",
      "auth": { "type": "macaroon", "value": "0201036c6e64…" }
    }
  },
  "expires_at": "2026-10-29T15:41:00Z"
}
Your endpoints. Your chain. Your credentials.

02 / WHAT AN ENVIRONMENT CONTAINS

Pick the parts you need.

The chain backend always comes up. Everything else is a choice you make at create time, and the choice is recorded in the bundle.

Components, their role, and whether they are always present or optional
Component Role When present
bitcoind Bitcoin Core in signet mode, one chain per environment ALWAYS
block signer BIP325 signer with a per-environment key, 30 second blocks or on demand ALWAYS
electrs Electrum indexer for wallets that track on-chain state OPT-IN
explorer Browser view of blocks, transactions, and addresses OPT-IN
faucet Funds any address with worthless coin from that chain OPT-IN
LND Named Lightning instances, one or many, with REST and gRPC OPT-IN

Lightning instances peer automatically after create. Channels stay manual, because channel liquidity is the thing under test.

03 / WHY THIS EXISTS

Three bad options. One that fits.

01 / REGTEST

Too small

One node. No real peering, no real mempool behaviour, and no sync worth measuring.

02 / PUBLIC TESTNET

Too crowded

Shared with everyone, unreliable under load, and short of coins when you need them.

03 / MAINNET

Too expensive

Real funds and real risk during integration tests. One mistake costs money.

04 / THIS

Private signet

Real proof of work and real chain sync, on a chain that only your key can validate.

04 / ISOLATED BY DEFAULT

One chain.
One challenge.

Every environment gets its own chain and its own signet challenge. Two environments cannot join the same chain, and there is no shared tier to compromise. A per-environment key signs every block. Destroying the environment removes it and everything inside it.

Local mode and hosted mode differ in connection details only, never in what the caller must know. The same configuration file that created a persistent environment works in CI with a TTL appended.

  1. CONFIGURATION One schema, three surfaces

    CLI flags, a JSON file, or a direct RPC call produce the same validated object.

  2. PROVISIONING API JSON-RPC over one route

    NIP-98 signed events or an API token authenticate the caller. Failures are error objects, not HTTP status codes.

  3. PROVISIONING One environment per call

    The platform applies the environment definition. The signer, node, and services start together.

  4. YOUR APPLICATION Connect and test

    The bundle carries endpoints, a macaroon, and the TLS certificate to pin. The reaper removes the rest.

05 / STATUS

What works today.

Stated plainly, because infrastructure claims are easy to make and hard to check.

Project status by area
Area State Detail
Chain and signer SHIPPED Custom signet, BIP325 signer, 30 second or on-demand blocks, 101 block premine
Provisioning SHIPPED JSON-RPC API, isolated environments, connection bundle, stop and start, TTL reaper
Components SHIPPED electrs, explorer, faucet, and named LND instances with REST and gRPC
CLI SHIPPED up, ls, get, fund, stop, start, down, token, schema, with JSON output
Dashboard IN PROGRESS Browser surface for the same API. The CLI is the supported path today.
MCP server SPECIFIED Same tools as the API for agent-driven provisioning. Not built yet.