Getting started

Pulse runs as one process: collector, Solana firehose, JSON API and dashboard on a single port. Everything has a default, so a fresh clone works with no accounts and no keys.

Requirements#

Run from source#

This is the path in the repository README.

git clone https://github.com/nirholas/pulse.git
cd pulse
npm install
cp .env.example .env       # optional, everything has a default
npm run build              # builds the dashboard into dist/web
npm start                  # collector + firehose + API + dashboard on http://localhost:8787

Open http://localhost:8787. The dashboard fills in after the first collection cycle finishes. Until then the overview shows an empty state and the status pill reads "last cycle pending".

Run from npm#

The pulse-trenches package ships two commands: pulse (the app) and pulse-mcp (the MCP server). Because the package has two bins, tell npx which package to take them from with -p.

npx -y -p pulse-trenches pulse            # start everything (same as: pulse start)
npx -y -p pulse-trenches pulse --help     # list subcommands

Subcommands of pulse:

CommandWhat it does
pulse startCollector, firehose, API and dashboard. The default when no subcommand is given.
pulse collectRun one collection cycle and exit. Add --jobs to also import wallet labels and score wallets.
pulse reportBuild the daily newsletter. Flags: --day YYYY-MM-DD, --no-send, --print.
pulse migrateApply database migrations and exit.
pulse mcpStart the MCP server over stdio. Set PULSE_URL to the API.

Confirm it is working#

The health route reports which database engine is in use, when the last collection cycle finished, and the live firehose state.

curl -s http://localhost:8787/api/health
{"ok":true,"db":"pglite","lastCycle":"2026-10-09T16:02:44.530Z","stream":null,"prices":{"solUsd":110.30668154929297,"ethUsd":2507.195}}

The response above came from a real run started with --no-stream, which is why stream is null. With the firehose on, it holds connection state and rolling counters. Then ask for the top tokens by volume:

curl -s "http://localhost:8787/api/tokens?limit=3&sort=volume"

Day-to-day commands#

CommandWhat it does
npm run devCollector and Vite dev server with hot reload (http://localhost:5173, API on 8787).
npm run collectOne collection cycle, then exit (-- --jobs also imports wallets and scores them).
npm run report -- --no-send --printBuild today's newsletter without sending it.
npm run db:upStart TimescaleDB with Docker Compose on host port 5544.
npm run db:migrateApply migrations and exit.
npm test, npm run typecheckTests and types.

Switch to Postgres or TimescaleDB#

npm run db:up              # Postgres on host port 5544
echo 'DATABASE_URL=postgres://pulse:pulse@localhost:5544/pulse' >> .env
npm start

Any Postgres works. On a TimescaleDB server Pulse converts the time-series tables to compressed hypertables automatically. See Data model and Deployment.

Next steps#