Router and safety reference for Solana bot and app projects created with `slv bot init`. This skill is template-agnostic — it covers the generic operations that apply to every template. Template-specific guides (trade-app, geyser-ts, shreds-rust, …) live in dedicated `slv-bot-*` skills loaded alongside this one.
Installs into .claude/skills of the current project.
Are you the author of Slv App?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/validatorsdao-slv-app)
# SLV App Skill
Router and safety reference for Solana bot and app projects created with
`slv bot init`. This skill is template-agnostic — it covers the generic
operations that apply to every template. Template-specific guides
(trade-app, geyser-ts, shreds-rust, …) live in dedicated `slv-bot-*`
skills loaded alongside this one.
## Available Template Types
| `-t <type>` | Skill | Description |
|---|---|---|
| `trade-app` | `slv-bot-trade-app` | Rust PumpSwap auto-trading bot with buy/sell/close lifecycle |
| `geyser-ts` | (future) | Real-time Solana data streaming via gRPC Geyser (TypeScript) |
| `geyser-rust` | (future) | Real-time Solana data streaming via gRPC Geyser (Rust) |
| `shreds-ts` | (future) | Low-level shred stream template (TypeScript) |
| `shreds-rust` | (future) | Low-level shred stream template (Rust) |
| `shreds-udp-rust` | (future) | UDP-based shred stream template (Rust) |
When the user picks a template, consult the matching sub-skill for its
step-by-step guide, env var reference, and template-specific REST API or
daemon behavior. This document provides the common layer those sub-skills
build on top of.
## `slv bot` CLI Commands
`slv b` is an alias for `slv bot`.
| CLI | Action |
|---|---|
| `slv bot init -t <template> -n <name>` | Scaffold a bot/app project in `~/slv/<name>/` from the named template |
| `slv bot build [-n <name>] [-p <path>]` | Rust templates only (`trade-app`, `shreds-rust`, `geyser-rust`, `shreds-udp-rust`). Runs `cargo build --release` locally. On Linux, also installs an idempotent systemd unit (`slv-<name>.service`) pointing `ExecStart` at the built binary; existing units are kept untouched. On macOS / non-Linux the systemd step is skipped |
| `slv bot deploy [-l\|--localhost] [-n <name>]` | Build + push to a VPS via SSH and install a systemd unit there. `-l` deploys to the current host instead (no SSH) |
| `slv bot list` | List registered bots |
| `slv bot start`, `slv bot stop`, `slv bot restart`, `slv bot status`, `slv bot log` | Lifecycle control. `log` accepts `-l/--lines <n>` (default 100) |
### Lifecycle backend (auto-selected)
`start` / `stop` / `restart` / `status` / `log` dispatch to the right backend based on where the bot lives, so the same command works everywhere:
| Bot location | Host OS | Backend |
|---|---|---|
| Remote (`deploy`) | Linux | `ssh … sudo systemctl …` / `journalctl` |
| Local (`deploy -l` or `build`) | Linux | Local `sudo systemctl …` / `journalctl` |
| Local (`build`) | macOS / non-Linux | `nohup` + PID file under `~/.slv/bot/runtime/<name>.{pid,log}`; `stop` sends SIGTERM, waits ~5 s, escalates to SIGKILL |
### Typical flows
- **Dev on macOS (Rust template)**: `slv bot init` → `slv bot build -n <name>` → `slv bot start -n <name>` (runs under `nohup`; see logs in `~/.slv/bot/runtime/<name>.log`). For TypeScript templates (`geyser-ts`, `shreds-ts`), skip `slv bot build` and run `pnpm dev` / the template's own script directly
- **Prod on a VPS**: `slv bot init` → `slv bot deploy -n <name>` (SCP + systemd, `sudo` required on remote)
- **Single-host Linux**: `slv bot init` → `slv bot deploy -l -n <name>` (no SSH; installs systemd locally)
Bot config (`~/.slv/bot/<name>.yml`) is written by both `build` and `deploy`. Once registered, every lifecycle command works with just `-n <name>`.
> **When invoking from `slv c` (non-interactive `run_command`)**: `slv bot build` requires `-n <name> -p <path>` explicitly. Without them the command fails fast with a usage hint (it no longer hangs on prompt) — but the build still won't proceed until you pass the flags.
### Passwordless sudo for `slv c` (dev VPS only)
The systemd install step in `slv bot build` / `slv bot deploy -l` needs `sudo`, but `slv c`'s `run_command` has no TTY to type a password into. On a **dedicated single-user development VPS** (not shared / not production), `slv onboard` offers a one-time install of `/etc/sudoers.d/slv-<user>` containing:
```
<user> ALL=(ALL) NOPASSWD: ALL
```
After that, every sudo call from inside `slv c` works without prompting. Remove later with `sudo rm /etc/sudoers.d/slv-<user>`.
Only accept this prompt on machines you fully own. Do NOT enable on shared hosts, staging, or production — the rule grants unrestricted passwordless sudo to your user.
**AI note:** never run `sudo -v` or `sudo -n -v` as a pre-check before invoking `slv bot build` / `slv bot deploy -l`. `sudo -n -v` returns false even when NOPASSWD is configured (it refreshes the credential timestamp, a separate operation from running commands), so the check is misleading. `slv bot build` already probes with `sudo -n true` internally and returns a clean `needs_sudo` state when it can't proceed — just invoke the build directly and surface its output.
### `slv bot init` safety notes
- `-y` forces `rm -rf` on the target directory before extracting the
template. **Never pass `-y` when `wallet.json` exists** in the target —
the private key will be destroyed. The CLI has a built-in
`~/.slv/wallet-rescue/` layer that persists `wallet.json`, `.env`, and
`*.bak.*` snapshots outside the bot dir before the atomic swap, but the
safest path is to never trigger the rescue in the first place.
- Templates are fetched from
`https://github.com/ValidatorsDAO/solana-stream`. No network at init time
→ template source must already be cached locally.
## Wallet safety at a glance
`wallet.json` in any `~/slv/<app>/` directory is a Solana secret key. Treat
it like a seed phrase. The full preflight rules live in `AGENT.md` — the
short version:
1. Never delete `wallet.json` or `wallet.json.bak.*`.
2. Never run `slv bot init -y` when `wallet.json` exists.
3. Always snapshot `wallet.json` before any action that could touch the
app directory.
## ERPC Cloud — Endpoint & Storage Provisioning
When users don't have a gRPC or Shredstream endpoint, direct them to
https://dashboard.erpc.global to browse plans and complete a purchase or
IP registration — those actions aren't available from `slv c`. Once a plan
is active, check its live status with `call_mcp`.
### Status checks (read-only, via `call_mcp`)
| Tool name | Purpose |
|-----------|---------|
| `get_grpc_status` | Shared gRPC status (registered IP + endpoint) |
| `get_shreds_shared_status` | Shared Shredstream status |
| `get_dedicated_status` | Dedicated gRPC/Shredstream status |
| `get_geyser_grpc_status` | Dedicated Geyser gRPC status (after purchase) |
| `get_shreds_dedicated_status` | Dedicated Shredstream status (after purchase) |
| `get_storage_usage` | Current storage usage |
### Flow
1. Check `get_grpc_status` — if a slot is already active, use its endpoint.
2. Otherwise send the user to https://dashboard.erpc.global to purchase a
plan and register their IPv4 (`curl -4 -s ifconfig.me`).
3. For higher performance: point the user at the dedicated plans on the
dashboard, then verify with `get_geyser_grpc_status` /
`get_shreds_dedicated_status`.
### Important: Backup storage
Trade history and position data need persistent storage. Without backup,
data is lost on restart or crash. Check `get_storage_usage` and point the
user to https://dashboard.erpc.global for backup storage plans.
## Operator Notes
- `wallet.json` contains a private key — never commit it.
- Keep examples OSS-safe: placeholders only, never real tokens or private
endpoints.
- After local testing succeeds, recommend `slv bot deploy` to deploy to a
VPS.
- If the user lacks gRPC/Shredstream endpoints, direct them to
https://dashboard.erpc.global to show products and purchase links.