> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nanoclaw.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# The ncl admin CLI

> Administer a running NanoClaw host from the terminal — inspect and modify groups, wirings, users, sessions, and approvals over the ncl Unix socket.

`ncl` is the admin CLI for a running NanoClaw host. It sends one request frame over a Unix socket at `data/ncl.sock` and prints the response — every command reads or mutates the host's central database live, no restart needed. The socket is `chmod 0600`, so only the user that started the host can connect.

Don't confuse it with the [CLI channel](/channels/cli), which is a chat adapter for talking *to an agent* from the terminal — `ncl` is for operating the host itself.

This page is the working tour. The [ncl CLI reference](/reference/ncl-cli) has every operation, flag, and enum for all twelve resources — including the operator-only [`policies`](/reference/ncl-cli#policies) gate for agent-to-agent messages.

## Invoking ncl

Setup symlinks `bin/ncl` into `~/.local/bin`, so after install you can run `ncl` from anywhere. From the project root, `pnpm ncl` works too:

```bash theme={null}
ncl groups list
pnpm ncl groups list   # equivalent, from the checkout
```

The general shape is:

```bash theme={null}
ncl <resource> <verb> [target] [--key value ...] [--json]
```

Positional words join into the command name. A trailing positional becomes the target ID only if the ID contains no dashes — the dispatcher trims a single dash-segment, so `ncl groups get abc123` works, but a real NanoClaw ID (a UUID, four hyphens) does not resolve. In practice, always pass `--id <uuid>`. Flags map to columns; hyphens and underscores are interchangeable (`--agent-group-id` = `--agent_group_id`). Run `ncl help` to list every resource, and `ncl <resource> help` for its verbs, columns, and enums.

## Output and errors

By default `ncl` prints a human format: a small aligned table for list results, pretty-printed JSON for single objects, and `error (<code>): <message>` on failure. Pass `--json` to get the raw response frame instead — use that for scripting. Exit codes: `0` success, `1` command error, `2` transport error.

If the host isn't running, `ncl` can't reach the socket and tells you so:

```text theme={null}
ncl: cannot reach NanoClaw host (connect ENOENT .../data/ncl.sock).
Is the host running? Start it with: pnpm run dev
Or, if installed as a service:
  macOS:  launchctl kickstart -k gui/$(id -u)/com.nanoclaw-v2-<slug>
  Linux:  systemctl --user restart nanoclaw-v2-<slug>
```

## Agents can run ncl too

The same command surface is exposed to agents inside containers. What an agent may do is controlled per group by `cli_scope` in its container config:

* **`disabled`** — all `ncl` commands are rejected.
* **`group`** (default) — the agent only sees the `groups`, `sessions`, `destinations`, and `members` resources, pinned to its own group: IDs are auto-filled, rows from other groups are filtered out, and it cannot change its own `cli_scope`.
* **`global`** — full access to every resource.

Regardless of scope, mutating verbs (`create`, `update`, `delete`, `grant`, `restart`, ...) are approval-gated for agents: the agent gets `approval-pending` and an admin receives a card showing the exact command. From the host socket, the same verbs run immediately — the socket file permissions are the auth boundary. Change the scope with:

```bash theme={null}
ncl groups config update --id <group-id> --cli-scope disabled
```

## Working with resources

Representative commands per resource — `ncl <resource> help` shows the full set.

### groups

Agent groups: the agent identities with their own folder, history, and container image. Beyond CRUD, `groups` carries the container-config and lifecycle verbs.

```bash theme={null}
ncl groups create --name "Research" --folder research
ncl groups restart --id <group-id> --rebuild
```

`restart` kills and respawns the group's containers (`--rebuild` rebuilds the image first — required after package changes; `--message <text>` leaves an on-wake instruction). `delete` cascades through sessions, wirings, roles, memberships, and destinations in one transaction.

Config subcommands edit the group's `container_configs` row — changes apply on the next `restart`:

```bash theme={null}
ncl groups config get --id <group-id>
ncl groups config update --id <group-id> --model claude-sonnet-4-5 --effort high
ncl groups config add-mcp-server --id <group-id> --name fetch --command npx --args '["mcp-fetch"]'
ncl groups config add-package --id <group-id> --apt ffmpeg
```

`config update` accepts `--provider`, `--model`, `--effort`, `--image-tag`, `--assistant-name`, `--max-messages-per-prompt`, and `--cli-scope`.

### messaging-groups and wirings

A messaging group is one chat on one platform (unique `channel_type` + `platform_id`); a wiring connects it to an agent group and sets engagement rules. List commands accept column filters and `--limit`:

```bash theme={null}
ncl messaging-groups list --channel_type telegram
ncl wirings create --messaging-group-id <mg-id> --agent-group-id <group-id> --engage-mode mention-sticky
ncl wirings update --id <wiring-id> --session-mode per-thread
```

Wiring columns: `engage_mode` (`mention` | `mention-sticky` | `pattern`), `engage_pattern`, `sender_scope` (`all` | `known`), `ignored_message_policy` (`drop` | `accumulate`), `session_mode` (`shared` | `per-thread` | `agent-shared`).

### users, roles, and members

Users are per-channel identities (`tg:6037840640`, `discord:1234...`). Roles grant privilege (`owner` is always global; `admin` can be global or scoped to one group with `--group`). Members let unprivileged users talk to a group when its wiring has `sender_scope known`.

```bash theme={null}
ncl users create --id tg:6037840640 --kind telegram --display-name "Ethan"
ncl roles grant --user tg:6037840640 --role admin --group <group-id>
ncl members add --user tg:6037840640 --group <group-id>
```

`roles revoke` and `members remove` take the same flags.

### sessions

Read-only view of the runtime units — one row per (agent group, messaging group, thread) with its container status (`running` | `stopped`; `idle` is reserved and currently unused):

```bash theme={null}
ncl sessions list --agent_group_id <group-id>
```

### dropped-messages

Read-only log of messages the router dropped, aggregated per sender and chat with a `reason` (`no_agent_wired`, `no_agent_engaged`, `unknown_sender_strict`, `unknown_sender_request_approval`). Your first stop when a message got no reply:

```bash theme={null}
ncl dropped-messages list
```

### approvals

Read-only view of in-flight approval cards waiting for an admin response:

```bash theme={null}
ncl approvals list --status pending
```

### destinations and user-dms

Destinations are per-agent send ACLs — each row lets an agent address a channel or another agent by a local name. `user-dms` is the read-only DM-route cache the host uses to cold-DM users.

```bash theme={null}
ncl destinations list --agent_group_id <group-id>
ncl destinations add --agent-group-id <group-id> --local-name ops-channel --target-type channel --target-id <mg-id>
ncl user-dms list
```
