Skip to content
Automation
Skill

/add-dial

Add Dial channel integration — a real phone number for SMS and AI voice calls via the Dial platform (getdial.ai). Native adapter — no Chat SDK bridge.

From plugin
nanoclaw
31k61 skills
Install
$ npx -y skills add nanocoai/nanoclaw --skill add-dial --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/add-dial

Context preview

The summary Claude sees to decide when to auto-load this skill.

Add Dial channel integration — a real phone number for SMS and AI voice calls via the Dial platform (getdial.ai). Native adapter — no Chat SDK bridge.

SKILL.md

add-dial.SKILL.md
name: add-dial
description: Add Dial channel integration — a real phone number for SMS and AI voice calls via the Dial platform (getdial.ai). Native adapter — no Chat SDK bridge.

Add Dial Channel

Adds [Dial](https://getdial.ai) — a real phone number for **SMS and AI voice calls**. Native adapter (no Chat SDK bridge): both directions go through the `dial` CLI — outbound via `dial message`, inbound via its command-target daemon. NanoClaw doesn't ship channels in trunk — this skill copies the Dial adapter, its pairing helper, and their tests in from the `channels` branch. The `pair-dial` setup step is maintained in trunk, so it is not copied here.

The mechanical steps under **Apply** carry `nc:` directive fences: an agent reads the prose and applies them, and a parser can apply them deterministically from the same document. Every directive is idempotent, so the whole skill is safe to re-run; anything a parser can't apply falls back to the prose beside it.

Apply

1. Copy the adapter, pairing helper, and tests

Fetch the `channels` branch and copy the Dial adapter, its pairing store and user-agent helper (each with its test), and the registration test into place (overwrite — the branch is canonical):

src/channels/dial.ts
src/channels/dial-pairing.ts
src/channels/dial-pairing.test.ts
src/channels/dial-user-agent.ts
src/channels/dial-user-agent.test.ts
src/channels/dial-registration.test.ts
src/channels/dial-grant.test.ts
src/channels/dial-status.test.ts

The `dial-cli` container skill is deliberately **not** copied here. `container/skills/` is mounted read-only into *every* agent container (`src/container-runner.ts`), and a group with `skills:'all'` picks up whatever it finds there — so shipping the skill with the adapter would hand it to agents on installs that never configured Dial. It is installed only by `/add-dial-tool`, offered under *Add phone superpowers* below, which is the skill that actually provisions the CLI the skill documents.

`dial.ts` imports `dial-user-agent.js` at module scope, so omitting that helper breaks the build and every test that loads the channel barrel.

2. Register the adapter

Append the self-registration import to the channel barrel (skipped if present). This one line is the skill's only reach-in into the channel core:

import './dial.js';

3. Register the pairing setup step

Add the `pair-dial` loader to the `STEPS` map in `setup/index.ts`, inside the dormant marker region (skipped if already present — `pair-dial` ships in core, so this idempotent-skips on a normal install, but is expressed for a clean-upstream rebuild). The pairing handshake below spawns this step:

'pair-dial': () => import('./pair-dial.js'),

4. Install the packages

Pinned to exact versions — the supply-chain policy rejects ranges and `latest`. `qrcode` renders the scannable pairing card:

qrcode@1.5.4

The adapter needs no Dial client library: it shells out to the `dial` CLI, which this skill already requires for inbound. `@getdial/sdk` was dropped because it depends on `pubnub`, which pulls react-native, Metro and Hermes into the lockfile for what is a single send — and the CLI ships in lockstep with the Dial API, so a contract change arrives as a CLI release rather than breaking a request pinned in the adapter.

5. Build

Build first: it guards the adapter's typed core calls and proves the dependency is installed.

pnpm run build

6. Validate

Then run the one integration test.

pnpm exec vitest run src/channels/dial-registration.test.ts

`dial-registration.test.ts` imports the real channel barrel and asserts the registry contains `dial` — it goes red if the import line drifts. End-to-end SMS/voice is verified manually once the service runs.

Sign in to Dial

Install the CLI

Dial's CLI owns the account credential (an auth file it writes on sign-in), so the setup uses the `dial` CLI here. Ensure it's installed — this installs it if it's missing (for the full onboarding/auth reference, see the `dial-cli` skill or `curl -fsSL https://getdial.ai/skills.md`):

command -v dial || curl -fsSL https://getdial.ai/install | bash

Identify this install

Calls this setup makes to Dial identify the install. The `dial` CLI prepends `DIAL_USER_AGENT` to its own token, so the account's requests stay attributable to this NanoClaw install in Dial's server-side logs. Resolve the token once (`nanoclaw/<version>`; an unreadable `package.json` degrades to `nanoclaw/unknown` rather than blocking the install) and prefix every `dial` command below with it:

node -p "'nanoclaw/'+(require('./package.json').version||'unknown')" 2>/dev/null || echo nanoclaw/unknown

Pin the CLI path

Now pin the CLI's **absolute** path into `.env`. The adapter shells out to `dial` to register its inbound command target, and it runs inside the NanoClaw service, which does not inherit your interactive shell's `PATH`. The CLI usually lands in a version-manager bin directory (`~/.nvm/versions/node/*/bin`, `~/node/bin`, …) that the service cannot see, so a bare `dial` fails with `ENOENT`, the command target is never registered, and the channel comes up connected but deaf — no inbound SMS or calls, with only a line in `logs/nanoclaw.error.log` to show for it. `DIAL_CLI_PATH` removes the guesswork; `dial.ts` already prefers it:

command -v dial
DIAL_CLI_PATH={{dial_cli_path}}

Check the sign-in

Check whether you're already signed in:

DIAL_USER_AGENT={{dial_ua}} dial doctor --json

Skip the reuse question when signed

Read more
Ships withnanoclaw

A lightweight alternative to OpenClaw that runs in containers for security. Connects to WhatsApp, Telegram, Slack, Discord, Gmail and other messaging apps,, has memory, scheduled jobs, and runs directly on Anthropic's Agents SDK

Get the whole plugin
Stats
30,745
Stars
12,836
Forks
Active
Maintenance
TypeScript
Language
MIT
License
2d ago
Last commit
7mo ago
Created

Repo: nanocoai/nanoclaw

Other skills on nanoclaw.