> ## 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 120+ 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): 31 tools for querying blocks, transactions, logs, instructions, and analytics across 120+ 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>
  Pipes CLI and Pipes UI publish the 1.0 line under the npm `beta` tag, so the commands below pin `@beta` for those two packages. Without the pin, npm serves an older 1.0 alpha that does not accept the config shown here. `@subsquid/pipes` itself installs the 1.0 line by default, no tag needed.
</Note>

In a few minutes, you'll have a running pipe that indexes USDC token transfers on Ethereum 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 USDC token transfers mentioned above:

```bash theme={"system"}
pnpx @subsquid/pipes-cli@beta init --config '{
  "projectFolder": "usdc-example",
  "packageManager": "pnpm",
  "target": "postgresql",
  "networkType": "evm",
  "defaultNetwork": "ethereum-mainnet",
  "templates": [
    {
      "templateId": "erc20Transfers",
      "params": {
        "deployments": [
          {
            "address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
            "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 usdc-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 `erc20_transfers` table within a minute.

## What was generated

The project layout:

```
usdc-example/
├── src/
│   ├── index.ts        # the pipe — stream, decoder, target
│   ├── schemas.ts      # Drizzle table definitions
│   └── 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 erc20Transfers = evmEventDecoder({
  profiler: { name: 'erc20-transfers' },
  range: { from: 'latest' },
  contracts: ['0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'],
  events: { transfers: commonAbis.erc20.events.Transfer },
}).pipe(({ transfers }) =>
  transfers.map((transfer) => ({
    blockNumber: transfer.block.number,
    txHash: transfer.rawEvent.transactionHash,
    logIndex: transfer.rawEvent.logIndex,
    timestamp: transfer.timestamp.getTime(),
    from: transfer.event.from,
    to: transfer.event.to,
    value: transfer.event.value,
    tokenAddress: transfer.contract,
  })),
)
```

This query-transform combo asks the Portal for ERC-20 `Transfer` logs from the USDC contract, decodes them and (in the `.pipe` step) reshapes each one into a row matching the Drizzle table. See the [Pipe anatomy](./guides/basic-development/anatomy) and [Handling contract events](./guides/basic-development/handling-events) guides for more info on `evmEventDecoder()`.

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

```ts theme={"system"}
export async function main() {
  await evmPortalStream({
    id: '104a2cf1', // generated; keep it stable
    portal: 'https://portal.sqd.dev/datasets/ethereum-mainnet',
    outputs: { erc20Transfers },
  }).pipeTo(
    drizzleTarget({
      db: drizzle(env.DB_CONNECTION_STR),
      tables: [erc20TransfersTable],
      onData: async ({ tx, data }) => {
        for (const values of chunkForInsert(data.erc20Transfers)) {
          await tx.insert(erc20TransfersTable).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="Uniswap V3 swaps via factory">
    Tracks every pool created by the Uniswap V3 factory and indexes its `Swap` events. The generated decoder uses [factory transformers](./guides/advanced-topics/factory-transformers) with a SQLite-backed pool registry.

    ```bash theme={"system"}
    pnpx @subsquid/pipes-cli@beta init --config '{
      "projectFolder": "uniswapv3-swaps",
      "packageManager": "pnpm",
      "target": "postgresql",
      "networkType": "evm",
      "defaultNetwork": "ethereum-mainnet",
      "templates": [
        {
          "templateId": "uniswapV3Swaps",
          "params": {
            "factoryAddress": "0x1f98431c8ad98523631ae4a59f267346ea31f984",
            "range": { "from": "latest" }
          }
        }
      ]
    }'
    ```
  </Accordion>

  <Accordion title="Aave V3 supply / withdraw (custom template)">
    The `custom` template generates ABI bindings and decoder wiring from an event list you provide. Drop in any contract and event set.

    ```bash theme={"system"}
    pnpx @subsquid/pipes-cli@beta init --config '{
      "projectFolder": "aave-supply-withdraw",
      "packageManager": "pnpm",
      "target": "postgresql",
      "networkType": "evm",
      "defaultNetwork": "ethereum-mainnet",
      "templates": [
        {
          "templateId": "custom",
          "params": {
            "contracts": [
              {
                "contractName": "AaveV3Pool",
                "contractEvents": [
                  {
                    "anonymous": false,
                    "inputs": [
                      { "indexed": true, "name": "reserve", "type": "address" },
                      { "indexed": false, "name": "user", "type": "address" },
                      { "indexed": true, "name": "onBehalfOf", "type": "address" },
                      { "indexed": false, "name": "amount", "type": "uint256" },
                      { "indexed": true, "name": "referralCode", "type": "uint16" }
                    ],
                    "name": "Supply",
                    "type": "event"
                  },
                  {
                    "anonymous": false,
                    "inputs": [
                      { "indexed": true, "name": "reserve", "type": "address" },
                      { "indexed": true, "name": "user", "type": "address" },
                      { "indexed": true, "name": "to", "type": "address" },
                      { "indexed": false, "name": "amount", "type": "uint256" }
                    ],
                    "name": "Withdraw",
                    "type": "event"
                  }
                ],
                "deployments": [
                  {
                    "address": "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2",
                    "range": { "from": "latest" }
                  }
                ]
              }
            ]
          }
        }
      ]
    }'
    ```
  </Accordion>
</AccordionGroup>

The CLI has two built-in EVM templates, `erc20Transfers` and `uniswapV3Swaps`, plus the open-ended `custom` template.


## Related topics

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


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.