> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.getdial.ai/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.getdial.ai/_mcp/server.

# CLI command target

> Run a local executable per Dial event — the daemon passes the event JSON as the final positional argument.

A **CLI command target** is the simplest way to hook a local script into Dial. You register an executable with the listen daemon and, for every account event, the daemon spawns that executable with the event JSON as its **final positional argument**. No HTTP server, no signature header — just a process you'd normally run from a shell.

## When to use it

* Quick automations that already live in a script you'd otherwise call by hand.
* Glue work where the agent or service you're notifying doesn't expose a webhook listener.
* One-shot side effects: write to a file, kick a build, ring a bell.

If the receiver already speaks HTTP, prefer a [Local URL target](/integrations/methods/local-url-target) — it scales better and lets the receiver run as a long-lived process.

## Prerequisites

```bash
dial listen install
```

The listen daemon owns the fan-out queue and is what actually spawns your executable. See [Listen service](/documentation/cli/listen-service).

## Register

```bash
dial local-target add cmd /usr/local/bin/handle-dial-event
```

For each event, the daemon invokes:

```
/usr/local/bin/handle-dial-event '<event_json>'
```

You can attach extra arguments — anything after the path is forwarded verbatim *before* the JSON argument:

```bash
dial local-target add cmd /usr/local/bin/handle-dial-event --log-level info --label dial
```

Per-event invocation:

```
/usr/local/bin/handle-dial-event --log-level info --label dial '<event_json>'
```

See [`dial local-target add cmd`](/documentation/cli/commands#local-target-add-cmd) for the full reference.

## Example handler

The most useful thing a CLI target can do is **wake a fresh Claude Code session** with the event as the prompt. The handler shapes the event JSON into a prompt, spawns Claude Code detached in the background, and exits immediately — so the daemon sees a fast `0` and the agent does the heavy lifting on its own time.

```bash
#!/usr/bin/env bash
# /usr/local/bin/handle-dial-event
event="$1"

type=$(jq -r '.type'        <<<"$event")
from=$(jq -r '.from // ""'  <<<"$event")
body=$(jq -r '.body // ""'  <<<"$event")

prompt=$(cat <<EOF
A Dial event just arrived. Decide what to do and act on it.

  type: $type
  from: $from
  body: $body

raw event JSON:
$event
EOF
)

# Detach a fresh Claude Code session and return right away.
nohup claude -p "$prompt" </dev/null >>~/.dial/agent.log 2>&1 &
disown
exit 0
```

The `nohup … & disown` pattern is what makes this safe inside a `cmd` target: the spawned `claude` keeps running after the handler exits, so even a multi-minute agent run never bumps into the daemon's per-attempt `--timeout`.

Make it executable, then register it:

```bash
chmod +x /usr/local/bin/handle-dial-event
dial local-target add cmd /usr/local/bin/handle-dial-event
```

## Delivery semantics

* **Exit code `0`** — treated as delivered.
* **Non-zero exit, or a timeout** — the daemon retries the invocation **once**. If the retry also fails, the event is logged and dropped; nothing is queued for later.
* **Timeout** — `--timeout <seconds>` per attempt, defaulting to `5`.
* **Stdout / stderr** — captured into the listen log so you can see what the executable printed.
* **Environment** — each invocation runs with a clean environment except for `PATH` and `HOME`. Anything else your handler needs must be looked up from inside the handler (or wrapped in a shell script that sets it).
* **Concurrency** — invocations of the same target run independently; the daemon doesn't serialize them, so make your handler safe to run twice in close succession (the once-retry can produce that).

## Verify, list, remove

```bash
dial local-target list
# url  http://127.0.0.1:8787/dial-events
# cmd  /usr/local/bin/handle-dial-event

dial local-target remove /usr/local/bin/handle-dial-event
```

No daemon restart is required for any of these — the fan-out registry updates on the fly.