Skip to content
Back to skills

Voice Test Stack

ASecurity

Bring the full Delta Agents local voice-test stack into a known-good state — kill stale gateway/dashboard listeners, start both from a named checkout/worktree with nohup + readiness polling, start the tunnel (cloudflared or ngrok, auto-picked from GATEWAY_URL), and print the callable state (tunnel URL, gateway health, dashboard URL, webhook URL shapes). Use before any live voice/webhook test against the local gateway, when the user says "spin up the voice test stack", or whenever a Retell/CRM...

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 27, 2026
developmentgobashnodetestingapi

Works with

  • api
  • mcp

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned September 27, 2026

npx -y skills add zalogarcia/zalo-claude-code-setup --skill voice-test-stack --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Voice Test Stack?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Voice Test Stack
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/zalogarcia-voice-test-stack/badge)](https://www.skillsdirectory.com/skills/zalogarcia-voice-test-stack)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: voice-test-stack
description: Bring the full Delta Agents local voice-test stack into a known-good state — kill stale gateway/dashboard listeners, start both from a named checkout/worktree with nohup + readiness polling, start the tunnel (cloudflared or ngrok, auto-picked from GATEWAY_URL), and print the callable state (tunnel URL, gateway health, dashboard URL, webhook URL shapes). Use before any live voice/webhook test against the local gateway, when the user says "spin up the voice test stack", or whenever a Retell/CRM webhook needs to reach localhost. Replaces the hand-assembled kill+build+node+vite+tunnel ritual.
---

Get the Delta Agents voice-test stack — gateway (:3000), dashboard (:5174), tunnel —
killed, restarted, listening, publicly reachable — via one deterministic script. Do not
hand-write the kill+build+nohup+curl+tunnel chain; invoke `voice-test-stack.sh`.

## When to invoke

- Before a live voice call test (Retell webhooks / in-call MCP tools must reach the local gateway)
- Before webhook testing (`POST /hooks/:crm_type/:tenant_slug`) against a local gateway
- After switching branches/worktrees — pass the checkout path to run the stack from it
- When the user says "start the voice test stack" / "get the tunnel up" / "expose the local gateway"

Skip for: prod testing (use `https://api.operatorbase.app` directly), dashboard-only UI
work (use the `dev-server-restart` skill on :5174 alone).

## Invocation

```bash
~/.claude/skills/voice-test-stack/voice-test-stack.sh up   [REPO_DIR] [--tunnel auto|cloudflared|ngrok|none] [--no-build]
~/.claude/skills/voice-test-stack/voice-test-stack.sh down [REPO_DIR]
~/.claude/skills/voice-test-stack/voice-test-stack.sh status
```

**Defaults:** `REPO_DIR=/Users/zalo/dev/delta-agents`, `--tunnel auto`, build ON.

**Examples:**

```bash
# Full stack from main, tunnel auto-picked from GATEWAY_URL in .env
~/.claude/skills/voice-test-stack/voice-test-stack.sh up

# From a worktree, no tunnel (local-only webhook curls)
~/.claude/skills/voice-test-stack/voice-test-stack.sh up /path/to/worktree --tunnel none

# Skip the tsc chain when dist/ is known-fresh
~/.claude/skills/voice-test-stack/voice-test-stack.sh up --no-build

# Tear down everything the script started
~/.claude/skills/voice-test-stack/voice-test-stack.sh down
```

## What the script does (verified against the repo 2026-07-02)

1. Preconditions: `$REPO_DIR/.env` exists; `node_modules` present (fresh worktrees need
   `npm ci` first — known gotcha)
2. Kills anything listening on :3000 and :5174 (`lsof -ti tcp:PORT -sTCP:LISTEN` — by
   port, not process name; same approach as `dev-server-restart`)
3. Builds the tsc chain shared → providers → core → mcp-servers → gateway (mirrors
   `scripts/dev.sh` standard mode), then verifies `apps/gateway/dist/index.js` exists
4. Starts the gateway detached: `node --env-file=.env dist/index.js` (built-JS mode —
   more reliable than `tsx watch`, per `dev.sh`), logs to `/tmp/voice-stack-gateway.log`,
   polls `/health` until 200 (45s cap), then reports `/ready` (sticky pool-warm boot gate)
5. Starts the dashboard detached: `npx vite --port 5174 --strictPort` in
   `apps/dashboard`, polls until responding
6. Starts the tunnel (see below), polls `https://<host>/health` until 200
7. Prints the **callable state block**: branch + checkout, gateway/dashboard/tunnel
   health codes, `GATEWAY_URL` match/mismatch, webhook URL shapes
   (`POST $BASE/hooks/:crm_type/:tenant_slug[/:agent_slug]`,
   `POST $BASE/voice/mcp/:tenantId/:agentId`, retell inbound/post-call), and a pointer to
   `.claude/test-identities.md`

## Tunnel modes

`--tunnel auto` (default) derives the mode from `GATEWAY_URL` in `$REPO_DIR/.env`:

- `*ngrok*` host → **ngrok**: `ngrok http --url=<host> 3000` (static domain
  `wanting-saddlebag-rocklike.ngrok-free.dev`; authtoken already in
  `~/Library/Application Support/ngrok/ngrok.yml` — non-interactive)
- `*blackumbrella.app*` host (or cloudflared config present) → **cloudflared**:
  `cloudflared tunnel run` (named tunnel `4199e388…` → `da-local.blackumbrella.app` →
  `localhost:3000`; credentials already in `~/.cloudflared/` — non-interactive)
- neither → `none` with a warning

**Critical invariant:** Retell-sync builds the in-call MCP/webhook URLs from
`GATEWAY_URL` (`apps/gateway/src/retell-sync/_shared.ts`). The script prints
MATCH/MISMATCH between the running tunnel and `GATEWAY_URL` — on MISMATCH, fix `.env`
and re-sync the voice agents under test, or Retell will call a dead URL mid-call.

## Exit codes

- `0` — gateway + dashboard up (and tunnel 200 if started)
- `1` — gateway failed `/health` within timeout (last 30 log lines on stderr)
- `2` — dashboard failed to respond (last 30 log lines on stderr)
- `3` — gateway+dashboard fine but tunnel never returned 200 (tunnel log tail on stderr)
- `64` — bad arguments

## Output shape

Ends with a `CALLABLE STATE` block. Do NOT paste service logs into the conversation —
the script surfaces the failure region itself. Logs stay at
`/tmp/voice-stack-{gateway,dashboard,tunnel}.log`, PIDs at `/tmp/voice-stack-*.pid`.

## Edge cases

- **Port 3000 held by another project's dev server** — it gets killed (by-port kill is
  the point); mention it to the user if the process wasn't a delta-agents one
- **`/ready` stays 503** — Supabase pooler / Redis not reachable; check
  `.env` `REDIS_URL` (local dev Redis, NOT prod) and `/tmp/voice-stack-gateway.log`
- **Fresh worktree** — script refuses to run without `node_modules`; run `npm ci` first
- **ngrok free plan** — one simultaneous agent session; a session running elsewhere
  (another machine) makes the local one fail — the tunnel log tail shows it
- **Only gateway is tunneled** — the dashboard stays local-only; the tunnel ingress maps
  the public host to `localhost:3000` only
- **wa-bailey (:3002) is NOT started** — voice testing doesn't need WhatsApp; use
  `scripts/dev.sh` if you need the full trio

## Pair with

- `.claude/test-identities.md` (in the repo): admin account, test phone +17867810250
  (admin-owned; any call or text a live test triggers goes to an owner-controlled test number
  like this one, never to a customer or tenant contact), Retell test agents (Ava / zalito uno), dashboard token-mint recipe
- `dev-server-restart` skill — single-port restarts when you don't need the full stack
- `live-test` agent / `live-test-campaign` skill — bring the stack up first, then test

Files in this skill

  • SKILL.md6.4 KB
  • voice-test-stack.sh10.6 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…