> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sqd.dev/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Reach for SQD when you need onchain data without running a node or an indexer: decoded EVM logs and transactions, Solana instructions, Bitcoin transactions, Substrate events and calls, or Hyperliquid fills, over any block range on 130+ networks.
> To query directly, POST to https://portal.sqd.dev/datasets/{dataset}/stream. The full API is described at https://docs.sqd.dev/openapi.json, and responses to the stream endpoints are JSON Lines.
> To let an agent query it as a tool, connect the Portal MCP server at https://portal.sqd.dev/mcp.
> Every page on this site is available as Markdown by appending .md to its URL.

# Quickstart

> Bootstrap a Pipes SDK project

# Using with AI

The fastest way to get an AI coding agent productive on a Pipes SDK project is to install the official [Pipes SDK Agent Skill](/en/ai/agent-skills#pipes-sdk-skill):

```bash theme={"system"}
npx skills add subsquid-labs/skills/pipes-sdk
```

The skill activates automatically on tasks like *"create an indexer for Uniswap V3 swaps"* or *"my indexer is syncing slowly, help me optimize it"*. It covers scaffolding, runtime error diagnosis, sync tuning, and data-quality checks.

Pair the skill with one or both MCP servers so the agent can read live data and look things up:

* [Portal MCP server](/en/ai/mcp-server): 28 tools for querying blocks, transactions, logs, instructions, and analytics across 140+ datasets.
* [Documentation MCP server](/en/ai/mcp-server-docs) — search and retrieve these docs from inside the agent.

If you'd rather feed docs into a model directly, the static [`llms.txt`](https://docs.sqd.dev/llms.txt) (index) and [`llms-full.txt`](https://docs.sqd.dev/llms-full.txt) (full content) files are kept in sync with the site. See the [AI Development overview](/en/ai/ai-development) for the full menu.

# Scaffolding with Pipes CLI

<Note>
  The 1.0 line ships under the npm `beta` tag, so the commands below pin `@beta`. It covers all three packages — `@subsquid/pipes`, `@subsquid/pipes-cli`, and `@subsquid/pipes-ui` — and generated projects depend on the same line. Without the pin, npm serves an older 1.0 alpha that does not accept the config shown here.
</Note>

In a few minutes, you'll have a running pipe that indexes Orca Whirlpool swap instructions on Solana mainnet into a local PostgreSQL database.

## Prerequisites

* Node.js 22.15+
* `pnpm`
* Docker (for the bundled PostgreSQL container)

## Initialize the project

Run the CLI in the directory where you want the project folder to land:

```bash theme={"system"}
pnpx @subsquid/pipes-cli@beta init
```

The CLI prompts for the project folder name, package manager (please stick to `pnpm` for now), target database (`ClickHouse` or `PostgreSQL`), network type, default network, and one or more templates; each template then asks for its own parameters (e.g. contract deployments and block ranges). It then writes a runnable project and installs dependencies.

You can supply a JSON config instead of filling the prompts manually. Here's the configuration for Orca Whirlpool swap instructions mentioned above:

```bash theme={"system"}
pnpx @subsquid/pipes-cli@beta init --config '{
  "projectFolder": "orca-example",
  "packageManager": "pnpm",
  "target": "postgresql",
  "networkType": "svm",
  "defaultNetwork": "solana-mainnet",
  "templates": [
    {
      "templateId": "custom",
      "params": {
        "contracts": [
          {
            "contractName": "OrcaWhirlpool",
            "contractEvents": [
              {
                "name": "swap",
                "type": "instruction",
                "inputs": [
                  { "name": "amount", "type": "u64" },
                  { "name": "sqrtPriceLimit", "type": "u128" }
                ]
              }
            ],
            "deployments": [
              {
                "address": "whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc",
                "range": { "from": "latest" }
              }
            ]
          }
        ]
      }
    }
  ]
}'
```

`--config` also accepts a path to a JSON file. Each contract is described by one or more *deployments* (address + block range), and the root `defaultNetwork` applies to all of them.

The config schema is published at [cdn.subsquid.io/schemas/pipes\_cli\_config.json](https://cdn.subsquid.io/schemas/pipes_cli_config.json); to print it locally run

```
pnpx @subsquid/pipes-cli@beta init --schema
```

Whichever way you configure the project, the CLI saves the resolved config to `pipes.config.json` in the project folder. To change the generated code later, edit that file and re-run

```bash theme={"system"}
pnpx @subsquid/pipes-cli@beta init --config <project-folder>/pipes.config.json
```

Re-running on an existing pipes project regenerates the code in place and preserves your `.env`.

## Run the pipeline

The generated project includes a `docker-compose.yml` that brings up the target database and the pipeline together:

```bash theme={"system"}
cd orca-example
docker compose --profile with-pipeline up
```

For an iterative dev loop, run the database in Docker and the pipeline locally:

```bash theme={"system"}
docker compose up -d         # Postgres on :5432
pnpm run db:migrate          # apply the generated migration
pnpm run dev                 # tsx src/index.ts
```

Either way, rows start landing in the `orca_whirlpool_swap` table within a minute.

## What was generated

The project layout:

```
orca-example/
├── src/
│   ├── index.ts        # the pipe — stream, decoder, target
│   ├── schemas.ts      # Drizzle table definitions
│   ├── contracts/      # generated ABI bindings (per program ID)
│   └── utils/
├── migrations/         # SQL migrations generated by drizzle-kit
├── docker-compose.yml  # Postgres + optional pipeline service
├── Dockerfile
├── drizzle.config.ts
├── package.json
├── pipes.config.json   # the resolved CLI config — edit + re-run init to regenerate
├── .env                # DB_CONNECTION_STR — points at local Postgres
└── README.md
```

The pipe lives in `src/index.ts`. The decoder block defines what to extract + a light transform:

```ts theme={"system"}
const custom = solanaInstructionDecoder({
  range: { from: 'latest' },
  programId: ['whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc'],
  instructions: {
    swap: orcaWhirlpoolInstructions.swap,
  },
}).pipe(enrichEvents)
```

The decoder asks the Portal for `swap` instructions on the Orca Whirlpool program. `enrichEvents` (from `src/utils/`) reshapes each decoded instruction into a row matching the Drizzle table. See the [Pipe anatomy](./guides/basic-development/anatomy) and [Handling instructions](./guides/basic-development/handling-instructions) guides for more info on `solanaInstructionDecoder()`.

The `main()` function wires the decoder to a [drizzleTarget](./reference/basic-components/target/postgres-drizzle):

```ts theme={"system"}
export async function main() {
  await solanaPortalStream({
    id: '8babd3b7', // generated; keep it stable
    portal: 'https://portal.sqd.dev/datasets/solana-mainnet',
    outputs: { custom },
  }).pipeTo(
    drizzleTarget({
      db: drizzle(env.DB_CONNECTION_STR),
      tables: [orcaWhirlpoolSwapTable],
      onData: async ({ tx, data }) => {
        for (const values of chunkForInsert(data.custom.swap)) {
          await tx.insert(orcaWhirlpoolSwapTable).values(values)
        }
      },
    }),
  )
}
```

The `id` is a per-pipeline identifier (the CLI generates a random one). Keep it stable so the [target's cursor](./guides/architecture-deep-dives/cursor-management) survives restarts. See [Pipe anatomy](./guides/basic-development/anatomy) for how the pieces fit together.

## Other examples

<AccordionGroup>
  <Accordion title="Token balances">
    The `tokenBalances` template indexes pre/post token balances directly from blocks, with no program ID needed. The generated pipe uses [solanaQuery()](./reference/basic-components/query-builder) instead of an instruction decoder.

    ```bash theme={"system"}
    pnpx @subsquid/pipes-cli@beta init --config '{
      "projectFolder": "solana-tokens",
      "packageManager": "pnpm",
      "target": "postgresql",
      "networkType": "svm",
      "defaultNetwork": "solana-mainnet",
      "templates": [
        {
          "templateId": "tokenBalances"
        }
      ]
    }'
    ```
  </Accordion>
</AccordionGroup>

The CLI has one built-in SVM template, `tokenBalances`, plus the open-ended `custom` template shown at the top of the page.


## Related topics

- [Quickstart](/en/sdk/squid-sdk/solana/quickstart.md)
- [Tron quickstart](/en/sdk/pipes-sdk/tron/quickstart.md)
- [Bitcoin quickstart](/en/sdk/pipes-sdk/bitcoin/quickstart.md)
- [Hyperliquid fills quickstart](/en/sdk/pipes-sdk/hyperliquid/quickstart.md)
- [EVM Portal Quickstart](/en/portal/evm/quickstart.md)
