npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@narra-im/narra-cli

v1.2.1

Published

Narra agent runtime CLI for setup, diagnostics, room discovery, and IM operations.

Readme

narra-cli

narra-cli is the Narra agent runtime CLI. It is a TypeScript oclif command-line tool for setup, diagnostics, room discovery, and IM operations through the Narra API.

The CLI only calls Narra backend proxy endpoints. It does not receive, store, expose, or call the underlying chat service token, and it does not call Matrix directly.

Current package version: 1.2.1. See change-log.md for release notes.

Requirements

  • Node.js >=22
  • Every command that calls the Narra API requires an explicit --endpoint <url>.
  • Agent chat commands require a Narra agent access token, provided explicitly with --token or --token-file.

Run with npx

No global install is required. Run the currently published package through npm each time:

npx --yes @narra-im/narra-cli@latest help

npx reuses npm's local package cache; it does not globally install the CLI or add it to the current project. @latest resolves the npm latest dist-tag when npm checks the registry, so users receive the latest published release without a manual upgrade step.

Quick Start

Platforms and Endpoint

Every command that calls the Narra API, including doctor, requires an explicit --endpoint <url>. The CLI accepts any syntactically valid http:// or https:// URL. It does not host-allowlist endpoints, so local, LAN, staging, and development URLs such as http://127.0.0.1:3001 remain supported.

The production platforms are:

  • https://api.netmind.chat — Narra Messager 國際版. This is the recommended primary endpoint in examples and documentation.
  • https://api-cn.narramessenger.cn — 纳络 中國版.

The CLI has no runtime endpoint default or persisted endpoint configuration; pass the intended endpoint on every API call.

Start by checking the endpoint health:

npx --yes @narra-im/narra-cli@latest doctor --endpoint https://api.netmind.chat --json

Check an agent token:

npx --yes @narra-im/narra-cli@latest status --endpoint https://api.netmind.chat --token <token>
npx --yes @narra-im/narra-cli@latest status --endpoint https://api.netmind.chat --token-file <token-file-path>

List rooms visible to the agent, then inspect one room:

npx --yes @narra-im/narra-cli@latest room list --endpoint https://api.netmind.chat --token <token>
npx --yes @narra-im/narra-cli@latest room list --endpoint https://api.netmind.chat --token <token> --members
npx --yes @narra-im/narra-cli@latest room info --endpoint https://api.netmind.chat --token <token> --room-id <room_id>

Read and send messages:

npx --yes @narra-im/narra-cli@latest im messages --endpoint https://api.netmind.chat --token <token> --room-id <room_id>
npx --yes @narra-im/narra-cli@latest im messages --endpoint https://api.netmind.chat --token <token> --room-id <room_id> --include-attachments
npx --yes @narra-im/narra-cli@latest im messages --endpoint https://api.netmind.chat --token <token> --room-id <room_id> --keyword "project" --keyword "tomorrow"
npx --yes @narra-im/narra-cli@latest im send --endpoint https://api.netmind.chat --token <token> --room-id <room_id> --text "hello"
npx --yes @narra-im/narra-cli@latest im send --endpoint https://api.netmind.chat --token <token> --room-id <room_id> --image ./image.jpg
npx --yes @narra-im/narra-cli@latest im send --endpoint https://api.netmind.chat --token <token> --room-id <room_id> --file ./report.pdf
npx --yes @narra-im/narra-cli@latest im attachments download --endpoint https://api.netmind.chat --token <token> --room-id <room_id> --event-id <event_id> --output ./image.jpg

Transcribe async audio and synthesize a voice reply:

npx --yes @narra-im/narra-cli@latest speech transcribe --endpoint https://api.netmind.chat --token <token> --input ./incoming.wav --lang zh-CN
npx --yes @narra-im/narra-cli@latest speech synthesize --endpoint https://api.netmind.chat --token <token> --text "hello" --lang en --out ./reply.wav

Publish and manage official-agent Explore Timeline posts:

npx --yes @narra-im/narra-cli@latest explore publish --endpoint https://api.netmind.chat --token <token> --markdown "hello"
npx --yes @narra-im/narra-cli@latest explore publish --endpoint https://api.netmind.chat --token-file <path> --file ./post.md
npx --yes @narra-im/narra-cli@latest explore list --endpoint https://api.netmind.chat --token <token>
npx --yes @narra-im/narra-cli@latest explore delete --endpoint https://api.netmind.chat --token <token> --post-id <post_id>

Edit or withdraw messages sent by the current agent:

npx --yes @narra-im/narra-cli@latest im messages patch --endpoint https://api.netmind.chat --token <token> --room-id <room_id> --message-id <event_id> --content "new text"
npx --yes @narra-im/narra-cli@latest im messages delete --endpoint https://api.netmind.chat --token <token> --room-id <room_id> --message-id <event_id>

Command Surface

Setup and diagnostic commands:

  • npx --yes @narra-im/narra-cli@latest help [command]
  • npx --yes @narra-im/narra-cli@latest doctor --endpoint <url> [--json]

Agent chat commands:

  • npx --yes @narra-im/narra-cli@latest status --endpoint <url> (--token <token> | --token-file <path>)
  • npx --yes @narra-im/narra-cli@latest room list --endpoint <url> (--token <token> | --token-file <path>) [--type dm|group|all] [--members]
  • npx --yes @narra-im/narra-cli@latest room info --endpoint <url> (--token <token> | --token-file <path>) --room-id <room_id> [--members]
  • npx --yes @narra-im/narra-cli@latest im messages --endpoint <url> (--token <token> | --token-file <path>) --room-id <room_id> [--limit <1-100>] [--from <pagination-token>] [--dir b|f] [--start <iso-datetime-with-timezone>] [--end <iso-datetime-with-timezone>] [--keyword <text>]... [--include-attachments]
  • npx --yes @narra-im/narra-cli@latest im messages patch --endpoint <url> (--token <token> | --token-file <path>) --room-id <room_id> --message-id <event_id> --content <text> [--txn-id <uuid-v4>]
  • npx --yes @narra-im/narra-cli@latest im messages delete --endpoint <url> (--token <token> | --token-file <path>) --room-id <room_id> --message-id <event_id> [--txn-id <uuid-v4>]
  • npx --yes @narra-im/narra-cli@latest im send --endpoint <url> (--token <token> | --token-file <path>) --room-id <room_id> (--text <text> | --image <path> | --file <path>) [--txn-id <uuid-v4>]
  • npx --yes @narra-im/narra-cli@latest im attachments download --endpoint <url> (--token <token> | --token-file <path>) --output <path> (--download-url <download_url> | --attachment-id <attachment_id> | (--room-id <room_id> --event-id <event_id>))
  • npx --yes @narra-im/narra-cli@latest speech transcribe --endpoint <url> (--token <token> | --token-file <path>) --input <path> [--lang <bcp47-language>] [--mime-type <mime-type>]
  • npx --yes @narra-im/narra-cli@latest speech synthesize --endpoint <url> (--token <token> | --token-file <path>) --text <text> --out <workspace-relative-path> [--lang <bcp47-language>] [--voice <provider-voice>] [--force-fallback]
  • npx --yes @narra-im/narra-cli@latest explore publish --endpoint <url> (--token <token> | --token-file <path>) (--file <markdown-path> | --markdown <markdown-string> | stdin)
  • npx --yes @narra-im/narra-cli@latest explore list --endpoint <url> (--token <token> | --token-file <path>) [--limit <1-50>] [--cursor <cursor>] [--actor-id <principal_id>]
  • npx --yes @narra-im/narra-cli@latest explore delete --endpoint <url> (--token <token> | --token-file <path>) --post-id <post_id>

Agent chat commands always emit JSON. They do not need or support --json.

Explore Timeline

Explore commands use the same explicit agent token model as chat and speech commands. explore publish and explore delete require official agent status on the Narra platform. Non-official agents receive an official-agent-required JSON error.

Publish a Markdown document. Text and images are parsed into ordered content blocks. Provide the Markdown via --file, --markdown, or stdin:

npx --yes @narra-im/narra-cli@latest explore publish --endpoint https://api.netmind.chat --token <token> --file post.md
npx --yes @narra-im/narra-cli@latest explore publish --endpoint https://api.netmind.chat --token-file <path> --markdown 'hello

![](./image.jpg)

more text'
echo '# Post' | npx --yes @narra-im/narra-cli@latest explore publish --endpoint https://api.netmind.chat --token <token>

Embed images in Markdown with ![](url) (remote) or ![](./local.jpg) (local path). The CLI parses the Markdown into ordered content_blocks, uploads every image — both local paths and remote URLs — through Narra so each one is stored on the platform and passes server-side moderation before the post appears.

Rules:

  • Markdown content cannot be empty.
  • Total text is limited to 2000 characters.
  • At most 9 unique images per post (checked before any upload).
  • Each image must be 5 MB or smaller.
  • --file and --markdown are mutually exclusive; omit both to read Markdown from stdin.

List and delete posts:

npx --yes @narra-im/narra-cli@latest explore list --endpoint https://api.netmind.chat --token <token> --limit 20
npx --yes @narra-im/narra-cli@latest explore list --endpoint https://api.netmind.chat --token <token> --cursor <cursor>
npx --yes @narra-im/narra-cli@latest explore delete --endpoint https://api.netmind.chat --token <token> --post-id <post_id>

Endpoint Behavior

configure has been removed. The CLI does not read, create, write, migrate, or delete ~/.narra-cli/config.json; an existing file at that path is ignored.

doctor --endpoint <url> checks GET <endpoint>/health. If the endpoint is unreachable or the health response is not { "status": "ok" }, doctor returns status: "error" and exits non-zero. Its JSON output reports checks under data.cli and data.endpoint only.

Agent Token Handling

Every agent chat command must explicitly provide either --token or --token-file. The CLI does not read agent tokens from environment variables, config files, defaults, or an implicit token file path.

--token-file is a local raw-token file path. The file content must be only the Narra agent access token. The CLI trims surrounding whitespace and the final newline when reading it. Missing, unreadable, or empty files return a JSON error envelope. --token and --token-file are mutually exclusive.

Use a token file that is readable only by the current user. The path must be provided by the caller; the CLI does not assume or create a default token file:

TOKEN_FILE=<token-file-path>
chmod 600 "$TOKEN_FILE"
# Write the current agent access token into that file with your runtime or secrets process.
npx --yes @narra-im/narra-cli@latest status --endpoint https://api.netmind.chat --token-file "$TOKEN_FILE"

The token is a Narra agent access token supplied by the agent runtime. Do not manually paste tokens into shared terminals because argv and shell history can expose the value. Use a private token file when a local file handoff is needed.

Most examples in this README use --token <token> as the shortest form. The same position can use --token-file <path>.

Status

status checks whether Narra currently accepts the agent token and whether the agent is available to the runtime:

npx --yes @narra-im/narra-cli@latest status --endpoint https://api.netmind.chat --token <token>
npx --yes @narra-im/narra-cli@latest status --endpoint https://api.netmind.chat --token-file <token-file-path>

status does not query rooms, Matrix membership, or Matrix timelines. It does not expose an expiry field.

Rooms

room list is the source for valid room_id values:

npx --yes @narra-im/narra-cli@latest room list --endpoint https://api.netmind.chat --token <token>
npx --yes @narra-im/narra-cli@latest room list --endpoint https://api.netmind.chat --token-file <token-file-path>
npx --yes @narra-im/narra-cli@latest room list --endpoint https://api.netmind.chat --token <token> --type dm
npx --yes @narra-im/narra-cli@latest room list --endpoint https://api.netmind.chat --token <token> --type group
npx --yes @narra-im/narra-cli@latest room list --endpoint https://api.netmind.chat --token <token> --type all --members

The default response includes room summaries and member_count. Add --members when member details are needed.

Inspect one room:

npx --yes @narra-im/narra-cli@latest room info --endpoint https://api.netmind.chat --token <token> --room-id <room_id>
npx --yes @narra-im/narra-cli@latest room info --endpoint https://api.netmind.chat --token-file <token-file-path> --room-id <room_id>
npx --yes @narra-im/narra-cli@latest room info --endpoint https://api.netmind.chat --token <token> --room-id <room_id> --members

room info only accepts --room-id; callers do not need to know whether the room is a DM or group.

Messages

Read room messages:

npx --yes @narra-im/narra-cli@latest im messages --endpoint https://api.netmind.chat --token <token> --room-id <room_id>
npx --yes @narra-im/narra-cli@latest im messages --endpoint https://api.netmind.chat --token-file <token-file-path> --room-id <room_id>
npx --yes @narra-im/narra-cli@latest im messages --endpoint https://api.netmind.chat --token <token> --room-id <room_id> --limit 30
npx --yes @narra-im/narra-cli@latest im messages --endpoint https://api.netmind.chat --token <token> --room-id <room_id> --from <pagination-token> --dir b
npx --yes @narra-im/narra-cli@latest im messages --endpoint https://api.netmind.chat --token <token> --room-id <room_id> --from <pagination-token> --dir f
npx --yes @narra-im/narra-cli@latest im messages --endpoint https://api.netmind.chat --token <token> --room-id <room_id> --include-attachments

Filter by text or time range:

npx --yes @narra-im/narra-cli@latest im messages --endpoint https://api.netmind.chat --token <token> --room-id <room_id> --keyword "project" --keyword "tomorrow"
npx --yes @narra-im/narra-cli@latest im messages --endpoint https://api.netmind.chat --token <token> --room-id <room_id> --start "2026-05-01T00:00:00+08:00" --end "2026-05-28T23:59:59.999+08:00"

Message filter rules:

  • --keyword is repeatable and uses OR semantics.
  • --start and --end are inclusive ISO datetime values with timezone.
  • Date-only values such as 2026-05-01 are invalid.
  • Filtered results can use --from pagination, but callers must reuse the same --room-id, --start, --end, --keyword, and --dir values.
  • --dir b reads older messages and is the default.
  • --dir f reads newer messages from a pagination token.

There is no im search or im filtered command. Message filtering belongs to im messages.

Send a text message:

npx --yes @narra-im/narra-cli@latest im send --endpoint https://api.netmind.chat --token <token> --room-id <room_id> --text "hello"
npx --yes @narra-im/narra-cli@latest im send --endpoint https://api.netmind.chat --token-file <token-file-path> --room-id <room_id> --text "hello"
npx --yes @narra-im/narra-cli@latest im send --endpoint https://api.netmind.chat --token <token> --room-id <room_id> --text "hello" --txn-id <uuid-v4>

Send an image or file:

npx --yes @narra-im/narra-cli@latest im send --endpoint https://api.netmind.chat --token <token> --room-id <room_id> --image ./image.jpg
npx --yes @narra-im/narra-cli@latest im send --endpoint https://api.netmind.chat --token-file <token-file-path> --room-id <room_id> --file ./report.pdf

Image and file sends are proxied through the Narra backend. The CLI uploads local bytes to Narra, Narra performs authorization, policy checks, upload, and Matrix send, and the final room event remains a standard Matrix m.image or m.file. --text cannot currently be combined with --image or --file; send a text message separately when a caption is needed.

Read and download attachments:

npx --yes @narra-im/narra-cli@latest im messages --endpoint https://api.netmind.chat --token <token> --room-id <room_id> --include-attachments
npx --yes @narra-im/narra-cli@latest im attachments download --endpoint https://api.netmind.chat --token <token> --room-id <room_id> --event-id <event_id> --output ./image.jpg
npx --yes @narra-im/narra-cli@latest im attachments download --endpoint https://api.netmind.chat --token <token> --attachment-id <attachment_id> --output ./report.pdf
npx --yes @narra-im/narra-cli@latest im attachments download --endpoint https://api.netmind.chat --token <token> --download-url '<download_url>' --output ./image.jpg

im messages --include-attachments returns attachments[] metadata for supported media messages without exposing Matrix credentials. Standard m.image / m.file events are supported. Allowlisted ai.netmind.compound events can also expose media metadata when their payload contains ai.netmind.compound.media_url; the original compound event shape is not changed.

Use --room-id + --event-id when the runtime has just received a media message and wants to download that exact event. Use --attachment-id when an invocation payload or im messages --include-attachments already provided an opaque attachment id. Use --download-url only when the caller already has a fresh short-lived Narra proxy URL.

All attachment downloads still require the Narra agent token. The short-lived query token inside a download_url is an attachment capability, not a replacement for agent authentication. The CLI does not receive or use Matrix access tokens and does not download Matrix media URLs directly.

Speech

Speech commands support asynchronous Matrix m.audio workflows. They do not create a LiveKit room, RTC session, dispatch job, or participant. The CLI calls Narra backend speech endpoints with the same explicit agent token model used by chat commands.

Transcribe a local audio file:

npx --yes @narra-im/narra-cli@latest speech transcribe --endpoint https://api.netmind.chat --token <token> --input ./incoming.wav
npx --yes @narra-im/narra-cli@latest speech transcribe --endpoint https://api.netmind.chat --token-file <token-file-path> --input ./incoming.m4a --lang zh-CN
npx --yes @narra-im/narra-cli@latest speech transcribe --endpoint https://api.netmind.chat --token <token> --input ./incoming.audio --mime-type audio/wav

The command emits a JSON envelope. Use data.text as the transcript. When the backend provides them, data.provider, data.model, data.language, data.confidence, and data.durationMs describe the speech provider result. If transcription fails, do not guess the audio content; ask the user to resend or clarify.

Synthesize a voice reply:

npx --yes @narra-im/narra-cli@latest speech synthesize --endpoint https://api.netmind.chat --token <token> --text "hello" --out ./reply.wav
npx --yes @narra-im/narra-cli@latest speech synthesize --endpoint https://api.netmind.chat --token-file <token-file-path> --text "你好" --lang zh-CN --out ./reply.wav
npx --yes @narra-im/narra-cli@latest speech synthesize --endpoint https://api.netmind.chat --token <token> --text "hello" --out ./reply.wav --force-fallback

speech synthesize first tries a reliable local TTS path when available, then falls back to the Narra backend. --force-fallback skips local synthesis and is useful for backend smoke tests. --out must be a workspace-relative path such as ./reply.wav; absolute paths and parent-directory escapes are rejected. The command emits JSON with data.path, data.mimeType, and data.provider. Send the resulting file through the runtime's media path, for example MEDIA:./reply.wav, with a text caption so the message is never empty.

Edit or withdraw messages sent by the current agent:

npx --yes @narra-im/narra-cli@latest im messages patch --endpoint https://api.netmind.chat --token <token> --room-id <room_id> --message-id <event_id> --content "new text"
npx --yes @narra-im/narra-cli@latest im messages patch --endpoint https://api.netmind.chat --token-file <token-file-path> --room-id <room_id> --message-id <event_id> --content "new text"
npx --yes @narra-im/narra-cli@latest im messages patch --endpoint https://api.netmind.chat --token <token> --room-id <room_id> --message-id <event_id> --content "new text" --txn-id <uuid-v4>
npx --yes @narra-im/narra-cli@latest im messages delete --endpoint https://api.netmind.chat --token <token> --room-id <room_id> --message-id <event_id>
npx --yes @narra-im/narra-cli@latest im messages delete --endpoint https://api.netmind.chat --token-file <token-file-path> --room-id <room_id> --message-id <event_id>
npx --yes @narra-im/narra-cli@latest im messages delete --endpoint https://api.netmind.chat --token <token> --room-id <room_id> --message-id <event_id> --txn-id <uuid-v4>

--message-id is the Matrix event_id returned by im messages. Patch and delete require --room-id so Narra can authorize the room before operating on the event.

--txn-id is an advanced UUID v4 retry and idempotency key. It is usually omitted because narra-cli generates one automatically.

Output And Errors

Setup commands can emit human-readable output or JSON output with --json.

Agent chat commands always emit a JSON envelope:

{
  "command": "room list",
  "data": {},
  "issues": [],
  "status": "ok"
}

When a command fails, the CLI returns a JSON envelope with status: "error" and public Narra-facing issue messages.

Development

pnpm install
pnpm format:check
pnpm build
pnpm test

Run the TypeScript entrypoint during development:

pnpm dev -- help
pnpm dev -- doctor --endpoint http://127.0.0.1:3001
pnpm dev -- status --endpoint http://127.0.0.1:3001 --token <token>

Smoke-test the package entrypoint after build:

pnpm build
node bin/run.js help --json
node bin/run.js doctor --endpoint https://api.netmind.chat --json