@nordbyte/nordrelay 0.8.0 → 0.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +9 -0
- package/README.md +81 -1197
- package/dist/{access-control.js → access/access-control.js} +1 -1
- package/dist/{audit-log.js → access/audit-log.js} +2 -2
- package/dist/{session-locks.js → access/session-locks.js} +1 -1
- package/dist/{user-management.js → access/user-management.js} +1 -1
- package/dist/{claude-code-cli.js → agents/claude-code/claude-code-cli.js} +2 -2
- package/dist/{claude-code-session.js → agents/claude-code/claude-code-session.js} +1 -1
- package/dist/{codex-cli.js → agents/codex/codex-cli.js} +14 -5
- package/dist/{codex-session.js → agents/codex/codex-session.js} +2 -4
- package/dist/{hermes-cli.js → agents/hermes/hermes-cli.js} +2 -2
- package/dist/{hermes-launch.js → agents/hermes/hermes-launch.js} +1 -1
- package/dist/{hermes-session.js → agents/hermes/hermes-session.js} +1 -1
- package/dist/{openclaw-cli.js → agents/openclaw/openclaw-cli.js} +2 -2
- package/dist/{openclaw-launch.js → agents/openclaw/openclaw-launch.js} +1 -1
- package/dist/{openclaw-session.js → agents/openclaw/openclaw-session.js} +1 -1
- package/dist/{pi-cli.js → agents/pi/pi-cli.js} +2 -2
- package/dist/{pi-launch.js → agents/pi/pi-launch.js} +1 -1
- package/dist/{pi-session.js → agents/pi/pi-session.js} +1 -1
- package/dist/{adapter-conformance.js → agents/shared/adapter-conformance.js} +2 -2
- package/dist/{agent-activity.js → agents/shared/agent-activity.js} +5 -5
- package/dist/agents/shared/agent-auth-commands.js +30 -0
- package/dist/{agent-factory.js → agents/shared/agent-factory.js} +5 -5
- package/dist/{agent-feature-matrix.js → agents/shared/agent-feature-matrix.js} +2 -2
- package/dist/{agent-updates.js → agents/shared/agent-updates.js} +7 -7
- package/dist/{discord-artifacts.js → channels/discord/discord-artifacts.js} +4 -4
- package/dist/{discord-bot.js → channels/discord/discord-bot.js} +164 -424
- package/dist/{discord-channel-runtime.js → channels/discord/discord-channel-runtime.js} +2 -2
- package/dist/{discord-command-surface.js → channels/discord/discord-command-surface.js} +3 -3
- package/dist/{bot-rendering.js → channels/shared/bot-rendering.js} +6 -6
- package/dist/{channel-actions.js → channels/shared/channel-actions.js} +4 -4
- package/dist/channels/shared/channel-bridge-controller.js +69 -0
- package/dist/channels/shared/channel-cli-artifacts.js +51 -0
- package/dist/{channel-command-service.js → channels/shared/channel-command-service.js} +51 -28
- package/dist/channels/shared/channel-external-mirror-controller.js +193 -0
- package/dist/channels/shared/channel-external-monitor.js +52 -0
- package/dist/{channel-mirror-registry.js → channels/shared/channel-mirror-registry.js} +14 -6
- package/dist/{channel-peer-prompt.js → channels/shared/channel-peer-prompt.js} +3 -3
- package/dist/{channel-turn-service.js → channels/shared/channel-turn-service.js} +2 -2
- package/dist/{context-key.js → channels/shared/context-key.js} +1 -1
- package/dist/{session-format.js → channels/shared/session-format.js} +2 -2
- package/dist/{slack-artifacts.js → channels/slack/slack-artifacts.js} +4 -4
- package/dist/{slack-bot.js → channels/slack/slack-bot.js} +159 -294
- package/dist/{slack-channel-runtime.js → channels/slack/slack-channel-runtime.js} +2 -2
- package/dist/{slack-command-surface.js → channels/slack/slack-command-surface.js} +2 -2
- package/dist/{slack-diagnostics.js → channels/slack/slack-diagnostics.js} +2 -2
- package/dist/{bot-ui.js → channels/telegram/bot-ui.js} +1 -1
- package/dist/{bot.js → channels/telegram/bot.js} +178 -427
- package/dist/{telegram-access-commands.js → channels/telegram/telegram-access-commands.js} +3 -3
- package/dist/{telegram-access-middleware.js → channels/telegram/telegram-access-middleware.js} +4 -4
- package/dist/{telegram-agent-commands.js → channels/telegram/telegram-agent-commands.js} +9 -9
- package/dist/{telegram-artifact-commands.js → channels/telegram/telegram-artifact-commands.js} +4 -4
- package/dist/{telegram-channel-runtime.js → channels/telegram/telegram-channel-runtime.js} +2 -2
- package/dist/{telegram-command-menu.js → channels/telegram/telegram-command-menu.js} +1 -1
- package/dist/{telegram-diagnostics-command.js → channels/telegram/telegram-diagnostics-command.js} +7 -7
- package/dist/{telegram-general-commands.js → channels/telegram/telegram-general-commands.js} +4 -4
- package/dist/{telegram-operational-commands.js → channels/telegram/telegram-operational-commands.js} +5 -5
- package/dist/{telegram-output.js → channels/telegram/telegram-output.js} +2 -2
- package/dist/{telegram-preference-commands.js → channels/telegram/telegram-preference-commands.js} +3 -3
- package/dist/{telegram-queue-commands.js → channels/telegram/telegram-queue-commands.js} +6 -6
- package/dist/{telegram-support-command.js → channels/telegram/telegram-support-command.js} +4 -4
- package/dist/{telegram-update-commands.js → channels/telegram/telegram-update-commands.js} +5 -5
- package/dist/{config-metadata.js → core/config-metadata.js} +8 -0
- package/dist/{config.js → core/config.js} +11 -3
- package/dist/index.js +27 -23
- package/dist/{peer-client.js → peers/peer-client.js} +57 -1
- package/dist/peers/peer-discovery-jobs.js +206 -0
- package/dist/peers/peer-discovery.js +223 -0
- package/dist/peers/peer-health-monitor.js +49 -0
- package/dist/{peer-identity.js → peers/peer-identity.js} +50 -1
- package/dist/{peer-runtime-service.js → peers/peer-runtime-service.js} +29 -7
- package/dist/{peer-server.js → peers/peer-server.js} +23 -6
- package/dist/{peer-store.js → peers/peer-store.js} +84 -11
- package/dist/{peer-types.js → peers/peer-types.js} +9 -0
- package/dist/peers/peer-web-proxy-contract.js +127 -0
- package/dist/{metrics.js → runtime/metrics.js} +5 -3
- package/dist/{relay-artifact-service.js → runtime/relay-artifact-service.js} +1 -1
- package/dist/runtime/relay-auth-service.js +63 -0
- package/dist/runtime/relay-dashboard-service.js +139 -0
- package/dist/{relay-external-activity-monitor.js → runtime/relay-external-activity-monitor.js} +140 -53
- package/dist/runtime/relay-runtime-active-sessions.js +387 -0
- package/dist/runtime/relay-runtime-dashboard.js +201 -0
- package/dist/runtime/relay-runtime-prompt-queue-artifacts.js +307 -0
- package/dist/runtime/relay-runtime-sessions.js +623 -0
- package/dist/runtime/relay-runtime-types.js +1 -0
- package/dist/runtime/relay-runtime-updates-jobs.js +360 -0
- package/dist/runtime/relay-runtime.js +451 -0
- package/dist/runtime/runtime-cache.js +117 -0
- package/dist/{session-registry.js → state/session-registry.js} +3 -3
- package/dist/{operations.js → support/operations.js} +7 -7
- package/dist/{support-bundle.js → support/support-bundle.js} +1 -1
- package/dist/{web-api-contract.js → web/web-api-contract.js} +17 -3
- package/dist/web/web-api-types.js +1 -0
- package/dist/{web-dashboard-access-routes.js → web/web-dashboard-access-routes.js} +2 -2
- package/dist/{web-dashboard-assets.js → web/web-dashboard-assets.js} +24 -2
- package/dist/{web-dashboard-http.js → web/web-dashboard-http.js} +41 -5
- package/dist/{web-dashboard-pages.js → web/web-dashboard-pages.js} +37 -10
- package/dist/{web-dashboard-peer-routes.js → web/web-dashboard-peer-routes.js} +102 -7
- package/dist/web/web-dashboard-security.js +14 -0
- package/dist/{web-dashboard-session-routes.js → web/web-dashboard-session-routes.js} +12 -1
- package/dist/{web-dashboard.js → web/web-dashboard.js} +132 -48
- package/dist/web/web-performance.js +60 -0
- package/dist/web/web-rate-limit.js +19 -0
- package/dist/{web-state.js → web/web-state.js} +74 -5
- package/dist/webui-assets/dashboard.css +171 -10
- package/dist/webui-assets/dashboard.js +515 -48
- package/dist/webui-assets/favicon.ico +0 -0
- package/dist/webui-assets/favicon.png +0 -0
- package/dist/webui-assets/logo.png +0 -0
- package/package.json +4 -3
- package/plugins/nordrelay/scripts/nordrelay.mjs +17 -5
- package/{launchd/start.sh → scripts/launchd-start.sh} +1 -1
- package/dist/relay-runtime.js +0 -1916
- package/dist/runtime-cache.js +0 -57
- /package/dist/{user-management-crypto.js → access/user-management-crypto.js} +0 -0
- /package/dist/{user-management-normalize.js → access/user-management-normalize.js} +0 -0
- /package/dist/{user-management-types.js → access/user-management-types.js} +0 -0
- /package/dist/{claude-code-auth.js → agents/claude-code/claude-code-auth.js} +0 -0
- /package/dist/{claude-code-launch.js → agents/claude-code/claude-code-launch.js} +0 -0
- /package/dist/{claude-code-state.js → agents/claude-code/claude-code-state.js} +0 -0
- /package/dist/{codex-auth.js → agents/codex/codex-auth.js} +0 -0
- /package/dist/{codex-config.js → agents/codex/codex-config.js} +0 -0
- /package/dist/{codex-launch.js → agents/codex/codex-launch.js} +0 -0
- /package/dist/{codex-state.js → agents/codex/codex-state.js} +0 -0
- /package/dist/{hermes-api.js → agents/hermes/hermes-api.js} +0 -0
- /package/dist/{hermes-auth.js → agents/hermes/hermes-auth.js} +0 -0
- /package/dist/{hermes-state.js → agents/hermes/hermes-state.js} +0 -0
- /package/dist/{openclaw-auth.js → agents/openclaw/openclaw-auth.js} +0 -0
- /package/dist/{openclaw-gateway.js → agents/openclaw/openclaw-gateway.js} +0 -0
- /package/dist/{openclaw-state.js → agents/openclaw/openclaw-state.js} +0 -0
- /package/dist/{pi-auth.js → agents/pi/pi-auth.js} +0 -0
- /package/dist/{pi-rpc.js → agents/pi/pi-rpc.js} +0 -0
- /package/dist/{pi-state.js → agents/pi/pi-state.js} +0 -0
- /package/dist/{agent-adapter.js → agents/shared/agent-adapter.js} +0 -0
- /package/dist/{agent.js → agents/shared/agent.js} +0 -0
- /package/dist/{artifacts.js → artifacts/artifacts.js} +0 -0
- /package/dist/{attachments.js → artifacts/attachments.js} +0 -0
- /package/dist/{voice.js → artifacts/voice.js} +0 -0
- /package/dist/{discord-rate-limit.js → channels/discord/discord-rate-limit.js} +0 -0
- /package/dist/{channel-adapter.js → channels/shared/channel-adapter.js} +0 -0
- /package/dist/{relay-runtime-types.js → channels/shared/channel-bridge-state.js} +0 -0
- /package/dist/{channel-command-catalog.js → channels/shared/channel-command-catalog.js} +0 -0
- /package/dist/{channel-command-core.js → channels/shared/channel-command-core.js} +0 -0
- /package/dist/{channel-prompt-engine.js → channels/shared/channel-prompt-engine.js} +0 -0
- /package/dist/{channel-runtime.js → channels/shared/channel-runtime.js} +0 -0
- /package/dist/{channel-turn-lifecycle.js → channels/shared/channel-turn-lifecycle.js} +0 -0
- /package/dist/{slack-rate-limit.js → channels/slack/slack-rate-limit.js} +0 -0
- /package/dist/{telegram-command-types.js → channels/telegram/telegram-command-types.js} +0 -0
- /package/dist/{telegram-rate-limit.js → channels/telegram/telegram-rate-limit.js} +0 -0
- /package/dist/{activity-events.js → core/activity-events.js} +0 -0
- /package/dist/{error-messages.js → core/error-messages.js} +0 -0
- /package/dist/{format.js → core/format.js} +0 -0
- /package/dist/{logger.js → core/logger.js} +0 -0
- /package/dist/{redaction.js → core/redaction.js} +0 -0
- /package/dist/{settings-service.js → core/settings-service.js} +0 -0
- /package/dist/{settings-wizard-test.js → core/settings-wizard-test.js} +0 -0
- /package/dist/{workspace-policy.js → core/workspace-policy.js} +0 -0
- /package/dist/{peer-auth.js → peers/peer-auth.js} +0 -0
- /package/dist/{peer-context.js → peers/peer-context.js} +0 -0
- /package/dist/{peer-readiness.js → peers/peer-readiness.js} +0 -0
- /package/dist/{relay-queue-service.js → runtime/relay-queue-service.js} +0 -0
- /package/dist/{web-api-types.js → runtime/relay-runtime-delegate.js} +0 -0
- /package/dist/{relay-runtime-helpers.js → runtime/relay-runtime-helpers.js} +0 -0
- /package/dist/{remote-prompt.js → runtime/remote-prompt.js} +0 -0
- /package/dist/{bot-preferences.js → state/bot-preferences.js} +0 -0
- /package/dist/{job-store.js → state/job-store.js} +0 -0
- /package/dist/{persistence.js → state/persistence.js} +0 -0
- /package/dist/{prompt-store.js → state/prompt-store.js} +0 -0
- /package/dist/{state-backend.js → state/state-backend.js} +0 -0
- /package/dist/{zip-writer.js → support/zip-writer.js} +0 -0
- /package/dist/{web-dashboard-artifact-routes.js → web/web-dashboard-artifact-routes.js} +0 -0
- /package/dist/{web-dashboard-runtime-routes.js → web/web-dashboard-runtime-routes.js} +0 -0
- /package/dist/{web-dashboard-ui.js → web/web-dashboard-ui.js} +0 -0
package/README.md
CHANGED
|
@@ -1,1274 +1,158 @@
|
|
|
1
1
|
# NordRelay
|
|
2
|
+
 [](https://github.com/nordbyte/nordrelay/releases/latest) [](https://github.com/nordbyte/nordrelay/actions/workflows/ci.yml) [](LICENSE) [](https://www.npmjs.com/package/@nordbyte/nordrelay) [](package.json) [](tsconfig.json)
|
|
2
3
|
|
|
3
|
-
NordRelay is a remote control plane for coding agents
|
|
4
|
+
NordRelay is a secure remote control plane for coding agents. It connects Codex, Pi, Hermes, OpenClaw, and Claude Code sessions to Telegram, Discord, Slack, the WebUI, and trusted peer nodes, with streaming replies, file/photo/voice input, queues, artifacts, user permissions, and multi-host control.
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
Use the README for the first install and quick start. Full feature, command, configuration, deployment, and architecture details live in [docs/](docs/).
|
|
6
7
|
|
|
7
|
-
##
|
|
8
|
+
## Quick Start
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
Requirements:
|
|
10
11
|
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
- `/new` starts a fresh thread, with workspace selection when known workspaces are available.
|
|
15
|
-
- `/session` shows thread id, workspace, launch profile, launch behavior, model, reasoning, fast mode, context usage, token totals, and subscription limit remaining percentages.
|
|
16
|
-
- `/sessions` opens a paginated browser for recent sessions from the selected agent.
|
|
17
|
-
- `/sessions <query>` filters recent sessions by id, title, workspace, model, or first message.
|
|
18
|
-
- `/sync` manually refreshes the active chat session from local CLI state when the selected agent supports state watching.
|
|
19
|
-
- `/pin`, `/unpin`, and `/pinned` keep important threads at the top of Telegram session browsing.
|
|
20
|
-
- `/switch <session-id>` switches directly to an existing session.
|
|
21
|
-
- `/attach <session-id>` binds an existing agent session to the current chat or topic.
|
|
22
|
-
- Existing thread metadata is imported on switch/attach, including model, reasoning effort, sandbox mode, and approval policy.
|
|
23
|
-
- Codex session usage is read from local rollout JSONL files, including context-used percent, total input/output tokens, 5h limit remaining, and weekly limit remaining.
|
|
24
|
-
- `/handback` returns a ready-to-run CLI command for continuing in the native agent CLI.
|
|
25
|
-
- `/retry` resends the last prompt for the current chat context.
|
|
26
|
-
- `/queue`, inline run/top/up/down/cancel buttons, `/cancel <queue-id>`, and `/clearqueue` manage queued prompts for a busy chat context.
|
|
27
|
-
- `/queue later <minutes> <prompt>` schedules a prompt for later execution, and `/queue inspect <queue-id>` shows full queue metadata.
|
|
28
|
-
- `/abort`, `/stop`, and the inline Abort button cancel the active agent turn.
|
|
29
|
-
- Busy prompts are queued per chat context instead of being dropped.
|
|
30
|
-
- If the attached thread is currently active in the local agent CLI, chat prompts are queued until that CLI task finishes.
|
|
31
|
-
- Active Codex, Pi, Hermes, OpenClaw, and Claude Code CLI/API turns are mirrored into Telegram, Discord, and Slack with configurable `off`, `status`, `final`, or `full` modes.
|
|
32
|
-
- `/mirror` controls CLI mirroring per chat context.
|
|
33
|
-
- Queues survive connector restarts and are resumed automatically when the external CLI turn becomes idle.
|
|
34
|
-
- `/notify` controls completion/status notifications and quiet hours per chat context.
|
|
35
|
-
- `/workspaces` lists allowed workspaces and shows workspace guardrail warnings.
|
|
36
|
-
- `/status`, `/health`, and `/version` report connector runtime health from chat adapters.
|
|
37
|
-
- `/tasks` and `/progress` show the current turn status, queue length, active tool, elapsed time, and last error.
|
|
38
|
-
- `/activity` shows a compact timeline of recent rollout events for the active thread, with filters and export.
|
|
39
|
-
- `/diagnostics` reports redacted runtime, config, user/group authorization, channel rate-limit, mirror, voice, session, queue, and progress details.
|
|
40
|
-
- `/support` exports a redacted diagnostics ZIP with config, health, versions, agent paths, recent logs, audit events, update jobs, state backend, and OS/Node/npm info.
|
|
41
|
-
- `/lock`, `/unlock`, and `/locks` provide a team write-lock for shared sessions so one user can operate while others watch.
|
|
42
|
-
- `/audit` shows recent prompt, queue, lock, command, authentication, permission-denied, user, group, Telegram-link, Telegram-chat, Discord-link, Discord-channel, Slack-link, Slack-channel, and web-session audit events for admins.
|
|
12
|
+
- Node.js 22 or newer.
|
|
13
|
+
- At least one supported coding agent installed and authenticated, for example Codex CLI.
|
|
14
|
+
- A Telegram, Discord, or Slack bot/app token if you want chat access.
|
|
43
15
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
- Telegram supports text, typing, streaming edits, inline buttons, files, photos, voice, forum topics, and polling/webhook transport.
|
|
47
|
-
- Discord supports text, typing, streaming edits, buttons, files, photos, voice/audio transcription, guild channels, threads, DMs, message commands, and slash commands.
|
|
48
|
-
- Slack supports text, typing/status, streaming edits, Block Kit buttons, files, images, audio transcription, channels, DMs, threads, Socket Mode, and HTTP Events mode.
|
|
49
|
-
- Slack startup and `/diagnostics` include readiness checks for token/transport configuration, registered channels, Slack API auth probes, channel visibility probes, file-upload readiness notes, and rate-limit counters.
|
|
50
|
-
- `/channels` shows available and planned messaging adapters for Telegram, Discord, Slack, WhatsApp, and Matrix.
|
|
51
|
-
- Codex, Pi, Hermes, OpenClaw, and Claude Code are implemented as agent adapters.
|
|
52
|
-
- `/agents` shows available/planned agent adapters and whether Codex, Pi, Hermes, OpenClaw, and Claude Code are enabled.
|
|
53
|
-
- Agent and chat adapters expose a shared conformance matrix so command coverage and feature support can be tested and surfaced consistently.
|
|
54
|
-
- Shared command-action renderers and a channel runtime contract keep inbound commands, outbound messages, typing, files, inline actions, and streaming-ready delivery separate from channel-specific API calls.
|
|
55
|
-
|
|
56
|
-
Peer federation:
|
|
57
|
-
|
|
58
|
-
- Optional NordRelay-to-NordRelay pairing lets one instance operate agents on trusted Ubuntu, macOS, Windows, LAN, or remote hosts.
|
|
59
|
-
- Peer serving is disabled by default and uses a dedicated API port separate from the dashboard.
|
|
60
|
-
- Pairing requires an explicit one-time invitation code, Ed25519 node identity verification, a per-peer shared secret, request HMAC signatures, timestamp/nonce replay protection, and TLS fingerprint pinning.
|
|
61
|
-
- Peer scopes restrict which remote WebUI/API actions are allowed, including read, prompt, queue, file, diagnostic, log, and session permissions.
|
|
62
|
-
- Peer records can also restrict allowed agent ids, allowed workspace roots, and per-peer workspace aliases such as `app=/srv/app`.
|
|
63
|
-
- The WebUI has a Peers page plus a local/remote target selector; dashboard pages, SSE streaming, queue actions, artifact downloads, health checks, and the global session browser proxy through the selected peer when allowed.
|
|
64
|
-
- Telegram, Discord, and Slack expose `/peers` and `/target` so a linked user can choose whether prompts run locally or on a paired NordRelay instance.
|
|
65
|
-
- Remote prompts stream text, tool status, turn completion, and errors back to the originating Telegram, Discord, or Slack context.
|
|
66
|
-
|
|
67
|
-
Codex runtime:
|
|
68
|
-
|
|
69
|
-
- Uses `@openai/codex-sdk` to start, resume, and stream Codex threads.
|
|
70
|
-
- Prefers the host `codex` executable on `PATH`, so Codex CLI updates are picked up automatically; the SDK-bundled CLI is used only as fallback.
|
|
71
|
-
- Supports model selection through `/model`, using Codex model cache when available and fallback models otherwise.
|
|
72
|
-
- Supports reasoning effort selection through `/reasoning` and the backward-compatible `/effort` alias: `minimal`, `low`, `medium`, `high`, `xhigh`.
|
|
73
|
-
- Supports launch profiles through `/launch_profiles` and `/launch`.
|
|
74
|
-
- Built-in launch profiles include Default, Read Only, Review, and optional Full Access.
|
|
75
|
-
- Custom launch profiles can be configured with `CODEX_LAUNCH_PROFILES_JSON`.
|
|
76
|
-
- Unsafe `danger-full-access` profiles require `ENABLE_UNSAFE_LAUNCH_PROFILES=true` and channel confirmation.
|
|
77
|
-
- Review or unsafe launch profiles require an inline channel approval before each prompt is executed.
|
|
78
|
-
- Fast mode can be toggled with `/fast` and mirrors Codex's `fast_default_opt_out` setting from `~/.codex/config.toml`.
|
|
79
|
-
- Active chat sessions periodically sync model, reasoning, workspace, launch metadata, and fast-mode defaults from local agent state where supported.
|
|
80
|
-
- Active local Codex CLI tasks are detected from rollout JSONL files so chat adapters do not race the CLI on the same thread.
|
|
81
|
-
- `/diagnostics` includes rollout path, activity status, stale/idle reason, line count, and last update time.
|
|
82
|
-
- Optional per-turn token usage footer with `SHOW_TURN_TOKEN_USAGE=true`.
|
|
83
|
-
|
|
84
|
-
Pi runtime:
|
|
85
|
-
|
|
86
|
-
- Pi support is opt-in with `NORDRELAY_PI_ENABLED=true`.
|
|
87
|
-
- The default chat agent is selected with `NORDRELAY_DEFAULT_AGENT=codex`, `pi`, `hermes`, `openclaw`, or `claude-code`.
|
|
88
|
-
- Pi sessions are driven through official `pi --mode rpc` JSONL commands and events.
|
|
89
|
-
- Existing Pi sessions are discovered from `~/.pi/agent/sessions/` or `PI_SESSION_DIR`.
|
|
90
|
-
- `/sessions`, `/switch`, `/attach`, `/new`, `/session`, `/handback`, `/model`, `/reasoning`, `/abort`, `/stop`, `/retry`, `/queue`, files, photos, and voice input work for Pi contexts.
|
|
91
|
-
- Pi model selection uses `pi --list-models` and sends `set_model` through RPC for active sessions.
|
|
92
|
-
- Pi thinking levels use `/reasoning` and support `off`, `minimal`, `low`, `medium`, `high`, and `xhigh`.
|
|
93
|
-
- Pi token and context stats are read through `get_session_stats` when an RPC session is active.
|
|
94
|
-
- Pi launch profiles expose CLI safety modes such as default, read-only tools, no tools, offline, and safe offline.
|
|
95
|
-
- Pi external CLI activity is detected from Pi session JSONL files so chat/WebUI prompts queue while the same Pi session is busy.
|
|
96
|
-
- Pi CLI turns can be mirrored into chat adapters and the WebUI with status, tool activity, final answers, activity timelines, diagnostics, and generated artifact discovery.
|
|
97
|
-
- Pi provider auth checks report the environment variables expected for the selected provider.
|
|
98
|
-
- Codex-only subscription limit percentages remain Codex-specific; Pi reports token/context stats when available.
|
|
99
|
-
|
|
100
|
-
Hermes runtime:
|
|
101
|
-
|
|
102
|
-
- Hermes support is opt-in with `NORDRELAY_HERMES_ENABLED=true`.
|
|
103
|
-
- The default chat agent can be set with `NORDRELAY_DEFAULT_AGENT=hermes`.
|
|
104
|
-
- Hermes turns are executed through the Hermes API Server `/v1/runs` endpoint and streamed through `/v1/runs/{run_id}/events`.
|
|
105
|
-
- `/abort` and `/stop` use the Hermes run stop endpoint when a NordRelay-started Hermes run is active.
|
|
106
|
-
- Existing Hermes sessions are discovered from `~/.hermes/state.db`, or from `HERMES_STATE_DB_PATH` when configured.
|
|
107
|
-
- `/sessions`, `/switch`, `/attach`, `/new`, `/session`, `/handback`, `/model`, `/reasoning`, `/abort`, `/stop`, `/retry`, `/queue`, files, photos, and voice input work for Hermes contexts.
|
|
108
|
-
- Hermes model selection uses `/v1/models` when the API Server is reachable and falls back to the selected/default model.
|
|
109
|
-
- Hermes reasoning uses `/reasoning` and supports `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`.
|
|
110
|
-
- Hermes launch profiles include `default`, `safe`, `readonly`, and `yolo`; profiles map to run instructions and Hermes approval responses.
|
|
111
|
-
- Hermes external activity is detected from `state.db`, so chat/WebUI prompts queue while the same Hermes session has an unfinished CLI turn.
|
|
112
|
-
- Hermes CLI/API turns can be mirrored into chat adapters and the WebUI with status, tool activity, final answers, activity timelines, diagnostics, and generated artifact discovery.
|
|
113
|
-
- `/auth` checks that the Hermes API Server is reachable and that `HERMES_API_KEY` is usable when configured.
|
|
114
|
-
|
|
115
|
-
OpenClaw runtime:
|
|
116
|
-
|
|
117
|
-
- OpenClaw support is opt-in with `NORDRELAY_OPENCLAW_ENABLED=true`.
|
|
118
|
-
- The default chat agent can be set with `NORDRELAY_DEFAULT_AGENT=openclaw`.
|
|
119
|
-
- OpenClaw turns are executed through the OpenClaw Gateway WebSocket RPC endpoint configured by `OPENCLAW_GATEWAY_URL`.
|
|
120
|
-
- `/abort` and `/stop` call the OpenClaw Gateway cancel method when a NordRelay-started OpenClaw run is active.
|
|
121
|
-
- Existing OpenClaw sessions are discovered from `openclaw sessions --all-agents --json`, or from the state directory configured with `OPENCLAW_HOME` or `OPENCLAW_STATE_DIR`.
|
|
122
|
-
- `/sessions`, `/switch`, `/attach`, `/new`, `/session`, `/handback`, `/model`, `/reasoning`, `/abort`, `/stop`, `/retry`, `/queue`, files, photos, and voice input work for OpenClaw contexts.
|
|
123
|
-
- OpenClaw model selection uses the Gateway `models.list` method when reachable and falls back to `openclaw models list --json`.
|
|
124
|
-
- OpenClaw thinking uses `/reasoning` and supports `off`, `minimal`, `low`, `medium`, `high`, and `xhigh`.
|
|
125
|
-
- OpenClaw launch profiles include `default`, `safe`, `readonly`, `local`, and `deliver`; profiles map to Gateway run flags and additional instructions.
|
|
126
|
-
- OpenClaw external activity is detected from OpenClaw session state, so chat/WebUI prompts queue while the same OpenClaw session has an unfinished CLI turn.
|
|
127
|
-
- OpenClaw Gateway turns can be mirrored into chat adapters and the WebUI with status, tool activity, final answers, activity timelines, diagnostics, and generated artifact discovery.
|
|
128
|
-
- `/auth` checks that the OpenClaw Gateway is reachable and that `OPENCLAW_GATEWAY_TOKEN` or `OPENCLAW_GATEWAY_PASSWORD` is usable when configured.
|
|
129
|
-
|
|
130
|
-
Claude Code runtime:
|
|
131
|
-
|
|
132
|
-
- Claude Code support is opt-in with `NORDRELAY_CLAUDE_CODE_ENABLED=true`.
|
|
133
|
-
- The default chat agent can be set with `NORDRELAY_DEFAULT_AGENT=claude-code`.
|
|
134
|
-
- Claude Code turns are executed through `@anthropic-ai/claude-agent-sdk`, using the host `claude` executable when available and the SDK bundled runtime otherwise.
|
|
135
|
-
- Existing Claude Code sessions are discovered from `~/.claude/projects/`, or from `CLAUDE_CONFIG_DIR/projects` when configured.
|
|
136
|
-
- `/sessions`, `/switch`, `/attach`, `/new`, `/session`, `/handback`, `/model`, `/reasoning`, `/abort`, `/stop`, `/retry`, `/queue`, files, photos, and voice input work for Claude Code contexts.
|
|
137
|
-
- Claude Code model selection exposes common aliases and model ids; explicit values from existing sessions are preserved.
|
|
138
|
-
- Claude Code effort uses `/reasoning` and supports `off`, `low`, `medium`, `high`, and `xhigh`.
|
|
139
|
-
- Claude Code launch profiles include `default`, `accept-edits`, `plan`, `readonly`, `no-tools`, and optional `bypass-permissions`.
|
|
140
|
-
- Claude Code external activity is detected from transcript JSONL files, so chat/WebUI prompts queue while the same Claude Code session has an unfinished CLI turn.
|
|
141
|
-
- Claude Code SDK turns can be mirrored into chat adapters and the WebUI with status, tool activity, final answers, activity timelines, diagnostics, and generated artifact discovery.
|
|
142
|
-
- `/auth` checks the host Claude Code CLI auth state when `claude auth status` is available.
|
|
143
|
-
|
|
144
|
-
Telegram input:
|
|
145
|
-
|
|
146
|
-
- Plain text messages become prompts for the selected agent.
|
|
147
|
-
- Voice and audio messages are transcribed before being sent to the selected agent.
|
|
148
|
-
- Voice transcription uses local `faster-whisper` on Linux, local `parakeet-coreml` on macOS Apple Silicon, or OpenAI Whisper when `OPENAI_API_KEY` is set.
|
|
149
|
-
- `/voice` can select backend preference, language, and transcribe-only mode.
|
|
150
|
-
- Photo messages are passed to the selected agent as local image input when supported.
|
|
151
|
-
- Document messages are downloaded, sanitized, size-checked, and staged under `.nordrelay/inbox/<turn-id>/`.
|
|
152
|
-
- Telegram media groups and albums are combined into one agent turn with all photos and documents staged together.
|
|
153
|
-
- Uploaded documents include prompt instructions telling the selected agent where files were staged.
|
|
154
|
-
- Staged document and photo prompts are persisted so `/retry` and queued execution can replay them after a restart.
|
|
155
|
-
- Telegram forum topics are treated as separate work contexts.
|
|
156
|
-
|
|
157
|
-
Telegram output:
|
|
158
|
-
|
|
159
|
-
- Assistant replies stream back to Telegram with debounced message edits.
|
|
160
|
-
- Telegram `typing` status is sent while the selected agent is working.
|
|
161
|
-
- Markdown is converted to Telegram HTML where possible, with fallback to plain text.
|
|
162
|
-
- Long replies are split to respect Telegram message limits.
|
|
163
|
-
- Tool activity can be displayed as summary, full output, errors only, or hidden with `TOOL_VERBOSITY`.
|
|
164
|
-
- Command execution, web search, file changes, MCP tool calls, error items, and todo-list updates are surfaced.
|
|
165
|
-
- Todo-list updates are rendered as a live plan/status message.
|
|
166
|
-
- Generated artifacts from `.nordrelay/turns/<turn-id>/out/` are retained for manual retrieval with `/artifacts`.
|
|
167
|
-
- Workspace files detected after mirrored Codex, Pi, Hermes, OpenClaw, or Claude Code CLI/API turns are indexed as `/artifacts` entries, even when automatic artifact delivery is disabled.
|
|
168
|
-
- Automatic artifact summaries and file uploads are disabled by default; set `TELEGRAM_AUTO_SEND_ARTIFACTS=true` to send them after turns.
|
|
169
|
-
- Workspace artifact detection sorts by modification time and supports configurable ignored directories and globs.
|
|
170
|
-
- Image artifacts are sent with Telegram previews; large multi-file outputs are bundled into one ZIP when possible.
|
|
171
|
-
- `/artifacts` lists recent generated files and can resend the latest or a specific artifact turn.
|
|
172
|
-
- `/artifacts` includes inline actions to resend, ZIP, or delete artifact turns.
|
|
173
|
-
- `/artifacts images`, `/artifacts docs`, `/artifacts search <text>`, and `/artifacts delete <turn-id>` filter, find, and clean up artifacts from Telegram.
|
|
174
|
-
- Old artifact and inbox turn directories are pruned automatically with configurable retention.
|
|
175
|
-
- Optional Telegram message reactions can acknowledge work start and completion with `ENABLE_TELEGRAM_REACTIONS=true`.
|
|
176
|
-
|
|
177
|
-
Discord input and output:
|
|
178
|
-
|
|
179
|
-
- Enable Discord with `DISCORD_ENABLED=true` and `DISCORD_BOT_TOKEN`. If a requested chat adapter is missing its token, NordRelay disables that adapter and keeps running as long as another chat adapter is usable.
|
|
180
|
-
- Set `DISCORD_CLIENT_ID` to let NordRelay register slash commands automatically.
|
|
181
|
-
- `DISCORD_COMMAND_MODE=both` supports slash commands and `/command` text messages. Set it to `slash` if the bot should not read message commands.
|
|
182
|
-
- `DISCORD_MESSAGE_CONTENT_ENABLED=true` lets regular Discord messages become prompts. The matching privileged intent must also be enabled in the Discord Developer Portal.
|
|
183
|
-
- Discord DMs, guild channels, and threads get independent NordRelay contexts.
|
|
184
|
-
- Discord attachments are staged like Telegram uploads; images are passed as image inputs and audio files are transcribed before prompting.
|
|
185
|
-
- Discord buttons cover session picks, model/reasoning/launch picks, queue actions, artifact actions, update jobs, and abort where Discord component limits allow.
|
|
186
|
-
- Discord slash commands mirror the Telegram command surface where Discord supports it: `/agent`, `/auth`, `/login`, `/logout`, `/session`, `/sessions`, `/new`, `/switch`, `/attach`, `/handback`, `/workspaces`, `/pin`, `/unpin`, `/pinned`, `/model`, `/reasoning`, `/fast`, `/launch`, `/launch_profiles`, `/queue`, `/stop`, `/retry`, `/sync`, `/progress`, `/activity`, `/audit`, `/artifacts`, `/logs`, `/version`, `/diagnostics`, `/restart`, `/update`, `/lock`, `/unlock`, `/mirror`, `/notify`, `/voice`, `/link`, `/whoami`, and `/register_channel`.
|
|
187
|
-
|
|
188
|
-
Slack input and output:
|
|
189
|
-
|
|
190
|
-
- Enable Slack with `SLACK_ENABLED=true`, `SLACK_BOT_TOKEN`, and `SLACK_APP_TOKEN` for Socket Mode. If Socket Mode is disabled, set `SLACK_SIGNING_SECRET` and expose the Slack HTTP receiver.
|
|
191
|
-
- `SLACK_MESSAGE_CONTENT_ENABLED=true` lets regular Slack messages become prompts. Keep it disabled if you only want slash-command control.
|
|
192
|
-
- Slack DMs, channels, and message threads get independent NordRelay contexts.
|
|
193
|
-
- Slack files are staged like Telegram/Discord uploads; images are passed as image inputs and audio files are transcribed before prompting.
|
|
194
|
-
- Slack Block Kit buttons cover session picks, model/reasoning/launch picks, queue actions, artifact actions, update jobs, and abort where Slack component limits allow.
|
|
195
|
-
- Slack slash/text commands mirror the shared command surface where Slack supports it: `/agent`, `/auth`, `/login`, `/logout`, `/session`, `/sessions`, `/new`, `/switch`, `/attach`, `/handback`, `/workspaces`, `/pin`, `/unpin`, `/pinned`, `/model`, `/reasoning`, `/fast`, `/launch`, `/launch_profiles`, `/queue`, `/stop`, `/retry`, `/sync`, `/progress`, `/activity`, `/audit`, `/artifacts`, `/logs`, `/version`, `/diagnostics`, `/restart`, `/update`, `/lock`, `/unlock`, `/mirror`, `/notify`, `/voice`, `/link`, `/whoami`, and `/register_channel`.
|
|
196
|
-
|
|
197
|
-
Authentication and safety:
|
|
198
|
-
|
|
199
|
-
- WebUI login is required for every dashboard page, API route, SSE stream, artifact download, and health endpoint.
|
|
200
|
-
- Access is managed through NordRelay users, groups, permissions, web sessions, linked Telegram identities, linked Discord identities, and linked Slack identities.
|
|
201
|
-
- Built-in groups are `Admin`, `User`, and `Read Only`; custom groups can be created in the WebUI and can restrict allowed agents, workspace roots, Telegram chats, Discord channels, and Slack channels.
|
|
202
|
-
- The last active admin cannot be disabled or demoted, and web sessions are revoked when passwords or group memberships change.
|
|
203
|
-
- Admins can review and revoke active WebUI sessions from the Users page.
|
|
204
|
-
- Telegram private chats require a linked active NordRelay user.
|
|
205
|
-
- Telegram group and forum chats must be registered before use; admins can run `/register_chat` in the chat or enable chats in the WebUI.
|
|
206
|
-
- Discord DMs require a linked active NordRelay user.
|
|
207
|
-
- Discord guild channels and threads must be registered before use; admins can run `/register_channel` in the channel or enable channels in the WebUI.
|
|
208
|
-
- Slack DMs require a linked active NordRelay user.
|
|
209
|
-
- Slack channels and threads must be registered before use; admins can run `/register_channel` in the channel or enable channels in the WebUI.
|
|
210
|
-
- `/whoami` shows the linked NordRelay account and groups.
|
|
211
|
-
- `/link <code>` links a Telegram account to a NordRelay user after a link code is created in the WebUI or with `nordrelay user link-code`.
|
|
212
|
-
- `/link <code>` also links a Discord or Slack account when the code was created for that channel.
|
|
213
|
-
- WebUI login and chat-account link attempts are rate-limited to reduce brute-force risk.
|
|
214
|
-
- User, group, Telegram-link, Telegram-chat, Discord-link, Discord-channel, Slack-link, Slack-channel, web-session, login, and permission-denied events are written to the audit log.
|
|
215
|
-
- `/auth` reports Codex authentication, Pi provider environment health, Hermes API Server reachability, OpenClaw Gateway reachability, or Claude Code CLI auth for the selected agent.
|
|
216
|
-
- `/login` starts Telegram-managed CLI auth for Codex, Hermes, or Claude Code when enabled.
|
|
217
|
-
- `/logout` signs out of CLI auth for Codex, Hermes, or Claude Code; Codex logout is disabled while `CODEX_API_KEY` is in use.
|
|
218
|
-
- `CODEX_API_KEY` can be used for host-side Codex authentication.
|
|
219
|
-
- Friendly error messages are returned for auth, network, model, rate-limit, timeout, and context-length failures.
|
|
220
|
-
- Outgoing Telegram messages and logs redact common token/API-key patterns, with optional custom redaction patterns.
|
|
221
|
-
- Workspace allow/warn roots can prevent accidental operation in the wrong project directory.
|
|
222
|
-
|
|
223
|
-
Operations:
|
|
224
|
-
|
|
225
|
-
- Plugin command/skill starts, stops, restarts, and inspects the connector process.
|
|
226
|
-
- Manual process commands support `start`, `stop`, `restart`, `status`, `update`, and `foreground`.
|
|
227
|
-
- Telegram admin commands support `/logs`, `/diagnostics`, `/support`, `/restart`, and `/update` for NordRelay and agent CLIs.
|
|
228
|
-
- `nordrelay peer identity`, `list`, `invite`, `add`, `test`, and `revoke` manage secure peer federation from the CLI.
|
|
229
|
-
- `nordrelay update`, `/update`, and the WebUI update button detect the install type: npm installs update with `npm install -g @nordbyte/nordrelay@latest`; source checkouts pull `origin/main`, install dependencies, run check, tests, and build, then restart if the connector is running.
|
|
230
|
-
- `/update agents`, `/update <agent>`, `/update install <agent>`, `/update jobs`, `/update log <id>`, `/update cancel <id>`, and `/update input <id> <text>` manage Codex, Pi, Hermes, OpenClaw, and Claude Code updater or installer jobs from Telegram.
|
|
231
|
-
- `/logs` renders redacted connector, NordRelay update, and agent update logs with local-time timestamps, levels, file path, last-modified time, and highlighted warnings/errors.
|
|
232
|
-
- Logs can be emitted as timestamped plain text or JSON records with `CONNECTOR_LOG_FORMAT`.
|
|
233
|
-
- Telegram sends/edits/documents are routed through a rate-limit queue that honors Telegram retry-after responses.
|
|
234
|
-
- Mirror, notification, quiet-hour, and automatic artifact-delivery defaults are configured through channel-neutral `NORDRELAY_*` settings, with Telegram, Discord, and Slack override keys when a channel should differ.
|
|
235
|
-
- The WebUI Tasks page includes a unified Jobs view for active WebUI turns, external CLI turns, queued prompts, agent update/install jobs, self-updates, and diagnostics bundle exports, with log, cancel, and retry actions where supported.
|
|
236
|
-
- Unified Jobs are persisted across restarts and retain recent prompt, queue, update, connector-update, and support-bundle history for WebUI inspection.
|
|
237
|
-
- The WebUI Metrics page reports queue state, active/completed/failed turns, job counts, average prompt duration, and Telegram/Discord/Slack rate-limit counters.
|
|
238
|
-
- Expensive dashboard views such as version checks, adapter health, and diagnostics use a short stale-while-refresh server cache so the UI can render recent data while fresh checks run in the background.
|
|
239
|
-
- Context metadata, queues, and preferences are written atomically with backup recovery.
|
|
240
|
-
- Context metadata, queues, preferences, audit events, and locks can use JSON files or the optional SQLite state backend with `NORDRELAY_STATE_BACKEND=sqlite`.
|
|
241
|
-
- Runtime config, state, and logs are written under `~/.nordrelay/`.
|
|
242
|
-
- `nordrelay init` creates a private runtime config, `nordrelay doctor` validates host prerequisites, and `nordrelay web` starts the connector plus a full local WebUI dashboard.
|
|
243
|
-
- On first WebUI startup without an admin account, NordRelay shows a setup wizard for creating the first admin; remote setup requires the one-time token printed in the server console.
|
|
244
|
-
- The WebUI has responsive header/sidebar/footer navigation, live chat streaming, session controls, queue/artifact/log/diagnostic views, and settings management.
|
|
245
|
-
- The WebUI supports light and dark themes, tabbed settings groups, paginated session browsing, and chat uploads for images, documents, and audio transcription.
|
|
246
|
-
- The WebUI exposes REST and SSE endpoints for chat streaming, sessions, settings, queue, artifacts, logs, health, diagnostics, peers, adapter conformance, and redacted diagnostics bundle export.
|
|
247
|
-
- The dashboard can bind to `127.0.0.1` or `0.0.0.0`; user login and session cookies are mandatory in both modes.
|
|
248
|
-
- Telegram can run with long polling or an HTTP webhook via `TELEGRAM_TRANSPORT=webhook`.
|
|
249
|
-
- Version freshness checks are cached with `NORDRELAY_VERSION_CACHE_TTL_MS`, and installed agent CLI version checks are cached with `NORDRELAY_CLI_VERSION_CACHE_TTL_MS`, to keep `/version` and adapter health responsive.
|
|
250
|
-
- CI runs on Ubuntu, Windows, and macOS with typecheck, Vitest, Playwright WebUI browser tests, package dry run, npm audit, and a separate secret-scan workflow.
|
|
251
|
-
- `npm run dev`, `npm run build`, `npm run check`, `npm test`, `npm run test:e2e`, `npm start`, `npm stop`, and `npm run status` are available.
|
|
252
|
-
- Dockerfile and `docker-compose.yml` are included for containerized operation.
|
|
253
|
-
- A `launchd/start.sh` helper is included for host-managed startup.
|
|
254
|
-
|
|
255
|
-
## First Run Setup
|
|
256
|
-
|
|
257
|
-
Recommended npm setup:
|
|
16
|
+
Install NordRelay globally:
|
|
258
17
|
|
|
259
18
|
```bash
|
|
260
19
|
npm install -g @nordbyte/nordrelay
|
|
261
20
|
nordrelay init
|
|
262
|
-
nordrelay user list
|
|
263
21
|
nordrelay doctor
|
|
264
22
|
nordrelay start
|
|
265
23
|
```
|
|
266
24
|
|
|
267
|
-
|
|
268
|
-
If you start `nordrelay web` before creating an admin, the dashboard opens a first-run setup wizard. Remote setup requires the one-time setup token printed in the NordRelay console.
|
|
269
|
-
|
|
270
|
-
Non-interactive setup is also supported:
|
|
25
|
+
Open the dashboard:
|
|
271
26
|
|
|
272
27
|
```bash
|
|
273
|
-
nordrelay
|
|
274
|
-
--token 123456789:replace-me \
|
|
275
|
-
--enable-discord \
|
|
276
|
-
--discord-token "discord-bot-token" \
|
|
277
|
-
--discord-client-id "discord-client-id" \
|
|
278
|
-
--admin-email you@example.com \
|
|
279
|
-
--admin-name "Your Name" \
|
|
280
|
-
--admin-password "replace-with-a-long-password" \
|
|
281
|
-
--telegram-user-id 123456789
|
|
28
|
+
nordrelay web
|
|
282
29
|
```
|
|
283
30
|
|
|
284
|
-
|
|
285
|
-
Use `--discord-user-id <id>` with `nordrelay user create-admin` or `nordrelay user link-discord` to link Discord directly.
|
|
31
|
+
The dashboard is available at the URL printed by the command, usually:
|
|
286
32
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
Install dependencies and build the runtime:
|
|
290
|
-
|
|
291
|
-
```bash
|
|
292
|
-
npm install
|
|
293
|
-
npm run build
|
|
294
|
-
mkdir -p ~/.nordrelay
|
|
295
|
-
cp .env.example ~/.nordrelay/nordrelay.env
|
|
296
|
-
chmod 600 ~/.nordrelay/nordrelay.env
|
|
33
|
+
```text
|
|
34
|
+
http://127.0.0.1:31878/
|
|
297
35
|
```
|
|
298
36
|
|
|
299
|
-
|
|
37
|
+
On first WebUI startup, create the first admin user. After that, every dashboard page and chat adapter action is controlled by NordRelay users, groups, linked Telegram/Discord/Slack accounts, and registered channels.
|
|
300
38
|
|
|
301
|
-
|
|
302
|
-
2. Run `/newbot`.
|
|
303
|
-
3. Choose a display name and bot username.
|
|
304
|
-
4. Copy the bot token into `TELEGRAM_BOT_TOKEN` in `~/.nordrelay/nordrelay.env`.
|
|
305
|
-
5. Create the first admin user with `nordrelay init` or `nordrelay user create-admin`.
|
|
306
|
-
6. Link Telegram from the WebUI, with `nordrelay user link-telegram`, or by creating a link code and sending `/link <code>` to the bot.
|
|
39
|
+
## Minimal Setup
|
|
307
40
|
|
|
308
|
-
|
|
41
|
+
The recommended setup path is interactive:
|
|
309
42
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
7. In guild channels, run `/register_channel` once from an admin-linked Discord account.
|
|
43
|
+
```bash
|
|
44
|
+
nordrelay init
|
|
45
|
+
nordrelay user list
|
|
46
|
+
nordrelay doctor
|
|
47
|
+
nordrelay start
|
|
48
|
+
```
|
|
317
49
|
|
|
318
|
-
|
|
50
|
+
`nordrelay init` writes private runtime config to:
|
|
319
51
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
4. Add bot scopes for messages, files, channels, groups, IMs, MPIMs, commands, and chat write access.
|
|
324
|
-
5. Create the slash command configured in `SLACK_COMMAND` (default `/nordrelay`) and install the app to your workspace.
|
|
325
|
-
6. Link Slack from the WebUI, with `nordrelay user link-slack`, or by creating a Slack link code and sending `/link <code>` to the app.
|
|
326
|
-
7. In Slack channels, run `/register_channel` once from an admin-linked Slack account.
|
|
52
|
+
```text
|
|
53
|
+
~/.nordrelay/nordrelay.env
|
|
54
|
+
```
|
|
327
55
|
|
|
328
|
-
|
|
56
|
+
A minimal Telegram + Codex configuration looks like this:
|
|
329
57
|
|
|
330
58
|
```dotenv
|
|
59
|
+
TELEGRAM_ENABLED=true
|
|
331
60
|
TELEGRAM_BOT_TOKEN=123456789:replace-me
|
|
332
61
|
DISCORD_ENABLED=false
|
|
333
|
-
DISCORD_BOT_TOKEN=
|
|
334
|
-
DISCORD_CLIENT_ID=
|
|
335
62
|
SLACK_ENABLED=false
|
|
336
|
-
SLACK_BOT_TOKEN=
|
|
337
|
-
SLACK_APP_TOKEN=
|
|
338
63
|
NORDRELAY_CODEX_ENABLED=true
|
|
339
|
-
NORDRELAY_PI_ENABLED=false
|
|
340
|
-
NORDRELAY_HERMES_ENABLED=false
|
|
341
|
-
NORDRELAY_OPENCLAW_ENABLED=false
|
|
342
|
-
NORDRELAY_CLAUDE_CODE_ENABLED=false
|
|
343
64
|
NORDRELAY_DEFAULT_AGENT=codex
|
|
344
65
|
CODEX_SANDBOX_MODE=workspace-write
|
|
345
66
|
CODEX_APPROVAL_POLICY=never
|
|
346
67
|
```
|
|
347
68
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
- `nordrelay init` creates the first admin user and writes `~/.nordrelay/users.json`.
|
|
351
|
-
- `nordrelay user create-admin --email you@example.com --name "Your Name"` creates another admin.
|
|
352
|
-
- `nordrelay user create --email dev@example.com --name "Dev" --group user` creates a normal user.
|
|
353
|
-
- `nordrelay user link-telegram --email you@example.com --telegram-user-id 123456789` links a Telegram account directly.
|
|
354
|
-
- `nordrelay user link-discord --email you@example.com --discord-user-id 123456789012345678` links a Discord account directly.
|
|
355
|
-
- `nordrelay user link-slack --email you@example.com --slack-user-id U123 --slack-team-id T123` links a Slack account directly.
|
|
356
|
-
- `nordrelay user link-code --email you@example.com` creates a short-lived Telegram code that the user sends as `/link <code>` to the Telegram bot.
|
|
357
|
-
- `nordrelay user discord-link-code --email you@example.com` creates a short-lived Discord code that the user sends as `/link <code>` to the Discord bot.
|
|
358
|
-
- `nordrelay user slack-link-code --email you@example.com` creates a short-lived Slack code that the user sends as `/link <code>` to the Slack app.
|
|
359
|
-
- Telegram group chats are disabled until an admin enables them from the WebUI or runs `/register_chat` inside the group.
|
|
360
|
-
- Discord guild channels are disabled until an admin enables them from the WebUI or runs `/register_channel` inside the channel.
|
|
361
|
-
- Slack channels are disabled until an admin enables them from the WebUI or runs `/register_channel` inside the channel.
|
|
362
|
-
|
|
363
|
-
Peer setup:
|
|
364
|
-
|
|
365
|
-
1. On each host that should accept peer connections, set `NORDRELAY_PEER_ENABLED=true` in `~/.nordrelay/nordrelay.env`.
|
|
366
|
-
2. Keep `NORDRELAY_PEER_TLS_ENABLED=true` and `NORDRELAY_PEER_REQUIRE_TLS=true` for LAN or internet use.
|
|
367
|
-
3. Use `NORDRELAY_PEER_HOST=127.0.0.1` for local-only testing, a LAN/interface IP for trusted local networks, or keep the peer API behind a TLS reverse proxy/VPN for internet access.
|
|
368
|
-
4. Set `NORDRELAY_PEER_PUBLIC_URL=https://host.example:31979` when other hosts cannot reach the bind address directly.
|
|
369
|
-
5. Restart NordRelay on the accepting host and create an invitation:
|
|
370
|
-
|
|
371
|
-
```bash
|
|
372
|
-
nordrelay peer invite --name workstation --scopes inspect,sessions.read,sessions.write,prompt.send,prompt.abort,queue.read,queue.write,files.read,files.write,diagnostics.read,logs.read
|
|
373
|
-
```
|
|
374
|
-
|
|
375
|
-
6. On the controlling host, run the printed command:
|
|
376
|
-
|
|
377
|
-
```bash
|
|
378
|
-
nordrelay peer add https://workstation.example:31979 --code one-time-code
|
|
379
|
-
```
|
|
380
|
-
|
|
381
|
-
7. Confirm the connection:
|
|
382
|
-
|
|
383
|
-
```bash
|
|
384
|
-
nordrelay peer list
|
|
385
|
-
nordrelay peer test <peer-id>
|
|
386
|
-
```
|
|
387
|
-
|
|
388
|
-
Use `--workspace-aliases app=/srv/app,demo=/home/me/demo` on invites when a controller should be able to start remote sessions with short workspace names. Use the WebUI Peers page for the same invite, pair, enable/disable, test, alias, global-session, and revoke workflow. Use `/peers` from Telegram, Discord, or Slack to inspect paired nodes and `/target <peer-id>` or `/target local` to choose where subsequent prompts run.
|
|
389
|
-
|
|
390
|
-
Codex authentication:
|
|
391
|
-
|
|
392
|
-
- Preferred local setup: run `codex login` on the host before starting the connector.
|
|
393
|
-
- Remote setup: use `/auth` and `/login` in Telegram if `ENABLE_TELEGRAM_LOGIN=true`.
|
|
394
|
-
- API-key setup: set `CODEX_API_KEY`; `/logout` is disabled while `CODEX_API_KEY` is in use.
|
|
395
|
-
|
|
396
|
-
Pi setup:
|
|
397
|
-
|
|
398
|
-
- Install Pi from https://pi.dev/ and confirm `pi --help` works on the host.
|
|
399
|
-
- npm installs should use the current package name: `npm install -g @earendil-works/pi-coding-agent`.
|
|
400
|
-
- Set `NORDRELAY_PI_ENABLED=true` in `~/.nordrelay/nordrelay.env`.
|
|
401
|
-
- Keep `NORDRELAY_DEFAULT_AGENT=codex` to start chats in Codex, or set `NORDRELAY_DEFAULT_AGENT=pi` to start chats in Pi.
|
|
402
|
-
- Optional: set `PI_SESSION_DIR` if your Pi sessions are not stored in `~/.pi/agent/sessions/`.
|
|
403
|
-
- Optional: set `PI_DEFAULT_MODEL=openai-codex/gpt-5.5` and `PI_DEFAULT_THINKING=medium`.
|
|
404
|
-
|
|
405
|
-
Hermes setup:
|
|
406
|
-
|
|
407
|
-
- Install Hermes Agent and confirm `hermes --help` works on the host.
|
|
408
|
-
- Start the Hermes API Server locally and confirm `GET http://127.0.0.1:8642/health` returns OK.
|
|
409
|
-
- Set `NORDRELAY_HERMES_ENABLED=true` in `~/.nordrelay/nordrelay.env`.
|
|
410
|
-
- Keep `NORDRELAY_DEFAULT_AGENT=codex` to start chats in Codex, or set `NORDRELAY_DEFAULT_AGENT=hermes` to start chats in Hermes.
|
|
411
|
-
- Set `HERMES_API_BASE_URL` if the API Server is not listening on `http://127.0.0.1:8642`.
|
|
412
|
-
- Set `HERMES_API_KEY` when the Hermes API Server is protected with `API_SERVER_KEY`.
|
|
413
|
-
- Optional: use `/login` or run `hermes login --no-browser` on the host to refresh Hermes provider credentials.
|
|
414
|
-
- Optional: set `HERMES_STATE_DB_PATH` if your Hermes session database is not stored at `~/.hermes/state.db`.
|
|
415
|
-
- Optional: set `HERMES_DEFAULT_MODEL`, `HERMES_DEFAULT_REASONING`, and `HERMES_DEFAULT_PROFILE`.
|
|
416
|
-
|
|
417
|
-
OpenClaw setup:
|
|
418
|
-
|
|
419
|
-
- Install OpenClaw and confirm `openclaw --help` works on the host.
|
|
420
|
-
- Start the OpenClaw Gateway and confirm the WebSocket endpoint is reachable.
|
|
421
|
-
- Set `NORDRELAY_OPENCLAW_ENABLED=true` in `~/.nordrelay/nordrelay.env`.
|
|
422
|
-
- Keep `NORDRELAY_DEFAULT_AGENT=codex` to start chats in Codex, or set `NORDRELAY_DEFAULT_AGENT=openclaw` to start chats in OpenClaw.
|
|
423
|
-
- Set `OPENCLAW_GATEWAY_URL` if the Gateway is not listening on `ws://127.0.0.1:18789`.
|
|
424
|
-
- Set `OPENCLAW_GATEWAY_TOKEN` or `OPENCLAW_GATEWAY_PASSWORD` when the Gateway requires shared-secret auth.
|
|
425
|
-
- Optional: set `OPENCLAW_AGENT_ID` if you want a specific OpenClaw agent instead of `main`.
|
|
426
|
-
- Optional: set `OPENCLAW_HOME` or `OPENCLAW_STATE_DIR` if your OpenClaw session state is stored outside `~/.openclaw`.
|
|
427
|
-
- Optional: set `OPENCLAW_DEFAULT_MODEL`, `OPENCLAW_DEFAULT_THINKING`, and `OPENCLAW_DEFAULT_PROFILE`.
|
|
428
|
-
|
|
429
|
-
Claude Code setup:
|
|
430
|
-
|
|
431
|
-
- Install Claude Code and confirm `claude --help` works on the host, or use the SDK bundled runtime.
|
|
432
|
-
- Use `/login` or run `claude auth login` on the host when your Claude Code installation requires local auth.
|
|
433
|
-
- Set `NORDRELAY_CLAUDE_CODE_ENABLED=true` in `~/.nordrelay/nordrelay.env`.
|
|
434
|
-
- Keep `NORDRELAY_DEFAULT_AGENT=codex` to start chats in Codex, or set `NORDRELAY_DEFAULT_AGENT=claude-code` to start chats in Claude Code.
|
|
435
|
-
- Optional: set `CLAUDE_CODE_CLI_PATH` if `claude` is not on `PATH`.
|
|
436
|
-
- Optional: set `CLAUDE_CONFIG_DIR` if your Claude Code sessions are not stored under `~/.claude`.
|
|
437
|
-
- Optional: set `CLAUDE_CODE_DEFAULT_MODEL`, `CLAUDE_CODE_DEFAULT_EFFORT`, `CLAUDE_CODE_DEFAULT_PROFILE`, and `CLAUDE_CODE_MAX_TURNS`.
|
|
438
|
-
|
|
439
|
-
Register the local Codex marketplace:
|
|
440
|
-
|
|
441
|
-
```bash
|
|
442
|
-
codex plugin marketplace add ~/projects/nordrelay
|
|
443
|
-
```
|
|
444
|
-
|
|
445
|
-
An example local marketplace entry is available at `docs/nordrelay-marketplace.example.json`. Keep personal `.agents/` marketplace files outside the public repo.
|
|
446
|
-
|
|
447
|
-
## Running
|
|
448
|
-
|
|
449
|
-
From Codex, ask:
|
|
450
|
-
|
|
451
|
-
```text
|
|
452
|
-
Starte Telegram Remote
|
|
453
|
-
```
|
|
454
|
-
|
|
455
|
-
Where Codex exposes namespaced plugin commands, this also works:
|
|
69
|
+
For guided setup in the browser, open the WebUI, go to **Settings**, then use **Setup wizard** for Telegram, Discord, or Slack.
|
|
456
70
|
|
|
457
|
-
|
|
458
|
-
/nordrelay:remote
|
|
459
|
-
```
|
|
71
|
+
## Common Commands
|
|
460
72
|
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
Manual process commands:
|
|
73
|
+
CLI:
|
|
464
74
|
|
|
465
75
|
```bash
|
|
466
|
-
nordrelay init
|
|
467
|
-
nordrelay doctor
|
|
468
|
-
nordrelay start
|
|
469
76
|
nordrelay status
|
|
470
|
-
nordrelay
|
|
471
|
-
nordrelay restart
|
|
472
|
-
nordrelay stop
|
|
473
|
-
nordrelay foreground
|
|
474
|
-
nordrelay web
|
|
475
|
-
nordrelay peer list
|
|
476
|
-
nordrelay peer invite
|
|
477
|
-
nordrelay peer add https://peer.example:31979 --code one-time-code
|
|
478
|
-
```
|
|
479
|
-
|
|
480
|
-
Source checkout process commands:
|
|
481
|
-
|
|
482
|
-
```bash
|
|
483
|
-
node plugins/nordrelay/scripts/nordrelay.mjs start
|
|
484
|
-
node plugins/nordrelay/scripts/nordrelay.mjs status
|
|
485
|
-
node plugins/nordrelay/scripts/nordrelay.mjs update
|
|
486
|
-
node plugins/nordrelay/scripts/nordrelay.mjs restart
|
|
487
|
-
node plugins/nordrelay/scripts/nordrelay.mjs stop
|
|
488
|
-
node plugins/nordrelay/scripts/nordrelay.mjs foreground
|
|
489
|
-
node plugins/nordrelay/scripts/nordrelay.mjs user list
|
|
490
|
-
node plugins/nordrelay/scripts/nordrelay.mjs doctor
|
|
491
|
-
node plugins/nordrelay/scripts/nordrelay.mjs web
|
|
492
|
-
node plugins/nordrelay/scripts/nordrelay.mjs peer list
|
|
493
|
-
```
|
|
494
|
-
|
|
495
|
-
NPM shortcuts:
|
|
496
|
-
|
|
497
|
-
```bash
|
|
498
|
-
npm start
|
|
499
|
-
npm run status
|
|
500
|
-
npm stop
|
|
501
|
-
npm run foreground
|
|
502
|
-
```
|
|
503
|
-
|
|
504
|
-
Runtime files:
|
|
505
|
-
|
|
506
|
-
- PID file: `~/.nordrelay/nordrelay.pid`
|
|
507
|
-
- State file: `~/.nordrelay/state.json`
|
|
508
|
-
- Log file: `~/.nordrelay/nordrelay.log`
|
|
509
|
-
- Home override: `NORDRELAY_HOME=/custom/path`
|
|
510
|
-
- Local dashboard: `nordrelay web --host 127.0.0.1 --port 31878`
|
|
511
|
-
- `nordrelay start` and `nordrelay status` print the configured WebUI URL.
|
|
512
|
-
|
|
513
|
-
## WebUI Dashboard
|
|
514
|
-
|
|
515
|
-
Start the local WebUI:
|
|
516
|
-
|
|
517
|
-
```bash
|
|
77
|
+
nordrelay doctor
|
|
518
78
|
nordrelay web
|
|
79
|
+
nordrelay restart
|
|
80
|
+
nordrelay update
|
|
519
81
|
```
|
|
520
82
|
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
Open:
|
|
524
|
-
|
|
525
|
-
```text
|
|
526
|
-
http://127.0.0.1:31878/
|
|
527
|
-
```
|
|
528
|
-
|
|
529
|
-
The dashboard is a second NordRelay client next to Telegram. It can:
|
|
530
|
-
|
|
531
|
-
- Start a new Codex, Pi, Hermes, OpenClaw, or Claude Code session.
|
|
532
|
-
- Start a new session from a modal with agent, workspace, model, reasoning/thinking, fast mode, and launch-profile choices.
|
|
533
|
-
- Switch or attach existing sessions, and copy thread IDs from the session list.
|
|
534
|
-
- Send prompts and receive streamed text/tool/plan updates through Server-Sent Events.
|
|
535
|
-
- Upload images, documents, and audio files from the chat composer. Images are passed as image inputs, documents are staged for the agent, and audio is transcribed through the configured voice backend.
|
|
536
|
-
- Keep a persistent per-thread WebUI chat history across page reloads.
|
|
537
|
-
- Control the active session model, reasoning/thinking, fast mode, and launch profile directly from the chat view.
|
|
538
|
-
- Abort turns, hand sessions back to the native CLI, and inspect the active session.
|
|
539
|
-
- Manage queued prompts with pause/resume, run, cancel, reorder buttons, and drag-and-drop prioritization.
|
|
540
|
-
- Inspect unified jobs across queued prompts, active turns, mirrored CLI work, agent updates, self-updates, and support-bundle exports.
|
|
541
|
-
- Browse, preview, download, ZIP, and delete artifacts.
|
|
542
|
-
- Inspect the activity timeline for WebUI and mirrored CLI turns.
|
|
543
|
-
- Edit all supported runtime settings from tabbed Settings groups with option selects, validation feedback, and restart actions.
|
|
544
|
-
- View filtered connector/update/agent-update logs, structured diagnostics, enabled channels, and agent adapters.
|
|
545
|
-
- Inspect a per-agent capability matrix showing model, reasoning, launch, fast mode, attachments, activity, usage, auth, login/logout, and handback support.
|
|
546
|
-
- Check NordRelay and agent CLI versions, then start Codex, Pi, Hermes, OpenClaw, or Claude Code updates from outdated rows or installs from not-installed rows with live output, cancel, delete-log, and stdin response controls.
|
|
547
|
-
- Build dashboard CSS and client JavaScript from modular source assets through esbuild, then serve them as authenticated static assets instead of inline HTML.
|
|
548
|
-
- Pair, test, enable/disable, and revoke NordRelay peers, then switch the dashboard target between the local instance and paired remote instances.
|
|
549
|
-
|
|
550
|
-
Dashboard API endpoints are served under `/api/*`. Streaming uses `GET /api/events`.
|
|
551
|
-
|
|
552
|
-
Dashboard auth:
|
|
553
|
-
|
|
554
|
-
```dotenv
|
|
555
|
-
NORDRELAY_DASHBOARD_HOST=127.0.0.1
|
|
556
|
-
NORDRELAY_DASHBOARD_PORT=31878
|
|
557
|
-
```
|
|
558
|
-
|
|
559
|
-
The dashboard always requires NordRelay email/password login. Login cookies use `SameSite=Strict`, and every dashboard route, API endpoint, SSE stream, artifact download, and health endpoint requires an authenticated active user with the matching permission.
|
|
560
|
-
|
|
561
|
-
Webhook mode:
|
|
562
|
-
|
|
563
|
-
```dotenv
|
|
564
|
-
TELEGRAM_TRANSPORT=webhook
|
|
565
|
-
TELEGRAM_WEBHOOK_URL=https://relay.example
|
|
566
|
-
TELEGRAM_WEBHOOK_HOST=127.0.0.1
|
|
567
|
-
TELEGRAM_WEBHOOK_PORT=8080
|
|
568
|
-
TELEGRAM_WEBHOOK_PATH=/telegram/webhook
|
|
569
|
-
TELEGRAM_WEBHOOK_SECRET=replace-with-random-secret
|
|
570
|
-
```
|
|
571
|
-
|
|
572
|
-
Run NordRelay behind your reverse proxy so the public URL forwards to `http://127.0.0.1:8080/telegram/webhook`. Dashboard health checks are available to authenticated WebUI sessions through `/healthz` and `/api/health`.
|
|
573
|
-
|
|
574
|
-
## Telegram Commands
|
|
575
|
-
|
|
576
|
-
- `/start` shows welcome text and the selected launch profile.
|
|
577
|
-
- `/help` shows the grouped command reference.
|
|
578
|
-
- `/channels` shows available and planned messaging adapters.
|
|
579
|
-
- `/agents` shows available and planned coding-agent adapters.
|
|
580
|
-
- `/agent` selects the active agent for this Telegram context.
|
|
581
|
-
- `/peers` shows configured NordRelay peer instances.
|
|
582
|
-
- `/target local|<peer-id>` selects whether prompts for this chat run locally or on a paired peer.
|
|
583
|
-
- `/link <code>` links the Telegram account to a NordRelay user.
|
|
584
|
-
- `/whoami` shows the linked NordRelay user, groups, and permissions.
|
|
585
|
-
- `/register_chat` enables the current Telegram group or forum chat for NordRelay when the linked user has user-management permission.
|
|
586
|
-
- `/new` starts a new thread. If the selected agent knows multiple workspaces, Telegram shows a workspace picker.
|
|
587
|
-
- `/session` shows current thread details.
|
|
588
|
-
- `/sessions` opens a paginated recent-session picker.
|
|
589
|
-
- `/sessions <query>` searches recent sessions.
|
|
590
|
-
- `/sync` syncs the active session from local CLI state when supported.
|
|
591
|
-
- `/pinned` opens a pinned-thread picker.
|
|
592
|
-
- `/pin [thread-id]` pins a thread for this Telegram context; defaults to the active thread.
|
|
593
|
-
- `/unpin [thread-id]` unpins a thread for this Telegram context; defaults to the active thread.
|
|
594
|
-
- `/switch <session-id>` switches directly to a known session.
|
|
595
|
-
- `/attach <session-id>` binds a known session to the current chat or forum topic.
|
|
596
|
-
- `/handback` detaches the active session and prints the native CLI resume command.
|
|
597
|
-
- `/retry` resends the last prompt for this Telegram context.
|
|
598
|
-
- `/queue` shows queued prompts for this Telegram context with inline run/top/up/down/cancel buttons.
|
|
599
|
-
- `/queue pause` pauses automatic queued prompt execution.
|
|
600
|
-
- `/queue resume` resumes automatic queued prompt execution.
|
|
601
|
-
- `/queue later <minutes> <prompt>` schedules a prompt for later execution.
|
|
602
|
-
- `/queue inspect <queue-id>` shows one queued prompt with created time, schedule time, attempts, and last error.
|
|
603
|
-
- `/queue move <queue-id> top|up|down` changes queued prompt priority.
|
|
604
|
-
- `/queue run <queue-id>` resumes the queue and runs that prompt next when the session is idle.
|
|
605
|
-
- Queued prompt replies include a cancel button while the prompt is still waiting.
|
|
606
|
-
- `/cancel <queue-id>` removes one queued prompt; the queue id is the short code shown in messages such as `Queued prompt 332kmt`.
|
|
607
|
-
- `/clearqueue` clears queued prompts for this Telegram context.
|
|
608
|
-
- `/activity [all|tools|errors|user|agent|tasks] [limit] [since 1h] [export]` shows or exports rollout activity for the active thread.
|
|
609
|
-
- `/audit [limit]` shows recent audit events. Requires `audit.read`.
|
|
610
|
-
- `/lock` locks writes for this Telegram session to the current user.
|
|
611
|
-
- `/unlock` releases the current session write lock.
|
|
612
|
-
- `/locks` lists active write locks.
|
|
613
|
-
- `/artifacts [latest|zip latest|turn-id|images|docs|search <text>|delete <turn-id>]` lists, filters, resends, zips, searches, or deletes generated artifacts for the current workspace.
|
|
614
|
-
- `/workspaces` lists workspaces known to the selected agent and allowed by the workspace policy.
|
|
615
|
-
- `/abort` cancels the current operation.
|
|
616
|
-
- `/stop` is an alias for `/abort`.
|
|
617
|
-
- `/launch_profiles` or `/launch` opens the launch profile picker.
|
|
618
|
-
- `/fast [on|off]` toggles Codex fast mode. Without an argument it flips the current state.
|
|
619
|
-
- `/model` opens the model picker.
|
|
620
|
-
- `/reasoning` opens the selected agent's reasoning or thinking picker.
|
|
621
|
-
- `/effort` is a backward-compatible alias for `/reasoning`.
|
|
622
|
-
- `/mirror [off|status|final|full]` controls local CLI mirroring for this Telegram context.
|
|
623
|
-
- `/notify [off|minimal|all]` controls Telegram notifications.
|
|
624
|
-
- `/notify quiet HH-HH` sets quiet hours; `/notify quiet off` disables them.
|
|
625
|
-
- `/auth` reports Codex authentication status, Pi provider environment health, Hermes API Server reachability, OpenClaw Gateway reachability, or Claude Code CLI auth for the selected agent.
|
|
626
|
-
- `/login` starts Telegram-initiated CLI login for Codex, Hermes, or Claude Code when one of those agents is selected.
|
|
627
|
-
- `/logout` signs out from CLI auth for Codex, Hermes, or Claude Code when one of those agents is selected; Codex logout is disabled while `CODEX_API_KEY` is active.
|
|
628
|
-
- `/voice` reports voice transcription backends and current voice preferences.
|
|
629
|
-
- `/voice backend auto|parakeet|faster-whisper|openai` selects backend preference.
|
|
630
|
-
- `/voice language auto|<code>` selects transcription language.
|
|
631
|
-
- `/voice transcribe_only on|off` controls whether voice is only transcribed or also sent to the selected agent.
|
|
632
|
-
- `/tasks` or `/progress` reports the current turn and queue progress.
|
|
633
|
-
- `/status` reports connector runtime status.
|
|
634
|
-
- `/health` reports runtime health, auth, PIDs, Codex CLI, Pi CLI, Hermes CLI, OpenClaw CLI, Claude Code CLI, and state DB.
|
|
635
|
-
- `/version` reports connector, Codex CLI, Pi CLI, Hermes CLI, OpenClaw CLI, and Claude Code CLI paths plus installed/latest NordRelay, Codex, Pi, Hermes, OpenClaw, and Claude Code versions with status icons.
|
|
636
|
-
- `/logs [lines]` shows a redacted, timestamped connector log tail. Requires `logs.read`.
|
|
637
|
-
- `/logs update [lines]` shows the self-update log. Requires `logs.read`.
|
|
638
|
-
- `/logs agent [lines]` shows the aggregate agent updater log. Requires `logs.read`.
|
|
639
|
-
- `/logs all [lines]` shows connector, self-update, and agent update logs together. Requires `logs.read`.
|
|
640
|
-
- `/diagnostics` shows redacted connector diagnostics. Requires `diagnostics.read`.
|
|
641
|
-
- `/support` exports a redacted diagnostics ZIP. Requires `diagnostics.read`.
|
|
642
|
-
- `/restart` restarts the connector process. Requires `system.restart`.
|
|
643
|
-
- `/update` updates through npm or git depending on the detected install type, then restarts only on success. Requires `updates.run`.
|
|
644
|
-
- `/update agents`, `/update <agent>`, `/update install <agent>`, `/update jobs`, `/update log <id>`, `/update cancel <id>`, and `/update input <id> <text>` manage agent CLI update and install jobs. Requires `updates.run`.
|
|
645
|
-
|
|
646
|
-
## Discord Commands
|
|
647
|
-
|
|
648
|
-
Discord supports slash commands and `/command` text messages for the shared command set. The primary differences from Telegram are:
|
|
649
|
-
|
|
650
|
-
- `/register_channel` replaces `/register_chat` for guild channels and threads.
|
|
651
|
-
- `/prompt <text>` is available for slash-command-only deployments where regular message content is disabled.
|
|
652
|
-
- `/link <code>` consumes Discord link codes created in the WebUI or with `nordrelay user discord-link-code`.
|
|
653
|
-
- `/queue`, `/sessions`, `/agent`, `/model`, `/reasoning`, `/launch`, `/artifacts`, `/update`, and `/stop` use Discord buttons where component limits allow.
|
|
654
|
-
- `/peers` and `/target local|<peer-id>` use the same paired-instance target selection as Telegram.
|
|
655
|
-
- `/artifacts latest`, `/artifacts zip latest`, `/artifacts images`, `/artifacts docs`, `/artifacts search <text>`, and `/artifacts delete <turn-id>` are available in Discord.
|
|
656
|
-
- Unsafe launch profiles require explicit confirmation with `/launch <profile-id> confirm`.
|
|
657
|
-
- Discord does not support Telegram reactions or Telegram webhook transport; typing, message edits, attachments, files, DMs, guild channels, and threads are supported.
|
|
658
|
-
|
|
659
|
-
## Slack Commands
|
|
660
|
-
|
|
661
|
-
Slack supports the configured slash command and `/command` text messages for the shared command set. The primary differences from Telegram are:
|
|
662
|
-
|
|
663
|
-
- `/register_channel` enables the current Slack channel or thread for NordRelay when the linked user has user-management permission.
|
|
664
|
-
- `/prompt <text>` is available through the configured slash command when regular message content is disabled.
|
|
665
|
-
- `/link <code>` consumes Slack link codes created in the WebUI or with `nordrelay user slack-link-code`.
|
|
666
|
-
- `/queue`, `/sessions`, `/agent`, `/model`, `/reasoning`, `/launch`, `/artifacts`, `/update`, and `/stop` use Slack buttons where Block Kit limits allow.
|
|
667
|
-
- `/peers` and `/target local|<peer-id>` use the same paired-instance target selection as Telegram and Discord.
|
|
668
|
-
- `/artifacts latest`, `/artifacts zip latest`, `/artifacts images`, `/artifacts docs`, `/artifacts search <text>`, and `/artifacts delete <turn-id>` are available in Slack.
|
|
669
|
-
- Unsafe launch profiles require explicit confirmation with `/launch <profile-id> confirm`.
|
|
670
|
-
- Slack does not support Telegram reactions or Telegram webhook transport; typing/status, message edits, attachments, files, DMs, channels, and threads are supported.
|
|
671
|
-
|
|
672
|
-
## Command Examples
|
|
673
|
-
|
|
674
|
-
Switching to an existing thread:
|
|
83
|
+
Chat adapters share the core command set:
|
|
675
84
|
|
|
676
85
|
```text
|
|
86
|
+
/help
|
|
87
|
+
/session
|
|
677
88
|
/sessions
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
Tap a listed thread/session. The connector imports workspace, model, reasoning/thinking, and provider-specific metadata from the selected agent.
|
|
681
|
-
|
|
682
|
-
Direct session switch:
|
|
683
|
-
|
|
684
|
-
```text
|
|
685
|
-
/switch 019e178a-f275-7d01-95d6-c244ff3e30ed
|
|
686
|
-
```
|
|
687
|
-
|
|
688
|
-
Attach an existing CLI session to the current Telegram topic:
|
|
689
|
-
|
|
690
|
-
```text
|
|
691
|
-
/attach 019e178a-f275-7d01-95d6-c244ff3e30ed
|
|
692
|
-
```
|
|
693
|
-
|
|
694
|
-
Hand a session back to the native CLI:
|
|
695
|
-
|
|
696
|
-
```text
|
|
697
|
-
/handback
|
|
698
|
-
```
|
|
699
|
-
|
|
700
|
-
The bot replies with a command like:
|
|
701
|
-
|
|
702
|
-
```bash
|
|
703
|
-
cd ~/projects/my-workspace && codex resume 019e178a-f275-7d01-95d6-c244ff3e30ed
|
|
704
|
-
```
|
|
705
|
-
|
|
706
|
-
For Pi sessions the command looks like:
|
|
707
|
-
|
|
708
|
-
```bash
|
|
709
|
-
cd ~/projects/my-workspace && pi --session ~/.pi/agent/sessions/.../session.jsonl
|
|
710
|
-
```
|
|
711
|
-
|
|
712
|
-
For Hermes sessions the command looks like:
|
|
713
|
-
|
|
714
|
-
```bash
|
|
715
|
-
cd ~/projects/my-workspace && hermes --resume 20260512_181422_ab12cd34
|
|
716
|
-
```
|
|
717
|
-
|
|
718
|
-
For OpenClaw sessions the command looks like:
|
|
719
|
-
|
|
720
|
-
```bash
|
|
721
|
-
cd ~/projects/my-workspace && openclaw agent --agent main --session-id nordrelay-openclaw-a1b2c3d4e5f6 --message '<your next message>'
|
|
722
|
-
```
|
|
723
|
-
|
|
724
|
-
For Claude Code sessions the command looks like:
|
|
725
|
-
|
|
726
|
-
```bash
|
|
727
|
-
cd ~/projects/my-workspace && claude --resume 019e178a-f275-7d01-95d6-c244ff3e30ed
|
|
728
|
-
```
|
|
729
|
-
|
|
730
|
-
Change model:
|
|
731
|
-
|
|
732
|
-
```text
|
|
89
|
+
/agent
|
|
733
90
|
/model
|
|
734
|
-
```
|
|
735
|
-
|
|
736
|
-
Tap the model to use for new or reattached threads.
|
|
737
|
-
|
|
738
|
-
Change reasoning effort:
|
|
739
|
-
|
|
740
|
-
```text
|
|
741
91
|
/reasoning
|
|
92
|
+
/queue
|
|
93
|
+
/artifacts
|
|
94
|
+
/mirror
|
|
95
|
+
/stop
|
|
96
|
+
/diagnostics
|
|
742
97
|
```
|
|
743
98
|
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
Toggle fast mode:
|
|
747
|
-
|
|
748
|
-
```text
|
|
749
|
-
/fast
|
|
750
|
-
/fast on
|
|
751
|
-
/fast off
|
|
752
|
-
```
|
|
753
|
-
|
|
754
|
-
Fast mode maps to launch profiles: `on` selects an approval policy of `never`, while `off` selects an approval-requesting profile such as Review. If a thread is idle, `/fast` reattaches the current thread with the selected launch behavior immediately.
|
|
755
|
-
|
|
756
|
-
Choose launch profile:
|
|
757
|
-
|
|
758
|
-
```text
|
|
759
|
-
/launch_profiles
|
|
760
|
-
```
|
|
761
|
-
|
|
762
|
-
Tap the profile. Unsafe profiles require confirmation before they become active.
|
|
763
|
-
|
|
764
|
-
## File, Photo, Voice, and Artifact Workflow
|
|
765
|
-
|
|
766
|
-
Text:
|
|
767
|
-
|
|
768
|
-
- Any non-command text message becomes a prompt for the selected agent.
|
|
769
|
-
- While the selected agent works, Telegram shows `typing`.
|
|
770
|
-
- Replies stream back into the same chat or topic.
|
|
771
|
-
|
|
772
|
-
Photos:
|
|
773
|
-
|
|
774
|
-
- Send a photo with or without a caption.
|
|
775
|
-
- The connector downloads it and passes it to the selected agent as local image input.
|
|
776
|
-
- The caption becomes the text prompt when present.
|
|
777
|
-
- Sending multiple photos as a Telegram album creates one combined agent prompt.
|
|
778
|
-
|
|
779
|
-
Documents:
|
|
780
|
-
|
|
781
|
-
- Send a document with or without a caption.
|
|
782
|
-
- The connector downloads it, sanitizes the filename, enforces `MAX_FILE_SIZE`, and stages it under:
|
|
783
|
-
|
|
784
|
-
```text
|
|
785
|
-
<workspace>/.nordrelay/inbox/<turn-id>/
|
|
786
|
-
```
|
|
787
|
-
|
|
788
|
-
- The selected agent receives prompt instructions with the staged file paths.
|
|
789
|
-
- The caption becomes the text prompt when present.
|
|
790
|
-
- Document albums and mixed media groups are processed as one turn; oversized files are skipped and reported.
|
|
791
|
-
|
|
792
|
-
Artifacts:
|
|
793
|
-
|
|
794
|
-
- For generated files that should be returned to Telegram, tell the selected agent to write them to:
|
|
795
|
-
|
|
796
|
-
```text
|
|
797
|
-
<workspace>/.nordrelay/turns/<turn-id>/out/
|
|
798
|
-
```
|
|
799
|
-
|
|
800
|
-
- The connector stores files in that directory and keeps them available for `/artifacts`.
|
|
801
|
-
- Automatic Telegram artifact delivery is off by default. Set `TELEGRAM_AUTO_SEND_ARTIFACTS=true` to collect and send files right after a turn.
|
|
802
|
-
- When automatic delivery or explicit `/artifacts` sending is used, image outputs are sent with Telegram previews and other outputs are sent as documents.
|
|
803
|
-
- When more than five artifacts are sent, the connector tries to send one ZIP bundle instead of many separate files.
|
|
804
|
-
- Use `/artifacts` to list recent artifact turns with inline Send/ZIP/Delete actions.
|
|
805
|
-
- Use `/artifacts latest`, `/artifacts zip latest`, or `/artifacts <turn-id>` from text commands.
|
|
806
|
-
- Use `/artifacts images`, `/artifacts docs`, or `/artifacts search <text>` to narrow large artifact histories.
|
|
807
|
-
- Use `/artifacts delete <turn-id>` to delete an artifact turn without opening the inline confirmation flow.
|
|
808
|
-
- Telegram file delivery is capped at the configured `MAX_FILE_SIZE` per artifact or ZIP bundle.
|
|
809
|
-
- Old turn and inbox directories are pruned automatically to keep workspace state compact.
|
|
810
|
-
|
|
811
|
-
Voice and audio:
|
|
812
|
-
|
|
813
|
-
- Send a Telegram voice note or audio file.
|
|
814
|
-
- The connector transcribes it, then sends the transcript to the selected agent.
|
|
815
|
-
- Local transcription is tried first with `parakeet-coreml` or `faster-whisper` when installed.
|
|
816
|
-
- OpenAI Whisper is used when `OPENAI_API_KEY` is set.
|
|
817
|
-
|
|
818
|
-
Voice prerequisites:
|
|
819
|
-
|
|
820
|
-
```bash
|
|
821
|
-
# macOS Apple Silicon
|
|
822
|
-
brew install ffmpeg
|
|
823
|
-
npm install parakeet-coreml
|
|
824
|
-
```
|
|
825
|
-
|
|
826
|
-
```bash
|
|
827
|
-
# Debian/Ubuntu
|
|
828
|
-
sudo apt-get install ffmpeg
|
|
829
|
-
python3 -m venv .venv
|
|
830
|
-
.venv/bin/python -m pip install --upgrade pip
|
|
831
|
-
.venv/bin/python -m pip install faster-whisper
|
|
832
|
-
```
|
|
833
|
-
|
|
834
|
-
```dotenv
|
|
835
|
-
FASTER_WHISPER_PYTHON=.venv/bin/python
|
|
836
|
-
FASTER_WHISPER_MODEL=base
|
|
837
|
-
FASTER_WHISPER_COMPUTE_TYPE=int8
|
|
838
|
-
```
|
|
839
|
-
|
|
840
|
-
Whisper fallback:
|
|
841
|
-
|
|
842
|
-
```dotenv
|
|
843
|
-
OPENAI_API_KEY=sk-...
|
|
844
|
-
```
|
|
845
|
-
|
|
846
|
-
Voice transcription uses `OPENAI_API_KEY`, not `CODEX_API_KEY`.
|
|
847
|
-
|
|
848
|
-
## Environment Reference
|
|
849
|
-
|
|
850
|
-
Telegram:
|
|
851
|
-
|
|
852
|
-
- `TELEGRAM_ENABLED`: starts the Telegram adapter. Defaults to `true`.
|
|
853
|
-
- `TELEGRAM_BOT_TOKEN`: BotFather token. Required for the Telegram adapter to start.
|
|
854
|
-
- `TELEGRAM_RATE_LIMIT_MIN_INTERVAL_MS`: minimum interval for normal Telegram API sends. Defaults to `80`.
|
|
855
|
-
- `TELEGRAM_EDIT_MIN_INTERVAL_MS`: minimum interval for Telegram message edits. Defaults to `1200`.
|
|
856
|
-
- `TELEGRAM_TRANSPORT`: `polling` or `webhook`. Defaults to `polling`.
|
|
857
|
-
- `TELEGRAM_WEBHOOK_URL`: public base URL for webhook mode, for example `https://relay.example`.
|
|
858
|
-
- `TELEGRAM_WEBHOOK_HOST`: local bind host for webhook mode. Defaults to `127.0.0.1`.
|
|
859
|
-
- `TELEGRAM_WEBHOOK_PORT`: local bind port for webhook mode. Defaults to `8080`.
|
|
860
|
-
- `TELEGRAM_WEBHOOK_PATH`: webhook request path. Defaults to `/telegram/webhook`.
|
|
861
|
-
- `TELEGRAM_WEBHOOK_SECRET`: optional Telegram webhook secret token.
|
|
862
|
-
- `NORDRELAY_CLI_MIRROR_MODE`: default CLI mirror mode for chat adapters: `off`, `status`, `final`, or `full`. Defaults to `status`.
|
|
863
|
-
- `NORDRELAY_CLI_MIRROR_MIN_UPDATE_MS`: default minimum interval for mirrored CLI status edits. Defaults to `4000`.
|
|
864
|
-
- `NORDRELAY_NOTIFY_MODE`: default notification mode for chat adapters: `off`, `minimal`, or `all`. Defaults to `minimal`.
|
|
865
|
-
- `NORDRELAY_QUIET_HOURS`: optional default quiet-hour range in `HH-HH` format, for example `22-7`; use `off` in a channel override to disable inherited quiet hours.
|
|
866
|
-
- `NORDRELAY_AUTO_SEND_ARTIFACTS`: default automatic artifact summaries/uploads for chat adapters. Defaults to `false`.
|
|
867
|
-
- `TELEGRAM_CLI_MIRROR_MODE`, `TELEGRAM_CLI_MIRROR_MIN_UPDATE_MS`, `TELEGRAM_NOTIFY_MODE`, `TELEGRAM_QUIET_HOURS`, and `TELEGRAM_AUTO_SEND_ARTIFACTS`: optional Telegram-specific overrides.
|
|
868
|
-
- `TELEGRAM_REDACT_PATTERNS`: comma-separated regular expressions for additional Telegram/log redaction.
|
|
869
|
-
|
|
870
|
-
Discord:
|
|
871
|
-
|
|
872
|
-
- `DISCORD_ENABLED`: starts the Discord adapter. Defaults to `false`.
|
|
873
|
-
- `DISCORD_BOT_TOKEN`: Discord bot token. Required for the Discord adapter to start.
|
|
874
|
-
- `DISCORD_CLIENT_ID`: Discord application/client id used for slash-command registration.
|
|
875
|
-
- `DISCORD_GUILD_IDS`: optional comma-separated guild ids for instant guild slash-command registration.
|
|
876
|
-
- `DISCORD_ALLOWED_GUILD_IDS`: optional guild allow-list before user/group permissions are checked.
|
|
877
|
-
- `DISCORD_ALLOWED_CHANNEL_IDS`: optional channel allow-list before user/group permissions are checked.
|
|
878
|
-
- `DISCORD_MESSAGE_CONTENT_ENABLED`: reads regular Discord text messages as prompts. Defaults to `true`.
|
|
879
|
-
- `DISCORD_COMMAND_MODE`: `slash`, `message`, or `both`. Defaults to `both`.
|
|
880
|
-
- `DISCORD_AUTO_REGISTER_COMMANDS`: registers slash commands on startup when `DISCORD_CLIENT_ID` is set. Defaults to `true`.
|
|
881
|
-
- `DISCORD_CLI_MIRROR_MODE`, `DISCORD_CLI_MIRROR_MIN_UPDATE_MS`, `DISCORD_NOTIFY_MODE`, `DISCORD_QUIET_HOURS`, and `DISCORD_AUTO_SEND_ARTIFACTS`: optional Discord-specific overrides for the channel-neutral defaults.
|
|
882
|
-
|
|
883
|
-
Slack:
|
|
884
|
-
|
|
885
|
-
- `SLACK_ENABLED`: starts the Slack adapter. Defaults to `false`.
|
|
886
|
-
- `SLACK_BOT_TOKEN`: Slack bot token. Required for the Slack adapter to start.
|
|
887
|
-
- `SLACK_APP_TOKEN`: Slack app-level token for Socket Mode. Required when `SLACK_SOCKET_MODE=true`.
|
|
888
|
-
- `SLACK_SIGNING_SECRET`: Slack signing secret for HTTP Events mode. Required when `SLACK_SOCKET_MODE=false`.
|
|
889
|
-
- `SLACK_SOCKET_MODE`: uses Slack Socket Mode instead of an HTTP Events receiver. Defaults to `true`.
|
|
890
|
-
- `SLACK_PORT`: HTTP receiver port when Socket Mode is disabled. Defaults to `3000`.
|
|
891
|
-
- `SLACK_ALLOWED_TEAM_IDS`: optional Slack workspace allow-list before user/group permissions are checked.
|
|
892
|
-
- `SLACK_ALLOWED_CHANNEL_IDS`: optional channel allow-list before user/group permissions are checked.
|
|
893
|
-
- `SLACK_MESSAGE_CONTENT_ENABLED`: reads regular Slack text messages as prompts. Defaults to `true`.
|
|
894
|
-
- `SLACK_COMMAND`: slash command configured in Slack. Defaults to `/nordrelay`.
|
|
895
|
-
- `SLACK_CLI_MIRROR_MODE`, `SLACK_CLI_MIRROR_MIN_UPDATE_MS`, `SLACK_NOTIFY_MODE`, `SLACK_QUIET_HOURS`, and `SLACK_AUTO_SEND_ARTIFACTS`: optional Slack-specific overrides for the channel-neutral defaults.
|
|
896
|
-
|
|
897
|
-
User management:
|
|
898
|
-
|
|
899
|
-
- Users, groups, Telegram identities, Telegram group-chat access, Discord identities, Discord channel access, Slack identities, Slack channel access, and web sessions are stored in `~/.nordrelay/users.json`.
|
|
900
|
-
- Manage users in the WebUI Users page or with `nordrelay user list`, `create-admin`, `create`, `reset-password`, `link-telegram`, `link-discord`, `link-slack`, `link-code`, `discord-link-code`, and `slack-link-code`.
|
|
901
|
-
- Built-in groups are `admin`, `user`, and `readonly`.
|
|
902
|
-
- Group permissions include `inspect`, `sessions.read`, `sessions.write`, `prompt.send`, `prompt.abort`, `files.read`, `files.write`, `settings.read`, `settings.write`, `auth.manage`, `diagnostics.read`, `logs.read`, `logs.clear`, `queue.read`, `queue.write`, `updates.run`, `system.restart`, `users.read`, `users.write`, `audit.read`, `peers.read`, `peers.write`, and `peers.connect`.
|
|
903
|
-
- Custom groups can also restrict access to specific agent ids, workspace roots, Telegram chat ids, Discord channel ids, and Slack channel ids.
|
|
904
|
-
|
|
905
|
-
Peers:
|
|
906
|
-
|
|
907
|
-
- `NORDRELAY_PEER_ENABLED`: starts the dedicated peer API. Defaults to `false`.
|
|
908
|
-
- `NORDRELAY_PEER_NAME`: optional human-readable node name shown to paired instances.
|
|
909
|
-
- `NORDRELAY_PEER_HOST`: peer API bind host. Defaults to `127.0.0.1`.
|
|
910
|
-
- `NORDRELAY_PEER_PORT`: peer API port. Defaults to `31979`.
|
|
911
|
-
- `NORDRELAY_PEER_PUBLIC_URL`: optional URL other instances should use to reach this node.
|
|
912
|
-
- `NORDRELAY_PEER_TLS_ENABLED`: serves the peer API over HTTPS with an automatically generated local certificate. Defaults to `true`.
|
|
913
|
-
- `NORDRELAY_PEER_REQUIRE_TLS`: refuses plaintext peer serving on non-loopback hosts. Defaults to `true`.
|
|
914
|
-
- Peer identity, TLS certificate, peers, and invitations are stored under `~/.nordrelay/identity.json`, `~/.nordrelay/tls/`, and `~/.nordrelay/peers.json`.
|
|
915
|
-
- Peer invitations expire after at most 24 hours even if a longer lifetime is requested.
|
|
916
|
-
|
|
917
|
-
Agent selection:
|
|
918
|
-
|
|
919
|
-
- `NORDRELAY_CODEX_ENABLED`: enables Codex contexts. Defaults to `true`.
|
|
920
|
-
- `NORDRELAY_PI_ENABLED`: enables Pi contexts. Defaults to `false`.
|
|
921
|
-
- `NORDRELAY_HERMES_ENABLED`: enables Hermes contexts through the Hermes API Server. Defaults to `false`.
|
|
922
|
-
- `NORDRELAY_OPENCLAW_ENABLED`: enables OpenClaw contexts through the OpenClaw Gateway. Defaults to `false`.
|
|
923
|
-
- `NORDRELAY_CLAUDE_CODE_ENABLED`: enables Claude Code contexts through the Claude Agent SDK. Defaults to `false`.
|
|
924
|
-
- `NORDRELAY_DEFAULT_AGENT`: `codex`, `pi`, `hermes`, `openclaw`, or `claude-code`, used for new chat contexts. Defaults to the first enabled agent.
|
|
925
|
-
- `NORDRELAY_STATE_BACKEND`: `json` or `sqlite`. JSON is the default; SQLite requires `better-sqlite3`.
|
|
926
|
-
- `NORDRELAY_AUDIT_MAX_EVENTS`: maximum audit events retained. Defaults to `1000`.
|
|
927
|
-
- `NORDRELAY_SESSION_LOCK_TTL_MS`: session write-lock TTL. Defaults to `1800000`.
|
|
928
|
-
- `NORDRELAY_VERSION_CACHE_TTL_MS`: npm version freshness cache TTL. Defaults to `3600000`; set `0` to disable.
|
|
929
|
-
- `NORDRELAY_CLI_VERSION_CACHE_TTL_MS`: installed agent CLI version cache TTL. Defaults to `60000`; set `0` to disable.
|
|
930
|
-
|
|
931
|
-
Dashboard:
|
|
932
|
-
|
|
933
|
-
- `NORDRELAY_DASHBOARD_HOST`: dashboard bind host. Defaults to `127.0.0.1`.
|
|
934
|
-
- `NORDRELAY_DASHBOARD_PORT`: dashboard bind port. Defaults to `31878`.
|
|
935
|
-
- `NORDRELAY_ENV_FILE`: optional explicit env-file path used by the wrapper and edited by the dashboard settings page. Defaults to `~/.nordrelay/nordrelay.env`.
|
|
936
|
-
|
|
937
|
-
Codex:
|
|
938
|
-
|
|
939
|
-
- `CODEX_API_KEY`: optional API key for Codex SDK auth.
|
|
940
|
-
- `CODEX_CLI_PATH`: optional explicit path to the Codex CLI executable.
|
|
941
|
-
- `CODEX_USE_BUNDLED_CLI`: set `true` to force the SDK-bundled Codex CLI instead of the host `codex` executable.
|
|
942
|
-
- `CODEX_MODEL`: default model for new threads.
|
|
943
|
-
- `CODEX_SYNC_INTERVAL_MS`: periodic local Codex-state sync interval for active chat sessions. Defaults to `10000`; set `0` to disable.
|
|
944
|
-
- `CODEX_EXTERNAL_BUSY_CHECK_MS`: how often queued chat prompts re-check an active local Codex CLI task. Defaults to `5000`.
|
|
945
|
-
- `CODEX_EXTERNAL_BUSY_STALE_MS`: maximum age for an unclosed rollout task before it is treated as stale instead of active. Defaults to `300000`.
|
|
946
|
-
- `CODEX_SANDBOX_MODE`: default sandbox mode, one of `read-only`, `workspace-write`, `danger-full-access`.
|
|
947
|
-
- `CODEX_APPROVAL_POLICY`: default approval policy, one of `never`, `on-request`, `on-failure`, `untrusted`.
|
|
948
|
-
- `CODEX_LAUNCH_PROFILES_JSON`: JSON array of additional launch profiles.
|
|
949
|
-
- `CODEX_DEFAULT_LAUNCH_PROFILE`: profile id used by default. Defaults to `default`.
|
|
950
|
-
- `ENABLE_UNSAFE_LAUNCH_PROFILES`: set `true` to expose `danger-full-access` profiles.
|
|
951
|
-
|
|
952
|
-
Pi:
|
|
953
|
-
|
|
954
|
-
- `PI_CLI_PATH`: optional explicit path to the Pi CLI executable. Defaults to `pi` on `PATH`.
|
|
955
|
-
- `PI_SESSION_DIR`: optional Pi session directory. Defaults to `~/.pi/agent/sessions/` or `PI_CODING_AGENT_SESSION_DIR`.
|
|
956
|
-
- `PI_DEFAULT_MODEL`: optional default model pattern for new Pi sessions, for example `openai-codex/gpt-5.5`.
|
|
957
|
-
- `PI_DEFAULT_THINKING`: default Pi thinking level: `off`, `minimal`, `low`, `medium`, `high`, or `xhigh`. Defaults to `medium`.
|
|
958
|
-
- `PI_DEFAULT_PROFILE`: default Pi launch profile: `default`, `readonly`, `no-tools`, `offline`, or `safe-offline`. Defaults to `default`.
|
|
959
|
-
|
|
960
|
-
Hermes:
|
|
961
|
-
|
|
962
|
-
- `HERMES_CLI_PATH`: optional explicit path to the Hermes CLI executable. Defaults to `hermes` on `PATH`.
|
|
963
|
-
- `HERMES_HOME`: optional Hermes home directory. Defaults to `~/.hermes`.
|
|
964
|
-
- `HERMES_STATE_DB_PATH`: optional explicit Hermes `state.db` path. Overrides `HERMES_HOME`.
|
|
965
|
-
- `HERMES_API_BASE_URL`: Hermes API Server base URL. Defaults to `http://127.0.0.1:8642`.
|
|
966
|
-
- `HERMES_API_KEY`: optional bearer token for the Hermes API Server.
|
|
967
|
-
- `HERMES_DEFAULT_MODEL`: optional model label sent with new Hermes API runs.
|
|
968
|
-
- `HERMES_DEFAULT_REASONING`: default Hermes reasoning effort: `none`, `minimal`, `low`, `medium`, `high`, or `xhigh`.
|
|
969
|
-
- `HERMES_DEFAULT_PROFILE`: default Hermes launch profile: `default`, `safe`, `readonly`, or `yolo`. Defaults to `default`.
|
|
970
|
-
|
|
971
|
-
OpenClaw:
|
|
972
|
-
|
|
973
|
-
- `OPENCLAW_CLI_PATH`: optional explicit path to the OpenClaw CLI executable. Defaults to `openclaw` on `PATH`.
|
|
974
|
-
- `OPENCLAW_GATEWAY_URL`: OpenClaw Gateway WebSocket URL. Defaults to `ws://127.0.0.1:18789`.
|
|
975
|
-
- `OPENCLAW_GATEWAY_TOKEN`: optional shared-secret token for the OpenClaw Gateway.
|
|
976
|
-
- `OPENCLAW_GATEWAY_PASSWORD`: optional shared-secret password for the OpenClaw Gateway.
|
|
977
|
-
- `OPENCLAW_AGENT_ID`: OpenClaw agent id used for runs and session discovery. Defaults to `main`.
|
|
978
|
-
- `OPENCLAW_HOME`: optional OpenClaw home directory. Defaults to `~/.openclaw`.
|
|
979
|
-
- `OPENCLAW_STATE_DIR`: optional explicit OpenClaw state directory. Overrides `OPENCLAW_HOME`.
|
|
980
|
-
- `OPENCLAW_DEFAULT_MODEL`: optional model label sent with new OpenClaw Gateway runs.
|
|
981
|
-
- `OPENCLAW_DEFAULT_THINKING`: default OpenClaw thinking level: `off`, `minimal`, `low`, `medium`, `high`, or `xhigh`.
|
|
982
|
-
- `OPENCLAW_DEFAULT_PROFILE`: default OpenClaw launch profile: `default`, `safe`, `readonly`, `local`, or `deliver`. Defaults to `default`.
|
|
983
|
-
|
|
984
|
-
Claude Code:
|
|
985
|
-
|
|
986
|
-
- `CLAUDE_CODE_CLI_PATH`: optional explicit path to the Claude Code CLI executable. Defaults to `claude` on `PATH`, then the SDK bundled runtime.
|
|
987
|
-
- `CLAUDE_CONFIG_DIR`: optional Claude config directory. Defaults to `~/.claude`.
|
|
988
|
-
- `CLAUDE_CODE_DEFAULT_MODEL`: optional default Claude Code model alias or model id.
|
|
989
|
-
- `CLAUDE_CODE_DEFAULT_EFFORT`: default Claude Code effort: `off`, `low`, `medium`, `high`, or `xhigh`.
|
|
990
|
-
- `CLAUDE_CODE_DEFAULT_PROFILE`: default Claude Code launch profile: `default`, `accept-edits`, `plan`, `readonly`, `no-tools`, or `bypass-permissions`. Defaults to `default`.
|
|
991
|
-
- `CLAUDE_CODE_MAX_TURNS`: maximum agentic turns per Claude Code prompt. Defaults to `100`.
|
|
992
|
-
|
|
993
|
-
Telegram output:
|
|
994
|
-
|
|
995
|
-
- `CONNECTOR_LOG_FORMAT`: `text` or `json`. Defaults to `text`.
|
|
996
|
-
- `TOOL_VERBOSITY`: `all`, `summary`, `errors-only`, or `none`.
|
|
997
|
-
- `SHOW_TURN_TOKEN_USAGE`: appends per-turn token usage when `true`.
|
|
998
|
-
- `ENABLE_TELEGRAM_REACTIONS`: enables Telegram reactions when `true`.
|
|
999
|
-
- `MAX_FILE_SIZE`: maximum inbound Telegram document size in bytes. Defaults to 20 MB.
|
|
1000
|
-
- `ARTIFACT_RETENTION_DAYS`: artifact/inbox turn age before pruning. Defaults to `7`.
|
|
1001
|
-
- `ARTIFACT_MAX_TURNS`: maximum artifact turn directories to keep per workspace. Defaults to `30`.
|
|
1002
|
-
- `ARTIFACT_MAX_INBOX_DIRS`: maximum staged inbox directories to keep per workspace. Defaults to `30`.
|
|
1003
|
-
- `ARTIFACT_IGNORE_DIRS`: comma-separated extra directory names or relative paths ignored during workspace artifact scans.
|
|
1004
|
-
- `ARTIFACT_IGNORE_GLOBS`: comma-separated glob patterns ignored during workspace artifact scans.
|
|
1005
|
-
- `TELEGRAM_AUTO_SEND_ARTIFACTS`: automatically post generated artifact summaries/files after Telegram turns and mirrored CLI turns. Defaults to `false`.
|
|
1006
|
-
|
|
1007
|
-
Workspace policy:
|
|
1008
|
-
|
|
1009
|
-
- `WORKSPACE_ALLOWED_ROOTS`: comma-separated root directories allowed for session switching and workspace selection. Empty means unrestricted.
|
|
1010
|
-
- `WORKSPACE_WARN_ROOTS`: comma-separated broad roots that should be allowed but warned about in `/session` and `/workspaces`.
|
|
1011
|
-
|
|
1012
|
-
Auth and voice:
|
|
1013
|
-
|
|
1014
|
-
- `ENABLE_TELEGRAM_LOGIN`: enables `/login` and `/logout`. Defaults to `true`.
|
|
1015
|
-
- `FASTER_WHISPER_PYTHON`: Python executable for local Linux voice transcription. Example: `.venv/bin/python`.
|
|
1016
|
-
- `FASTER_WHISPER_MODEL`: faster-whisper model name. Defaults to `base`.
|
|
1017
|
-
- `FASTER_WHISPER_DEVICE`: faster-whisper device. Defaults to `cpu`.
|
|
1018
|
-
- `FASTER_WHISPER_COMPUTE_TYPE`: faster-whisper compute type. Defaults to `int8`.
|
|
1019
|
-
- `FASTER_WHISPER_LANGUAGE`: optional fixed transcription language.
|
|
1020
|
-
- `FASTER_WHISPER_TIMEOUT_MS`: local transcription timeout. Defaults to `600000`.
|
|
1021
|
-
- `OPENAI_API_KEY`: enables Whisper transcription fallback for voice/audio.
|
|
1022
|
-
- `VOICE_PREFERRED_BACKEND`: `auto`, `parakeet`, `faster-whisper`, or `openai`. Defaults to `auto`.
|
|
1023
|
-
- `VOICE_DEFAULT_LANGUAGE`: optional default language code, for example `de` or `en`.
|
|
1024
|
-
- `VOICE_TRANSCRIBE_ONLY`: when `true`, voice/audio messages are transcribed but not sent to the selected agent.
|
|
1025
|
-
|
|
1026
|
-
NordRelay wrapper:
|
|
1027
|
-
|
|
1028
|
-
- `NORDRELAY_HOME`: config/state/log directory override. Defaults to `~/.nordrelay`.
|
|
1029
|
-
- `NORDRELAY_SOURCE_ROOT`: runtime source root override. Useful when the plugin is launched from Codex cache.
|
|
1030
|
-
- `NORDRELAY_UPDATE_METHOD`: optional `auto`, `npm`, or `git` self-update method override used by `nordrelay update`, `/update`, and the WebUI update button. Auto uses git when the runtime root has a `.git` directory and npm otherwise.
|
|
1031
|
-
- Agent updates from the dashboard and Telegram use each agent's native updater where possible: `codex update`, `pi update pi`, `hermes update --yes`, `openclaw update --yes`, and `claude update`. Not-installed agents can be installed from the dashboard or with `/update install <agent>` using npm global installs.
|
|
1032
|
-
- `NORDRELAY_KEEP_PENDING_UPDATES`: set true to avoid dropping pending Telegram updates on start.
|
|
1033
|
-
- `NORDRELAY_FORWARD_TOOL_OUTPUT`: backward-compatible alias that sets `TOOL_VERBOSITY=all` when `TOOL_VERBOSITY` is unset.
|
|
1034
|
-
- `NORDRELAY_STATE_FILE`: internal state-file path passed by the wrapper.
|
|
1035
|
-
- `NORDRELAY_WRAPPER_PID`: internal wrapper PID passed to the runtime.
|
|
1036
|
-
- `NORDRELAY_DROP_PENDING_UPDATES`: internal polling startup flag.
|
|
1037
|
-
|
|
1038
|
-
## Launch Profiles
|
|
1039
|
-
|
|
1040
|
-
Built-in profiles:
|
|
1041
|
-
|
|
1042
|
-
- `default`: uses `CODEX_SANDBOX_MODE` and `CODEX_APPROVAL_POLICY`.
|
|
1043
|
-
- `readonly`: `read-only` with `never`.
|
|
1044
|
-
- `review`: `workspace-write` with `on-request`.
|
|
1045
|
-
- `full-access`: `danger-full-access` with `never`, only when unsafe profiles are enabled.
|
|
1046
|
-
|
|
1047
|
-
Custom profile example:
|
|
1048
|
-
|
|
1049
|
-
```dotenv
|
|
1050
|
-
CODEX_LAUNCH_PROFILES_JSON=[{"id":"review-safe","label":"Review Safe","sandboxMode":"workspace-write","approvalPolicy":"on-request"}]
|
|
1051
|
-
CODEX_DEFAULT_LAUNCH_PROFILE=review-safe
|
|
1052
|
-
```
|
|
1053
|
-
|
|
1054
|
-
Multiple profiles:
|
|
1055
|
-
|
|
1056
|
-
```dotenv
|
|
1057
|
-
CODEX_LAUNCH_PROFILES_JSON=[{"id":"readonly-audit","label":"Readonly Audit","sandboxMode":"read-only","approvalPolicy":"never"},{"id":"interactive","label":"Interactive","sandboxMode":"workspace-write","approvalPolicy":"on-request"}]
|
|
1058
|
-
```
|
|
1059
|
-
|
|
1060
|
-
Unsafe full-access profile:
|
|
1061
|
-
|
|
1062
|
-
```dotenv
|
|
1063
|
-
ENABLE_UNSAFE_LAUNCH_PROFILES=true
|
|
1064
|
-
CODEX_LAUNCH_PROFILES_JSON=[{"id":"host-full","label":"Host Full Access","sandboxMode":"danger-full-access","approvalPolicy":"never"}]
|
|
1065
|
-
```
|
|
1066
|
-
|
|
1067
|
-
Unsafe profiles are intentionally gated. Chat adapters ask for confirmation before applying them.
|
|
99
|
+
See [Commands](docs/commands.md) for the complete Telegram, Discord, Slack, queue, artifact, mirror, update, and diagnostic command reference.
|
|
1068
100
|
|
|
1069
|
-
##
|
|
101
|
+
## What NordRelay Provides
|
|
1070
102
|
|
|
1071
|
-
-
|
|
1072
|
-
-
|
|
1073
|
-
-
|
|
1074
|
-
-
|
|
1075
|
-
-
|
|
1076
|
-
-
|
|
1077
|
-
-
|
|
1078
|
-
-
|
|
1079
|
-
- In group chats, remember that any linked user with prompt permissions can prompt the selected agent in that chat context.
|
|
1080
|
-
- Use `TOOL_VERBOSITY=summary` or `errors-only` when command output may include sensitive data.
|
|
1081
|
-
- Review and unsafe launch profiles add a Telegram approve/deny gate before each turn starts.
|
|
1082
|
-
- Keep the peer API disabled unless needed. For internet use, expose it only through a firewall, VPN, or hardened reverse proxy; keep TLS enabled and revoke unused peers with `nordrelay peer revoke <peer-id>`.
|
|
103
|
+
- Independent sessions per Telegram chat/topic, Discord DM/channel/thread, Slack DM/channel/thread, WebUI, and peer target.
|
|
104
|
+
- Streaming replies, typing/status indicators, tool activity, queue handling, retry, abort/stop, and CLI handback.
|
|
105
|
+
- File, photo, voice/audio, and generated artifact workflows.
|
|
106
|
+
- Per-user and per-group access control for WebUI and chat adapters.
|
|
107
|
+
- Optional peer federation for controlling agents on other trusted NordRelay hosts.
|
|
108
|
+
- WebUI dashboard for chat, sessions, settings, logs, diagnostics, updates, artifacts, peers, metrics, and users.
|
|
109
|
+
- Agent adapters for Codex, Pi, Hermes, OpenClaw, and Claude Code.
|
|
110
|
+
- Chat adapters for Telegram, Discord, and Slack.
|
|
1083
111
|
|
|
1084
|
-
##
|
|
112
|
+
## Documentation
|
|
1085
113
|
|
|
1086
|
-
|
|
114
|
+
| Topic | Link |
|
|
115
|
+
| --- | --- |
|
|
116
|
+
| Full feature list and adapter capabilities | [docs/features.md](docs/features.md) |
|
|
117
|
+
| First-run setup, users, running modes, and WebUI | [docs/setup.md](docs/setup.md) |
|
|
118
|
+
| Telegram, Discord, Slack, and WebUI commands | [docs/commands.md](docs/commands.md) |
|
|
119
|
+
| Files, photos, voice, transcription, and artifacts | [docs/workflows.md](docs/workflows.md) |
|
|
120
|
+
| Environment variables and launch profiles | [docs/configuration.md](docs/configuration.md) |
|
|
121
|
+
| Security notes and troubleshooting | [docs/security-troubleshooting.md](docs/security-troubleshooting.md) |
|
|
122
|
+
| Deployment with npm, foreground, Docker, launchd, and systemd | [docs/deployment.md](docs/deployment.md) |
|
|
123
|
+
| Codebase architecture and module map | [docs/architecture.md](docs/architecture.md) |
|
|
124
|
+
| Public security policy | [SECURITY.md](SECURITY.md) |
|
|
125
|
+
| Contribution guide | [CONTRIBUTING.md](CONTRIBUTING.md) |
|
|
1087
126
|
|
|
1088
|
-
|
|
1089
|
-
- Cause: the same bot token is being polled by another process.
|
|
1090
|
-
- Fix: stop the other process or run `npm stop`, then `npm start`.
|
|
127
|
+
## Development
|
|
1091
128
|
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
- Symptom: Codex uses old command or skill text after a repo update.
|
|
1095
|
-
- Fix: reinstall/update the local marketplace or copy the plugin directory into the Codex plugin cache.
|
|
1096
|
-
- Current local cache path: `~/.codex/plugins/cache/nordrelay-local/nordrelay/<version>/`.
|
|
1097
|
-
|
|
1098
|
-
Missing dependencies:
|
|
1099
|
-
|
|
1100
|
-
- Symptom: startup says runtime is missing.
|
|
1101
|
-
- Fix:
|
|
129
|
+
From a source checkout:
|
|
1102
130
|
|
|
1103
131
|
```bash
|
|
1104
132
|
npm install
|
|
1105
133
|
npm run build
|
|
134
|
+
npm run check
|
|
135
|
+
npm test
|
|
136
|
+
npm run test:e2e
|
|
1106
137
|
```
|
|
1107
138
|
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
- Symptom: prompt execution says Codex is not authenticated.
|
|
1111
|
-
- Fix: run `codex login` on the host, use `/login`, or set `CODEX_API_KEY`.
|
|
1112
|
-
- Use `/auth` to check the current auth method.
|
|
1113
|
-
|
|
1114
|
-
No sessions listed:
|
|
1115
|
-
|
|
1116
|
-
- Symptom: `/sessions` says no recent threads found.
|
|
1117
|
-
- Cause for Codex: `~/.codex/state_*.sqlite` is missing, unreadable, or has no active threads.
|
|
1118
|
-
- Cause for Pi: `~/.pi/agent/sessions/` or `PI_SESSION_DIR` is missing, unreadable, or has no session JSONL files.
|
|
1119
|
-
- Cause for Hermes: `~/.hermes/state.db` or `HERMES_STATE_DB_PATH` is missing, unreadable, or has no session rows.
|
|
1120
|
-
- Cause for OpenClaw: `openclaw sessions --all-agents --json` returns no sessions, or `OPENCLAW_HOME`/`OPENCLAW_STATE_DIR` points at the wrong state location.
|
|
1121
|
-
- Cause for Claude Code: `~/.claude/projects/` or `CLAUDE_CONFIG_DIR/projects` is missing, unreadable, or has no session JSONL files.
|
|
1122
|
-
- Fix: run the selected agent locally once, resume or create a session, then try `/sessions` again.
|
|
1123
|
-
|
|
1124
|
-
Wrong model, reasoning, or fast mode after switching:
|
|
1125
|
-
|
|
1126
|
-
- The connector reads model, reasoning, workspace, sandbox, and approval metadata from supported local agent state on `/sessions`, `/switch`, `/attach`, and `/session`; Codex fast mode is read from `~/.codex/config.toml`.
|
|
1127
|
-
- For Pi, the connector reads model/thinking from Pi JSONL sessions and refreshes active RPC state when a session is running.
|
|
1128
|
-
- For Hermes, the connector reads model, reasoning, token usage, and message activity from Hermes `state.db`; `/model` and `/reasoning` values are sent with future API runs.
|
|
1129
|
-
- For OpenClaw, the connector reads model, thinking, token usage, and activity from OpenClaw session state; `/model` and `/reasoning` values are sent with future Gateway runs.
|
|
1130
|
-
- For Claude Code, the connector reads model, effort, token usage, and activity from Claude Code transcript JSONL files; `/model` and `/reasoning` values are sent with future SDK runs.
|
|
1131
|
-
- If values look stale, make sure the selected local CLI has finished writing session state.
|
|
1132
|
-
|
|
1133
|
-
Pi not available:
|
|
1134
|
-
|
|
1135
|
-
- Symptom: `/agent` cannot switch to Pi, or startup says Pi CLI is missing.
|
|
1136
|
-
- Fix: install Pi from https://pi.dev/, ensure `pi` is on `PATH`, or set `PI_CLI_PATH`.
|
|
1137
|
-
- Enable Pi with `NORDRELAY_PI_ENABLED=true`.
|
|
1138
|
-
|
|
1139
|
-
Hermes not available:
|
|
1140
|
-
|
|
1141
|
-
- Symptom: `/agent` cannot switch to Hermes, `/auth` fails, or prompt execution says the Hermes API request failed.
|
|
1142
|
-
- Fix: start the Hermes API Server, ensure `HERMES_API_BASE_URL` points to it, and set `HERMES_API_KEY` if the server requires a key.
|
|
1143
|
-
- Enable Hermes with `NORDRELAY_HERMES_ENABLED=true`.
|
|
1144
|
-
|
|
1145
|
-
OpenClaw not available:
|
|
1146
|
-
|
|
1147
|
-
- Symptom: `/agent` cannot switch to OpenClaw, `/auth` fails, or prompt execution says the OpenClaw Gateway request failed.
|
|
1148
|
-
- Fix: start the OpenClaw Gateway, ensure `OPENCLAW_GATEWAY_URL` points to it, and set `OPENCLAW_GATEWAY_TOKEN` or `OPENCLAW_GATEWAY_PASSWORD` if the Gateway requires shared-secret auth.
|
|
1149
|
-
- Enable OpenClaw with `NORDRELAY_OPENCLAW_ENABLED=true`.
|
|
1150
|
-
|
|
1151
|
-
Claude Code not available:
|
|
1152
|
-
|
|
1153
|
-
- Symptom: `/agent` cannot switch to Claude Code, `/auth` fails, or prompt execution says Claude Code auth is missing.
|
|
1154
|
-
- Fix: run `claude auth login` on the host, ensure `claude` is on `PATH`, or set `CLAUDE_CODE_CLI_PATH`.
|
|
1155
|
-
- Enable Claude Code with `NORDRELAY_CLAUDE_CODE_ENABLED=true`.
|
|
1156
|
-
|
|
1157
|
-
Voice not working:
|
|
1158
|
-
|
|
1159
|
-
- Run `/voice` to list available backends.
|
|
1160
|
-
- Install `ffmpeg` and `faster-whisper` on Linux, install `parakeet-coreml` on macOS Apple Silicon, or set `OPENAI_API_KEY`.
|
|
1161
|
-
- Check `~/.nordrelay/nordrelay.log` for transcription errors.
|
|
1162
|
-
|
|
1163
|
-
Files not returned:
|
|
1164
|
-
|
|
1165
|
-
- Ensure Codex writes generated files to `.nordrelay/turns/<turn-id>/out/`.
|
|
1166
|
-
- Files over 50 MB are skipped.
|
|
1167
|
-
- Hidden files, temp files, and directories are ignored.
|
|
1168
|
-
- Use `ARTIFACT_IGNORE_DIRS` and `ARTIFACT_IGNORE_GLOBS` to suppress project-specific build/cache output.
|
|
1169
|
-
- Automatic artifact sending stays off unless `TELEGRAM_AUTO_SEND_ARTIFACTS=true`; `/artifacts` can still list and resend indexed outputs.
|
|
1170
|
-
|
|
1171
|
-
## Deployment
|
|
1172
|
-
|
|
1173
|
-
Foreground debugging:
|
|
139
|
+
Useful runtime scripts:
|
|
1174
140
|
|
|
1175
141
|
```bash
|
|
1176
142
|
npm run foreground
|
|
1177
|
-
```
|
|
1178
|
-
|
|
1179
|
-
Background process:
|
|
1180
|
-
|
|
1181
|
-
```bash
|
|
1182
143
|
npm start
|
|
1183
144
|
npm run status
|
|
1184
145
|
npm stop
|
|
1185
146
|
```
|
|
1186
147
|
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
```bash
|
|
1190
|
-
docker compose up -d --build
|
|
1191
|
-
docker compose logs -f
|
|
1192
|
-
docker compose down
|
|
1193
|
-
```
|
|
1194
|
-
|
|
1195
|
-
The compose file mounts:
|
|
1196
|
-
|
|
1197
|
-
- `${HOME}/.codex` into the container for Codex auth and thread state.
|
|
1198
|
-
- `./workspace` as `/workspace` for container workspaces.
|
|
1199
|
-
|
|
1200
|
-
launchd helper:
|
|
1201
|
-
|
|
1202
|
-
```bash
|
|
1203
|
-
NORDRELAY_SOURCE_ROOT=~/projects/nordrelay launchd/start.sh
|
|
1204
|
-
```
|
|
1205
|
-
|
|
1206
|
-
Linux systemd example:
|
|
1207
|
-
|
|
1208
|
-
```ini
|
|
1209
|
-
[Unit]
|
|
1210
|
-
Description=NordRelay
|
|
1211
|
-
After=network-online.target
|
|
1212
|
-
|
|
1213
|
-
[Service]
|
|
1214
|
-
Type=simple
|
|
1215
|
-
WorkingDirectory=/opt/nordrelay
|
|
1216
|
-
Environment=NORDRELAY_SOURCE_ROOT=/opt/nordrelay
|
|
1217
|
-
ExecStart=/usr/bin/node dist/index.js
|
|
1218
|
-
Restart=on-failure
|
|
1219
|
-
RestartSec=5
|
|
1220
|
-
|
|
1221
|
-
[Install]
|
|
1222
|
-
WantedBy=multi-user.target
|
|
1223
|
-
```
|
|
1224
|
-
|
|
1225
|
-
Build before starting a service:
|
|
148
|
+
## Security Defaults
|
|
1226
149
|
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
150
|
+
- The dashboard requires login.
|
|
151
|
+
- Chat adapter access requires linked NordRelay users and registered/allowed channels.
|
|
152
|
+
- Peer serving is disabled by default and requires explicit pairing.
|
|
153
|
+
- Unsafe launch profiles are hidden unless explicitly enabled.
|
|
154
|
+
- Secrets belong in `~/.nordrelay/nordrelay.env` or host secret management, not in the repository.
|
|
1231
155
|
|
|
1232
|
-
##
|
|
156
|
+
## License
|
|
1233
157
|
|
|
1234
|
-
|
|
1235
|
-
- `plugins/nordrelay/scripts/nordrelay.mjs`: process manager for `start`, `stop`, `restart`, `status`, and `foreground`.
|
|
1236
|
-
- `src/index.ts`: runtime entrypoint, config load, auth check, state-file writes, polling lifecycle, shutdown.
|
|
1237
|
-
- `src/bot.ts`: Telegram prompt/session runtime, streaming, file/photo/voice handling, artifacts, and error handling.
|
|
1238
|
-
- `src/telegram-general-commands.ts`, `src/telegram-agent-commands.ts`, `src/telegram-preference-commands.ts`, `src/telegram-access-commands.ts`, `src/telegram-diagnostics-command.ts`, `src/telegram-update-commands.ts`, `src/telegram-support-command.ts`, and `src/telegram-command-menu.ts`: focused Telegram command groups for start/help/adapters, agent/auth controls, per-chat preferences, access linking, diagnostics/log/version commands, update jobs, diagnostics bundle export, and command menu registration.
|
|
1239
|
-
- `src/channel-adapter.ts`, `src/channel-runtime.ts`, `src/channel-command-core.ts`, `src/channel-actions.ts`, and `src/adapter-conformance.ts`: channel descriptors, shared command dispatch/coverage, outbound delivery contracts, channel-neutral responses, and generated feature/command conformance matrices.
|
|
1240
|
-
- `src/discord-bot.ts` and `src/slack-bot.ts`: Discord and Slack bridge runtimes built on the shared channel command core, channel runtimes, rate limiters, access checks, streaming replies, attachments, mirrors, and queue controls.
|
|
1241
|
-
- `src/slack-diagnostics.ts`: Slack readiness probes for token/transport config, auth, registered channel visibility, file-upload readiness, and rate-limit reporting.
|
|
1242
|
-
- `src/user-management.ts`, `src/user-management-types.ts`, `src/user-management-normalize.ts`, and `src/user-management-crypto.ts`: user/group/session/channel-access store with separated DTOs, payload normalization, password/token helpers, and public snapshots.
|
|
1243
|
-
- `src/config-metadata.ts`: shared setting metadata used by the WebUI settings page and generated `.env.example`.
|
|
1244
|
-
- `src/support-bundle.ts` and `src/zip-writer.ts`: redacted diagnostics bundle creation with a dependency-free ZIP writer.
|
|
1245
|
-
- `src/relay-queue-service.ts`, `src/relay-artifact-service.ts`, and `src/relay-external-activity-monitor.ts`: Web runtime queue operations, artifact preview/export/persistence, and external CLI activity mirroring.
|
|
1246
|
-
- `src/relay-runtime-types.ts`: shared Runtime/WebUI DTO types used by runtime, API contracts, and dashboard code.
|
|
1247
|
-
- `src/web-dashboard-http.ts`, `src/web-dashboard-pages.ts`, and `src/web-dashboard-runtime-routes.ts`: dashboard HTTP helpers, HTML shell rendering, and operational runtime API routes.
|
|
1248
|
-
- `src/webui/`: focused WebUI source assets for core runtime state/API helpers, overview rendering, live events, chat/session workflows, admin pages, and CSS sections.
|
|
1249
|
-
- `src/bot-preferences.ts`: per-context mirror, notification, quiet-hour, and voice preference persistence.
|
|
1250
|
-
- `src/telegram-rate-limit.ts`: centralized Telegram API send/edit/document rate limiting and retry-after tracking.
|
|
1251
|
-
- `src/persistence.ts`: atomic JSON/text writes with backup recovery.
|
|
1252
|
-
- `src/redaction.ts`: common secret redaction and custom redaction pattern support.
|
|
1253
|
-
- `src/workspace-policy.ts`: workspace allow/warn root evaluation.
|
|
1254
|
-
- `src/access-control.ts`: user/group permission definitions and command/callback/WebUI permission mapping.
|
|
1255
|
-
- `src/codex-session.ts`: Codex SDK service for new/resumed threads, streaming events, abort, model, reasoning, launch profiles, and handback.
|
|
1256
|
-
- `src/pi-session.ts`: Pi RPC service for JSONL RPC sessions, streaming events, abort, model, thinking, launch profiles, and handback.
|
|
1257
|
-
- `src/hermes-session.ts`: Hermes API Server service for streamed runs, stop, model, reasoning, launch profiles, attachments, and handback.
|
|
1258
|
-
- `src/openclaw-session.ts`: OpenClaw Gateway service for streamed runs, cancel, model, thinking, launch profiles, attachments, and handback.
|
|
1259
|
-
- `src/claude-code-session.ts`: Claude Agent SDK service for streamed runs, abort, model, effort, launch profiles, attachments, and handback.
|
|
1260
|
-
- `src/session-registry.ts`: per-chat/topic session registry and persisted context metadata.
|
|
1261
|
-
- `test/agent-adapter-contract.test.ts`: shared adapter contract coverage for descriptors, capability flags, reasoning options, launch profiles, and `AgentSessionService` method parity.
|
|
1262
|
-
- `src/session-format.ts`: compact Telegram rendering for session details, token usage, and limits.
|
|
1263
|
-
- `src/codex-state.ts`: reader for Codex `~/.codex/state_*.sqlite` thread, workspace, model, reasoning, sandbox, and approval metadata.
|
|
1264
|
-
- `src/pi-state.ts`: reader for Pi session JSONL files, activity timelines, diagnostics, and external busy detection.
|
|
1265
|
-
- `src/hermes-state.ts`: reader for Hermes `state.db` sessions, messages, token usage, activity timelines, diagnostics, and external busy detection.
|
|
1266
|
-
- `src/hermes-api.ts`: Hermes API Server client for health, capabilities, models, runs, events, approvals, and stop.
|
|
1267
|
-
- `src/openclaw-state.ts`: reader for OpenClaw session metadata, token usage, activity timelines, diagnostics, and external busy detection.
|
|
1268
|
-
- `src/openclaw-gateway.ts`: OpenClaw Gateway WebSocket RPC client for health, models, runs, stream events, and cancel.
|
|
1269
|
-
- `src/claude-code-state.ts`: reader for Claude Code transcript JSONL files, token usage, activity timelines, diagnostics, and external busy detection.
|
|
1270
|
-
- `src/attachments.ts`: inbound file staging and artifact output path construction.
|
|
1271
|
-
- `src/artifacts.ts`: generated artifact discovery, ZIP bundling, retention, and Telegram delivery filtering.
|
|
1272
|
-
- `src/voice.ts`: audio decoding and transcription backend selection.
|
|
1273
|
-
- `src/format.ts`: Telegram-safe HTML formatting and markdown conversion.
|
|
1274
|
-
- `src/error-messages.ts`: user-facing error translation.
|
|
158
|
+
MIT. See [LICENSE](LICENSE).
|