@nordbyte/nordrelay 0.4.1 → 0.5.0

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 CHANGED
@@ -1,153 +1,244 @@
1
- # Required: bot token from BotFather.
2
- TELEGRAM_BOT_TOKEN=123456789:replace-me
3
-
4
- # Required: comma-separated Telegram user ids that may administer and use the bot.
5
- # A fresh install only accepts messages from these admin user ids.
6
- TELEGRAM_ADMIN_USER_IDS=123456789
7
-
8
- # Optional role controls. Add non-admin operators or read-only users here.
9
- # Admin user ids are automatically allowed and do not need to be repeated.
10
- TELEGRAM_ALLOWED_USER_IDS=
11
- TELEGRAM_READONLY_USER_IDS=
12
- # Optional granular permission policy per role. Permissions: inspect, sessions,
13
- # prompt, files, settings, auth, admin. Admin always keeps admin permission.
14
- TELEGRAM_ROLE_POLICIES_JSON=
15
-
16
- # Backward-compatible alternative for this connector. Private chat ids usually
17
- # match the Telegram user id; group chat ids may be negative.
18
- TELEGRAM_ALLOWED_CHAT_IDS=
1
+ # NordRelay runtime config example.
2
+ # Access is managed with NordRelay users, groups, linked Telegram identities, and enabled Telegram group chats.
3
+ # Create the first admin with `nordrelay init` or `nordrelay user create-admin`.
19
4
 
20
- # Optional explicit override. Keep false for private bots.
21
- TELEGRAM_ALLOW_ANY_CHAT=false
5
+ # Telegram
6
+ # Required Telegram bot and transport settings.
7
+ # BotFather token.
8
+ TELEGRAM_BOT_TOKEN=123456789:replace-me
9
+ # polling or webhook.
10
+ # Options: polling, webhook
11
+ TELEGRAM_TRANSPORT=polling
12
+ # Public base URL for webhook mode.
13
+ TELEGRAM_WEBHOOK_URL=
14
+ # Local webhook bind host.
15
+ TELEGRAM_WEBHOOK_HOST=127.0.0.1
16
+ # Local webhook bind port.
17
+ TELEGRAM_WEBHOOK_PORT=8080
18
+ # Webhook request path.
19
+ TELEGRAM_WEBHOOK_PATH=/telegram/webhook
20
+ # Optional Telegram webhook secret token.
21
+ TELEGRAM_WEBHOOK_SECRET=
22
22
 
23
+ # Agents
23
24
  # Agent access. Codex is enabled by default; Pi, Hermes, OpenClaw, and Claude Code are opt-in.
24
- # Pi requires the `pi` CLI from https://pi.dev/ on the host. Hermes uses
25
- # the Hermes API Server (`hermes gateway` with API_SERVER_ENABLED=true).
26
- # OpenClaw uses the OpenClaw Gateway WebSocket RPC endpoint.
27
- # Claude Code uses the Claude Agent SDK and the host `claude` CLI when present.
25
+ # Allow Codex sessions.
28
26
  NORDRELAY_CODEX_ENABLED=true
27
+ # Allow Pi sessions.
29
28
  NORDRELAY_PI_ENABLED=false
29
+ # Allow Hermes sessions through the Hermes API Server.
30
30
  NORDRELAY_HERMES_ENABLED=false
31
+ # Allow OpenClaw sessions through the OpenClaw Gateway.
31
32
  NORDRELAY_OPENCLAW_ENABLED=false
33
+ # Allow Claude Code sessions through the Claude Agent SDK.
32
34
  NORDRELAY_CLAUDE_CODE_ENABLED=false
35
+ # codex, pi, hermes, openclaw, or claude-code.
36
+ # Options: codex, pi, hermes, openclaw, claude-code
33
37
  NORDRELAY_DEFAULT_AGENT=codex
34
38
 
35
- # Codex defaults for newly created or reattached Telegram sessions.
39
+ # Codex
40
+ # Codex defaults for newly created or reattached sessions.
41
+ # Optional Codex SDK API key.
36
42
  CODEX_API_KEY=
43
+ # Optional explicit Codex executable path.
37
44
  CODEX_CLI_PATH=
45
+ # Force SDK-bundled CLI instead of host CLI.
38
46
  CODEX_USE_BUNDLED_CLI=false
47
+ # Default model for new Codex threads.
39
48
  CODEX_MODEL=
49
+ # Local state sync interval.
40
50
  CODEX_SYNC_INTERVAL_MS=10000
51
+ # External CLI busy polling interval.
52
+ CODEX_EXTERNAL_BUSY_CHECK_MS=5000
53
+ # External CLI stale timeout.
54
+ CODEX_EXTERNAL_BUSY_STALE_MS=300000
55
+ # read-only, workspace-write, or danger-full-access.
56
+ # Options: read-only, workspace-write, danger-full-access
41
57
  CODEX_SANDBOX_MODE=workspace-write
58
+ # never, on-request, on-failure, or untrusted.
59
+ # Options: never, on-request, on-failure, untrusted
42
60
  CODEX_APPROVAL_POLICY=never
43
-
44
- # Optional extra launch profiles for /launch_profiles.
45
- # Example: [{"id":"review","label":"Review","sandboxMode":"workspace-write","approvalPolicy":"on-request"}]
61
+ # Additional launch profile definitions.
46
62
  CODEX_LAUNCH_PROFILES_JSON=
63
+ # Launch profile ID used by default.
47
64
  CODEX_DEFAULT_LAUNCH_PROFILE=default
65
+ # Expose danger-full-access profiles.
48
66
  ENABLE_UNSAFE_LAUNCH_PROFILES=false
49
67
 
50
- # Pi coding agent defaults. PI_DEFAULT_MODEL accepts Pi model patterns such as
51
- # openai-codex/gpt-5.5. PI_DEFAULT_THINKING: off, minimal, low, medium, high, xhigh.
68
+ # Pi
69
+ # Pi coding agent defaults.
70
+ # Optional Pi executable path.
52
71
  PI_CLI_PATH=
72
+ # Optional Pi session directory.
53
73
  PI_SESSION_DIR=
74
+ # Default Pi model slug.
54
75
  PI_DEFAULT_MODEL=
76
+ # off, minimal, low, medium, high, or xhigh.
77
+ # Options: off, minimal, low, medium, high, xhigh
55
78
  PI_DEFAULT_THINKING=medium
79
+ # default, readonly, no-tools, offline, or safe-offline.
80
+ # Options: default, readonly, no-tools, offline, safe-offline
56
81
  PI_DEFAULT_PROFILE=default
57
82
 
58
- # Hermes Agent defaults. HERMES_DEFAULT_REASONING: none, minimal, low,
59
- # medium, high, xhigh. HERMES_API_KEY must match API_SERVER_KEY when the
60
- # Hermes API Server is protected.
83
+ # Hermes
84
+ # Hermes Agent defaults. Hermes uses the Hermes API Server.
85
+ # Optional Hermes executable path.
61
86
  HERMES_CLI_PATH=
87
+ # Optional Hermes home directory. Defaults to ~/.hermes.
62
88
  HERMES_HOME=
89
+ # Optional explicit Hermes state.db path.
63
90
  HERMES_STATE_DB_PATH=
91
+ # Hermes API Server base URL.
64
92
  HERMES_API_BASE_URL=http://127.0.0.1:8642
93
+ # Bearer token for the Hermes API Server.
65
94
  HERMES_API_KEY=
95
+ # Default model label sent to Hermes API runs.
66
96
  HERMES_DEFAULT_MODEL=
97
+ # none, minimal, low, medium, high, or xhigh.
98
+ # Options: none, minimal, low, medium, high, xhigh
67
99
  HERMES_DEFAULT_REASONING=
100
+ # default, safe, readonly, or yolo.
101
+ # Options: default, safe, readonly, yolo
68
102
  HERMES_DEFAULT_PROFILE=default
69
103
 
70
- # OpenClaw Agent defaults. OPENCLAW_DEFAULT_THINKING: off, minimal, low,
71
- # medium, high, xhigh. Gateway token/password are optional unless your
72
- # OpenClaw Gateway requires shared-secret authentication.
104
+ # OpenClaw
105
+ # OpenClaw Agent defaults. OpenClaw uses the OpenClaw Gateway WebSocket RPC endpoint.
106
+ # Optional OpenClaw executable path.
73
107
  OPENCLAW_CLI_PATH=
108
+ # OpenClaw Gateway WebSocket URL.
74
109
  OPENCLAW_GATEWAY_URL=ws://127.0.0.1:18789
110
+ # Shared-secret token for the OpenClaw Gateway.
75
111
  OPENCLAW_GATEWAY_TOKEN=
112
+ # Shared-secret password for the OpenClaw Gateway.
76
113
  OPENCLAW_GATEWAY_PASSWORD=
114
+ # Configured OpenClaw agent id, for example main or work.
77
115
  OPENCLAW_AGENT_ID=main
116
+ # Optional OpenClaw home directory. Defaults to ~/.openclaw.
78
117
  OPENCLAW_HOME=
118
+ # Optional OpenClaw state directory.
79
119
  OPENCLAW_STATE_DIR=
120
+ # Default OpenClaw model id.
80
121
  OPENCLAW_DEFAULT_MODEL=
122
+ # off, minimal, low, medium, high, or xhigh.
123
+ # Options: off, minimal, low, medium, high, xhigh
81
124
  OPENCLAW_DEFAULT_THINKING=
125
+ # default, safe, readonly, local, or deliver.
126
+ # Options: default, safe, readonly, local, deliver
82
127
  OPENCLAW_DEFAULT_PROFILE=default
83
128
 
84
- # Claude Code defaults. CLAUDE_CODE_DEFAULT_EFFORT: off, low, medium, high,
85
- # xhigh. CLAUDE_CODE_CLI_PATH is optional; NordRelay uses `claude` on PATH or
86
- # the Claude Agent SDK bundled runtime.
129
+ # Claude Code
130
+ # Claude Code defaults. NordRelay uses the Claude Agent SDK and the host claude CLI when present.
131
+ # Optional Claude Code executable path. Defaults to claude on PATH or the SDK bundled runtime.
87
132
  CLAUDE_CODE_CLI_PATH=
133
+ # Optional Claude config directory. Defaults to ~/.claude.
88
134
  CLAUDE_CONFIG_DIR=
135
+ # Default Claude Code model alias or model id.
89
136
  CLAUDE_CODE_DEFAULT_MODEL=
137
+ # off, low, medium, high, or xhigh.
138
+ # Options: off, low, medium, high, xhigh
90
139
  CLAUDE_CODE_DEFAULT_EFFORT=
140
+ # default, accept-edits, plan, readonly, no-tools, or bypass-permissions.
141
+ # Options: default, accept-edits, plan, readonly, no-tools, bypass-permissions
91
142
  CLAUDE_CODE_DEFAULT_PROFILE=default
143
+ # Maximum agentic turns for each Claude Code prompt.
92
144
  CLAUDE_CODE_MAX_TURNS=100
93
145
 
94
- # Telegram output controls.
146
+ # Operations
147
+ # Runtime output, logging, update, and Telegram behavior controls.
148
+ # text or json.
149
+ # Options: text, json
95
150
  CONNECTOR_LOG_FORMAT=text
151
+ # all, summary, errors-only, or none.
152
+ # Options: all, summary, errors-only, none
96
153
  TOOL_VERBOSITY=summary
154
+ # Append per-turn token usage.
97
155
  SHOW_TURN_TOKEN_USAGE=false
156
+ # Allow /login and /logout.
98
157
  ENABLE_TELEGRAM_LOGIN=true
158
+ # Send Telegram reactions.
99
159
  ENABLE_TELEGRAM_REACTIONS=false
160
+ # Minimum send interval.
100
161
  TELEGRAM_RATE_LIMIT_MIN_INTERVAL_MS=80
162
+ # Minimum edit interval.
101
163
  TELEGRAM_EDIT_MIN_INTERVAL_MS=1200
102
- TELEGRAM_TRANSPORT=polling
103
- TELEGRAM_WEBHOOK_URL=
104
- TELEGRAM_WEBHOOK_HOST=127.0.0.1
105
- TELEGRAM_WEBHOOK_PORT=8080
106
- TELEGRAM_WEBHOOK_PATH=/telegram/webhook
107
- TELEGRAM_WEBHOOK_SECRET=
164
+ # off, status, final, or full.
165
+ # Options: off, status, final, full
108
166
  TELEGRAM_CLI_MIRROR_MODE=status
167
+ # Minimum mirrored edit interval.
109
168
  TELEGRAM_CLI_MIRROR_MIN_UPDATE_MS=4000
169
+ # off, minimal, or all.
170
+ # Options: off, minimal, all
110
171
  TELEGRAM_NOTIFY_MODE=minimal
172
+ # HH-HH or blank.
111
173
  TELEGRAM_QUIET_HOURS=
174
+ # Additional comma-separated regex patterns.
112
175
  TELEGRAM_REDACT_PATTERNS=
176
+ # auto, npm, or git.
177
+ # Options: auto, npm, git
178
+ NORDRELAY_UPDATE_METHOD=
179
+
180
+ # Artifacts
181
+ # File, artifact, and retention controls.
182
+ # Max inbound/outbound file size.
113
183
  MAX_FILE_SIZE=20971520
184
+ # Days before pruning.
114
185
  ARTIFACT_RETENTION_DAYS=7
186
+ # Maximum artifact turns retained.
115
187
  ARTIFACT_MAX_TURNS=30
188
+ # Maximum inbox dirs retained.
116
189
  ARTIFACT_MAX_INBOX_DIRS=30
190
+ # Extra ignored dirs or relative paths.
117
191
  ARTIFACT_IGNORE_DIRS=
192
+ # Extra ignored glob patterns.
118
193
  ARTIFACT_IGNORE_GLOBS=
194
+ # Automatically send artifact files.
119
195
  TELEGRAM_AUTO_SEND_ARTIFACTS=false
120
196
 
121
- # State and team controls. Use sqlite for a single-file state database when
122
- # better-sqlite3 is available; json keeps separate human-readable files.
197
+ # Workspace
198
+ # State and workspace guardrails.
199
+ # Restrict selectable workspaces.
200
+ WORKSPACE_ALLOWED_ROOTS=
201
+ # Warn for broad workspace roots.
202
+ WORKSPACE_WARN_ROOTS=
203
+ # json or sqlite.
204
+ # Options: json, sqlite
123
205
  NORDRELAY_STATE_BACKEND=json
206
+ # Retained audit events.
124
207
  NORDRELAY_AUDIT_MAX_EVENTS=1000
208
+ # Write-lock TTL.
125
209
  NORDRELAY_SESSION_LOCK_TTL_MS=1800000
210
+ # NPM version cache TTL.
126
211
  NORDRELAY_VERSION_CACHE_TTL_MS=3600000
127
212
 
128
- # Local WebUI dashboard. Binding to 0.0.0.0 requires either token auth or
129
- # basic auth; startup fails without one of these credentials.
130
- NORDRELAY_DASHBOARD_HOST=127.0.0.1
131
- NORDRELAY_DASHBOARD_PORT=31878
132
- NORDRELAY_DASHBOARD_TOKEN=
133
- NORDRELAY_DASHBOARD_USER=
134
- NORDRELAY_DASHBOARD_PASSWORD=
135
- NORDRELAY_ENV_FILE=
136
-
137
- # Optional workspace guardrails. Leave WORKSPACE_ALLOWED_ROOTS empty to allow
138
- # all workspaces discovered from enabled agent state.
139
- WORKSPACE_ALLOWED_ROOTS=
140
- WORKSPACE_WARN_ROOTS=
141
-
142
- # Optional voice transcription fallback. Local parakeet-coreml is used first
143
- # when installed; OpenAI Whisper is used when OPENAI_API_KEY is set.
213
+ # Voice
214
+ # Optional voice transcription settings.
215
+ # Whisper fallback API key.
144
216
  OPENAI_API_KEY=
217
+ # auto, parakeet, faster-whisper, or openai.
218
+ # Options: auto, parakeet, faster-whisper, openai
145
219
  VOICE_PREFERRED_BACKEND=auto
220
+ # Default transcription language.
146
221
  VOICE_DEFAULT_LANGUAGE=
222
+ # Do not send voice transcripts as prompts.
147
223
  VOICE_TRANSCRIBE_ONLY=false
224
+ # Python executable.
148
225
  FASTER_WHISPER_PYTHON=.venv/bin/python
226
+ # Model name.
149
227
  FASTER_WHISPER_MODEL=base
228
+ # cpu, cuda, etc.
150
229
  FASTER_WHISPER_DEVICE=cpu
230
+ # int8, float16, etc.
151
231
  FASTER_WHISPER_COMPUTE_TYPE=int8
232
+ # Fixed transcription language.
152
233
  FASTER_WHISPER_LANGUAGE=
234
+ # Transcription timeout.
153
235
  FASTER_WHISPER_TIMEOUT_MS=600000
236
+
237
+ # Dashboard
238
+ # Local WebUI dashboard. User login is required for every page, API route, SSE stream, artifact download, and health endpoint.
239
+ # WebUI bind host.
240
+ NORDRELAY_DASHBOARD_HOST=127.0.0.1
241
+ # WebUI bind port.
242
+ NORDRELAY_DASHBOARD_PORT=31878
243
+ # Optional explicit env-file path used by the CLI wrapper and dashboard.
244
+ NORDRELAY_ENV_FILE=
package/README.md CHANGED
@@ -36,9 +36,9 @@ Session control:
36
36
  - `/status`, `/health`, and `/version` report connector runtime health from Telegram.
37
37
  - `/tasks` and `/progress` show the current turn status, queue length, active tool, elapsed time, and last error.
38
38
  - `/activity` shows a compact timeline of recent rollout events for the active thread, with filters and export.
39
- - `/diagnostics` reports redacted runtime, config, role, Telegram rate-limit, mirror, voice, session, queue, and progress details for admins.
39
+ - `/diagnostics` reports redacted runtime, config, user/group authorization, Telegram rate-limit, mirror, voice, session, queue, and progress details.
40
40
  - `/lock`, `/unlock`, and `/locks` provide a team write-lock for shared sessions so one user can operate while others watch.
41
- - `/audit` shows recent prompt, queue, lock, and command audit events for admins.
41
+ - `/audit` shows recent prompt, queue, lock, command, authentication, permission-denied, user, group, Telegram-link, Telegram-chat, and web-session audit events for admins.
42
42
 
43
43
  Adapter architecture:
44
44
 
@@ -46,7 +46,7 @@ Adapter architecture:
46
46
  - `/channels` shows available and planned messaging adapters for Discord, WhatsApp, Slack, and Matrix.
47
47
  - Codex, Pi, Hermes, OpenClaw, and Claude Code are implemented as agent adapters.
48
48
  - `/agents` shows available/planned agent adapters and whether Codex, Pi, Hermes, OpenClaw, and Claude Code are enabled.
49
- - Shared command-action renderers keep channel-neutral responses for adapter lists, queues, artifacts, logs, and update jobs separate from Telegram-specific keyboards and delivery.
49
+ - Shared command-action renderers and a channel runtime contract keep inbound commands, outbound messages, typing, files, inline actions, and streaming-ready delivery separate from Telegram-specific API calls.
50
50
 
51
51
  Codex runtime:
52
52
 
@@ -160,13 +160,17 @@ Telegram output:
160
160
 
161
161
  Authentication and safety:
162
162
 
163
- - Telegram access requires `TELEGRAM_ADMIN_USER_IDS` by default; a fresh install only accepts those admin user ids.
164
- - `TELEGRAM_ALLOWED_USER_IDS` can add non-admin operators.
165
- - `TELEGRAM_ALLOWED_CHAT_IDS` is supported for private chats, groups, and backward compatibility.
166
- - `TELEGRAM_ALLOW_ANY_CHAT=true` is an explicit unsafe override for temporary local setup only.
167
- - `TELEGRAM_ADMIN_USER_IDS` restricts admin-only commands such as `/logs`, `/restart`, and `/update`.
168
- - `TELEGRAM_READONLY_USER_IDS` can inspect status and sessions but cannot send prompts or run mutating commands by default.
169
- - `TELEGRAM_ROLE_POLICIES_JSON` can override role permissions for `admin`, `operator`, and `readonly`.
163
+ - WebUI login is required for every dashboard page, API route, SSE stream, artifact download, and health endpoint.
164
+ - Access is managed through NordRelay users, groups, permissions, web sessions, and linked Telegram identities.
165
+ - Built-in groups are `Admin`, `User`, and `Read Only`; custom groups can be created in the WebUI and can restrict allowed agents, workspace roots, and Telegram chats.
166
+ - The last active admin cannot be disabled or demoted, and web sessions are revoked when passwords or group memberships change.
167
+ - Admins can review and revoke active WebUI sessions from the Users page.
168
+ - Telegram private chats require a linked active NordRelay user.
169
+ - Telegram group and forum chats must be registered before use; admins can run `/register_chat` in the chat or enable chats in the WebUI.
170
+ - `/whoami` shows the linked NordRelay account and groups.
171
+ - `/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`.
172
+ - WebUI login and Telegram link attempts are rate-limited to reduce brute-force risk.
173
+ - User, group, Telegram-link, Telegram-chat, web-session, login, and permission-denied events are written to the audit log.
170
174
  - `/auth` reports Codex authentication, Pi provider environment health, Hermes API Server reachability, OpenClaw Gateway reachability, or Claude Code CLI auth for the selected agent.
171
175
  - `/login` starts Telegram-managed CLI auth for Codex, Hermes, or Claude Code when enabled.
172
176
  - `/logout` signs out of CLI auth for Codex, Hermes, or Claude Code; Codex logout is disabled while `CODEX_API_KEY` is in use.
@@ -192,7 +196,7 @@ Operations:
192
196
  - The WebUI has responsive header/sidebar/footer navigation, live chat streaming, session controls, queue/artifact/log/diagnostic views, and settings management.
193
197
  - The WebUI supports light and dark themes, tabbed settings groups, paginated session browsing, and chat uploads for images, documents, and audio transcription.
194
198
  - The WebUI exposes REST and SSE endpoints for chat streaming, sessions, settings, queue, artifacts, logs, health, and diagnostics.
195
- - Binding the dashboard to `0.0.0.0` is refused unless `NORDRELAY_DASHBOARD_TOKEN` or `NORDRELAY_DASHBOARD_USER` plus `NORDRELAY_DASHBOARD_PASSWORD` is configured.
199
+ - The dashboard can bind to `127.0.0.1` or `0.0.0.0`; user login and session cookies are mandatory in both modes.
196
200
  - Telegram can run with long polling or an HTTP webhook via `TELEGRAM_TRANSPORT=webhook`.
197
201
  - Version freshness checks are cached with `NORDRELAY_VERSION_CACHE_TTL_MS` to keep `/version` responsive.
198
202
  - CI includes typecheck, tests, package dry run, npm audit, and a separate secret-scan workflow.
@@ -207,6 +211,7 @@ Recommended npm setup:
207
211
  ```bash
208
212
  npm install -g @nordbyte/nordrelay
209
213
  nordrelay init
214
+ nordrelay user list
210
215
  nordrelay doctor
211
216
  nordrelay start
212
217
  ```
@@ -216,9 +221,16 @@ npm is the fastest install path and is the recommended default for normal use. `
216
221
  Non-interactive setup is also supported:
217
222
 
218
223
  ```bash
219
- nordrelay init --token 123456789:replace-me --admin-id 123456789
224
+ nordrelay init \
225
+ --token 123456789:replace-me \
226
+ --admin-email you@example.com \
227
+ --admin-name "Your Name" \
228
+ --admin-password "replace-with-a-long-password" \
229
+ --telegram-user-id 123456789
220
230
  ```
221
231
 
232
+ `--telegram-user-id` is optional, but linking the first admin during setup is the fastest way to use Telegram immediately.
233
+
222
234
  Source checkout setup:
223
235
 
224
236
  Install dependencies and build the runtime:
@@ -237,14 +249,13 @@ Create the Telegram bot:
237
249
  2. Run `/newbot`.
238
250
  3. Choose a display name and bot username.
239
251
  4. Copy the bot token into `TELEGRAM_BOT_TOKEN` in `~/.nordrelay/nordrelay.env`.
240
- 5. Find your Telegram user id with a trusted id helper bot, for example `@userinfobot`, or from Telegram API tooling.
241
- 6. Put your user id into `TELEGRAM_ADMIN_USER_IDS`.
252
+ 5. Create the first admin user with `nordrelay init` or `nordrelay user create-admin`.
253
+ 6. Link Telegram from the WebUI, with `nordrelay user link-telegram`, or by creating a link code and sending `/link <code>` to the bot.
242
254
 
243
255
  Minimal private-bot `~/.nordrelay/nordrelay.env`:
244
256
 
245
257
  ```dotenv
246
258
  TELEGRAM_BOT_TOKEN=123456789:replace-me
247
- TELEGRAM_ADMIN_USER_IDS=123456789
248
259
  NORDRELAY_CODEX_ENABLED=true
249
260
  NORDRELAY_PI_ENABLED=false
250
261
  NORDRELAY_HERMES_ENABLED=false
@@ -255,13 +266,14 @@ CODEX_SANDBOX_MODE=workspace-write
255
266
  CODEX_APPROVAL_POLICY=never
256
267
  ```
257
268
 
258
- Optional non-admin operators can be added with:
259
-
260
- ```dotenv
261
- TELEGRAM_ALLOWED_USER_IDS=234567890,345678901
262
- ```
269
+ User and Telegram access management:
263
270
 
264
- Do not use `TELEGRAM_ALLOW_ANY_CHAT=true` for normal coding sessions. It makes the bot reachable from any Telegram chat that can message it.
271
+ - `nordrelay init` creates the first admin user and writes `~/.nordrelay/users.json`.
272
+ - `nordrelay user create-admin --email you@example.com --name "Your Name"` creates another admin.
273
+ - `nordrelay user create --email dev@example.com --name "Dev" --group user` creates a normal user.
274
+ - `nordrelay user link-telegram --email you@example.com --telegram-user-id 123456789` links a Telegram account directly.
275
+ - `nordrelay user link-code --email you@example.com` creates a short-lived code that the user sends as `/link <code>` to the bot.
276
+ - Group chats are disabled until an admin enables them from the WebUI or runs `/register_chat` inside the group.
265
277
 
266
278
  Codex authentication:
267
279
 
@@ -334,7 +346,7 @@ Where Codex exposes namespaced plugin commands, this also works:
334
346
  /nordrelay:remote
335
347
  ```
336
348
 
337
- The old unnamespaced `/remote` command is no longer required and current Codex TUI builds do not register it as a top-level plugin slash command. The command is only a process-manager shortcut; Telegram contains the actual controls.
349
+ The command is only a process-manager shortcut; Telegram contains the actual controls.
338
350
 
339
351
  Manual process commands:
340
352
 
@@ -357,6 +369,7 @@ node plugins/nordrelay/scripts/nordrelay.mjs status
357
369
  node plugins/nordrelay/scripts/nordrelay.mjs restart
358
370
  node plugins/nordrelay/scripts/nordrelay.mjs stop
359
371
  node plugins/nordrelay/scripts/nordrelay.mjs foreground
372
+ node plugins/nordrelay/scripts/nordrelay.mjs user list
360
373
  node plugins/nordrelay/scripts/nordrelay.mjs doctor
361
374
  node plugins/nordrelay/scripts/nordrelay.mjs web
362
375
  ```
@@ -411,8 +424,8 @@ The dashboard is a second NordRelay client next to Telegram. It can:
411
424
  - Edit all supported runtime settings from tabbed Settings groups with option selects, validation feedback, and restart actions.
412
425
  - View filtered connector/update/agent-update logs, structured diagnostics, enabled channels, and agent adapters.
413
426
  - Inspect a per-agent capability matrix showing model, reasoning, launch, fast mode, attachments, activity, usage, auth, login/logout, and handback support.
414
- - Check NordRelay and agent CLI versions, then start Codex, Pi, Hermes, OpenClaw, or Claude Code updates from outdated version rows with live output, cancel, full-log, and stdin response controls for interactive updaters.
415
- - Load dashboard CSS and client JavaScript as authenticated static assets instead of inline HTML, keeping the server shell, style, and browser client modules separate.
427
+ - Check NordRelay and agent CLI versions, then start Codex, Pi, Hermes, OpenClaw, or Claude Code updates from outdated version rows with live output, cancel, delete-log, and stdin response controls for interactive updaters.
428
+ - Build dashboard CSS and client JavaScript from modular source assets through esbuild, then serve them as authenticated static assets instead of inline HTML.
416
429
 
417
430
  Dashboard API endpoints are served under `/api/*`. Streaming uses `GET /api/events`.
418
431
 
@@ -421,13 +434,9 @@ Dashboard auth:
421
434
  ```dotenv
422
435
  NORDRELAY_DASHBOARD_HOST=127.0.0.1
423
436
  NORDRELAY_DASHBOARD_PORT=31878
424
- NORDRELAY_DASHBOARD_TOKEN=replace-with-random-token
425
- # or:
426
- NORDRELAY_DASHBOARD_USER=admin
427
- NORDRELAY_DASHBOARD_PASSWORD=replace-with-random-password
428
437
  ```
429
438
 
430
- When `NORDRELAY_DASHBOARD_HOST=0.0.0.0`, NordRelay refuses to start the dashboard unless token or basic auth is configured. Login cookies use `SameSite=Strict`, and every dashboard route, API endpoint, SSE stream, artifact download, and health endpoint requires the same auth.
439
+ 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.
431
440
 
432
441
  Webhook mode:
433
442
 
@@ -440,7 +449,7 @@ TELEGRAM_WEBHOOK_PATH=/telegram/webhook
440
449
  TELEGRAM_WEBHOOK_SECRET=replace-with-random-secret
441
450
  ```
442
451
 
443
- Run NordRelay behind your reverse proxy so the public URL forwards to `http://127.0.0.1:8080/telegram/webhook`. `GET /healthz` returns a simple health check.
452
+ 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`.
444
453
 
445
454
  ## Telegram Commands
446
455
 
@@ -449,6 +458,9 @@ Run NordRelay behind your reverse proxy so the public URL forwards to `http://12
449
458
  - `/channels` shows available and planned messaging adapters.
450
459
  - `/agents` shows available and planned coding-agent adapters.
451
460
  - `/agent` selects the active agent for this Telegram context.
461
+ - `/link <code>` links the Telegram account to a NordRelay user.
462
+ - `/whoami` shows the linked NordRelay user, groups, and permissions.
463
+ - `/register_chat` enables the current Telegram group or forum chat for NordRelay when the linked user has user-management permission.
452
464
  - `/new` starts a new thread. If the selected agent knows multiple workspaces, Telegram shows a workspace picker.
453
465
  - `/session` shows current thread details.
454
466
  - `/sessions` opens a paginated recent-session picker.
@@ -472,7 +484,7 @@ Run NordRelay behind your reverse proxy so the public URL forwards to `http://12
472
484
  - `/cancel <queue-id>` removes one queued prompt; the queue id is the short code shown in messages such as `Queued prompt 332kmt`.
473
485
  - `/clearqueue` clears queued prompts for this Telegram context.
474
486
  - `/activity [all|tools|errors|user|agent|tasks] [limit] [since 1h] [export]` shows or exports rollout activity for the active thread.
475
- - `/audit [limit]` shows recent audit events. Admin only.
487
+ - `/audit [limit]` shows recent audit events. Requires `audit.read`.
476
488
  - `/lock` locks writes for this Telegram session to the current user.
477
489
  - `/unlock` releases the current session write lock.
478
490
  - `/locks` lists active write locks.
@@ -499,14 +511,14 @@ Run NordRelay behind your reverse proxy so the public URL forwards to `http://12
499
511
  - `/status` reports connector runtime status.
500
512
  - `/health` reports runtime health, auth, PIDs, Codex CLI, Pi CLI, Hermes CLI, OpenClaw CLI, Claude Code CLI, and state DB.
501
513
  - `/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.
502
- - `/logs [lines]` shows a redacted, timestamped connector log tail. Admin only.
503
- - `/logs update [lines]` shows the self-update log. Admin only.
504
- - `/logs agent [lines]` shows the aggregate agent updater log. Admin only.
505
- - `/logs all [lines]` shows connector, self-update, and agent update logs together. Admin only.
506
- - `/diagnostics` shows redacted connector diagnostics. Admin only.
507
- - `/restart` restarts the connector process. Admin only.
508
- - `/update` updates through npm or git depending on the detected install type, then restarts only on success. Admin only.
509
- - `/update agents`, `/update <agent>`, `/update jobs`, `/update log <id>`, `/update cancel <id>`, and `/update input <id> <text>` manage agent CLI update jobs. Admin only.
514
+ - `/logs [lines]` shows a redacted, timestamped connector log tail. Requires `logs.read`.
515
+ - `/logs update [lines]` shows the self-update log. Requires `logs.read`.
516
+ - `/logs agent [lines]` shows the aggregate agent updater log. Requires `logs.read`.
517
+ - `/logs all [lines]` shows connector, self-update, and agent update logs together. Requires `logs.read`.
518
+ - `/diagnostics` shows redacted connector diagnostics. Requires `logs.read`.
519
+ - `/restart` restarts the connector process. Requires `system.restart`.
520
+ - `/update` updates through npm or git depending on the detected install type, then restarts only on success. Requires `updates.run`.
521
+ - `/update agents`, `/update <agent>`, `/update jobs`, `/update log <id>`, `/update cancel <id>`, and `/update input <id> <text>` manage agent CLI update jobs. Requires `updates.run`.
510
522
 
511
523
  ## Command Examples
512
524
 
@@ -689,12 +701,6 @@ Voice transcription uses `OPENAI_API_KEY`, not `CODEX_API_KEY`.
689
701
  Telegram:
690
702
 
691
703
  - `TELEGRAM_BOT_TOKEN`: required BotFather token.
692
- - `TELEGRAM_ADMIN_USER_IDS`: required comma-separated Telegram user ids allowed to use admin commands. Admin ids are automatically allowed to use the bot.
693
- - `TELEGRAM_ALLOWED_USER_IDS`: optional comma-separated non-admin Telegram user ids allowed to use the bot.
694
- - `TELEGRAM_READONLY_USER_IDS`: comma-separated Telegram user ids that can inspect status and sessions but cannot run prompts or mutating commands.
695
- - `TELEGRAM_ALLOWED_CHAT_IDS`: comma-separated chat ids allowed to use the bot. Group ids may be negative.
696
- - `TELEGRAM_ALLOW_ANY_CHAT`: allows all chats when `true`. Keep `false` unless you intentionally want an open bot.
697
- - `TELEGRAM_ROLE_POLICIES_JSON`: optional JSON object mapping roles to permissions. Permissions are `inspect`, `sessions`, `prompt`, `files`, `settings`, `auth`, and `admin`.
698
704
  - `TELEGRAM_RATE_LIMIT_MIN_INTERVAL_MS`: minimum interval for normal Telegram API sends. Defaults to `80`.
699
705
  - `TELEGRAM_EDIT_MIN_INTERVAL_MS`: minimum interval for Telegram message edits. Defaults to `1200`.
700
706
  - `TELEGRAM_TRANSPORT`: `polling` or `webhook`. Defaults to `polling`.
@@ -709,11 +715,13 @@ Telegram:
709
715
  - `TELEGRAM_QUIET_HOURS`: optional quiet-hour range in `HH-HH` format, for example `22-7`.
710
716
  - `TELEGRAM_REDACT_PATTERNS`: comma-separated regular expressions for additional Telegram/log redaction.
711
717
 
712
- Role policy example:
718
+ User management:
713
719
 
714
- ```dotenv
715
- TELEGRAM_ROLE_POLICIES_JSON={"readonly":["inspect","sessions"],"operator":["inspect","sessions","prompt","files"],"admin":"*"}
716
- ```
720
+ - Users, groups, Telegram identities, Telegram group-chat access, and web sessions are stored in `~/.nordrelay/users.json`.
721
+ - Manage users in the WebUI Users page or with `nordrelay user list`, `create-admin`, `create`, `reset-password`, `link-telegram`, and `link-code`.
722
+ - Built-in groups are `admin`, `user`, and `readonly`.
723
+ - 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`, and `audit.read`.
724
+ - Custom groups can also restrict access to specific agent ids, workspace roots, and Telegram chat ids.
717
725
 
718
726
  Agent selection:
719
727
 
@@ -732,9 +740,6 @@ Dashboard:
732
740
 
733
741
  - `NORDRELAY_DASHBOARD_HOST`: dashboard bind host. Defaults to `127.0.0.1`.
734
742
  - `NORDRELAY_DASHBOARD_PORT`: dashboard bind port. Defaults to `31878`.
735
- - `NORDRELAY_DASHBOARD_TOKEN`: optional dashboard bearer/login token. Required when binding to `0.0.0.0` unless basic auth is configured.
736
- - `NORDRELAY_DASHBOARD_USER`: optional dashboard basic-auth user.
737
- - `NORDRELAY_DASHBOARD_PASSWORD`: optional dashboard basic-auth password. Required with `NORDRELAY_DASHBOARD_USER`.
738
743
  - `NORDRELAY_ENV_FILE`: optional explicit env-file path used by the wrapper and edited by the dashboard settings page. Defaults to `~/.nordrelay/nordrelay.env`.
739
744
 
740
745
  Codex:
@@ -871,14 +876,14 @@ Unsafe profiles are intentionally gated. Telegram asks for confirmation before a
871
876
 
872
877
  ## Security Notes
873
878
 
874
- - Always set `TELEGRAM_ADMIN_USER_IDS`; a fresh install refuses to start without at least one admin user id.
875
- - Prefer `TELEGRAM_ADMIN_USER_IDS` and `TELEGRAM_ALLOWED_USER_IDS` over `TELEGRAM_ALLOWED_CHAT_IDS` for private bots.
876
- - Use `TELEGRAM_ALLOWED_CHAT_IDS` for groups or forum topics only when you trust the entire chat.
877
- - Do not leave `TELEGRAM_ALLOW_ANY_CHAT=true` enabled after setup.
879
+ - Create the first admin user during setup and keep that account protected with a strong password.
880
+ - Link Telegram accounts only to active NordRelay users that should control agents remotely.
881
+ - Enable Telegram group/forum chats only when the whole chat context is trusted for the permissions granted to linked users.
882
+ - Review group permissions before granting `prompt.send`, `prompt.abort`, `files.write`, `settings.write`, `updates.run`, `system.restart`, or `users.write`.
878
883
  - Treat `danger-full-access` as equivalent to shell access on the host.
879
884
  - Treat uploaded files as untrusted input. They are staged inside the active workspace so the selected sandbox policy still matters.
880
885
  - Keep `CODEX_API_KEY`, `HERMES_API_KEY`, `OPENCLAW_GATEWAY_TOKEN`, `OPENCLAW_GATEWAY_PASSWORD`, and `OPENAI_API_KEY` in `~/.nordrelay/nordrelay.env` or host secret management.
881
- - In group chats, remember that any allowed user can prompt the selected agent in that chat context.
886
+ - In group chats, remember that any linked user with prompt permissions can prompt the selected agent in that chat context.
882
887
  - Use `TOOL_VERBOSITY=summary` or `errors-only` when command output may include sensitive data.
883
888
  - Review and unsafe launch profiles add a Telegram approve/deny gate before each turn starts.
884
889
 
@@ -1035,19 +1040,24 @@ npm run build
1035
1040
  - `plugins/nordrelay/`: Codex plugin bundle with manifest, skill, command, icon, and process wrapper.
1036
1041
  - `plugins/nordrelay/scripts/nordrelay.mjs`: process manager for `start`, `stop`, `restart`, `status`, and `foreground`.
1037
1042
  - `src/index.ts`: runtime entrypoint, config load, auth check, state-file writes, polling lifecycle, shutdown.
1038
- - `src/bot.ts`: Telegram command handlers, callbacks, message streaming, file/photo/voice handling, artifacts, and error handling.
1043
+ - `src/bot.ts`: Telegram prompt/session runtime, streaming, file/photo/voice handling, artifacts, and error handling.
1044
+ - `src/telegram-access-commands.ts`, `src/telegram-update-commands.ts`, and `src/telegram-command-menu.ts`: focused Telegram command groups for access linking, update jobs, and command menu registration.
1045
+ - `src/channel-adapter.ts`, `src/channel-runtime.ts`, and `src/channel-actions.ts`: channel descriptors, generic command routing, outbound delivery contracts, and channel-neutral command responses.
1046
+ - `src/config-metadata.ts`: shared setting metadata used by the WebUI settings page and generated `.env.example`.
1047
+ - `src/webui/`: focused WebUI source assets for core runtime state/API helpers, overview rendering, live events, chat/session workflows, admin pages, and CSS sections.
1039
1048
  - `src/bot-preferences.ts`: per-context mirror, notification, quiet-hour, and voice preference persistence.
1040
1049
  - `src/telegram-rate-limit.ts`: centralized Telegram API send/edit/document rate limiting and retry-after tracking.
1041
1050
  - `src/persistence.ts`: atomic JSON/text writes with backup recovery.
1042
1051
  - `src/redaction.ts`: common secret redaction and custom redaction pattern support.
1043
1052
  - `src/workspace-policy.ts`: workspace allow/warn root evaluation.
1044
- - `src/access-control.ts`: Telegram role permissions and command/callback permission mapping.
1053
+ - `src/access-control.ts`: user/group permission definitions and command/callback/WebUI permission mapping.
1045
1054
  - `src/codex-session.ts`: Codex SDK service for new/resumed threads, streaming events, abort, model, reasoning, launch profiles, and handback.
1046
1055
  - `src/pi-session.ts`: Pi RPC service for JSONL RPC sessions, streaming events, abort, model, thinking, launch profiles, and handback.
1047
1056
  - `src/hermes-session.ts`: Hermes API Server service for streamed runs, stop, model, reasoning, launch profiles, attachments, and handback.
1048
1057
  - `src/openclaw-session.ts`: OpenClaw Gateway service for streamed runs, cancel, model, thinking, launch profiles, attachments, and handback.
1049
1058
  - `src/claude-code-session.ts`: Claude Agent SDK service for streamed runs, abort, model, effort, launch profiles, attachments, and handback.
1050
1059
  - `src/session-registry.ts`: per-chat/topic session registry and persisted context metadata.
1060
+ - `test/agent-adapter-contract.test.ts`: shared adapter contract coverage for descriptors, capability flags, reasoning options, launch profiles, and `AgentSessionService` method parity.
1051
1061
  - `src/session-format.ts`: compact Telegram rendering for session details, token usage, and limits.
1052
1062
  - `src/codex-state.ts`: reader for Codex `~/.codex/state_*.sqlite` thread, workspace, model, reasoning, sandbox, and approval metadata.
1053
1063
  - `src/pi-state.ts`: reader for Pi session JSONL files, activity timelines, diagnostics, and external busy detection.