nemoris 0.1.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.
Files changed (223) hide show
  1. package/.env.example +49 -0
  2. package/LICENSE +21 -0
  3. package/README.md +209 -0
  4. package/SECURITY.md +119 -0
  5. package/bin/nemoris +46 -0
  6. package/config/agents/agent.toml.example +28 -0
  7. package/config/agents/default.toml +22 -0
  8. package/config/agents/orchestrator.toml +18 -0
  9. package/config/delivery.toml +73 -0
  10. package/config/embeddings.toml +5 -0
  11. package/config/identity/default-purpose.md +1 -0
  12. package/config/identity/default-soul.md +3 -0
  13. package/config/identity/orchestrator-purpose.md +1 -0
  14. package/config/identity/orchestrator-soul.md +1 -0
  15. package/config/improvement-targets.toml +15 -0
  16. package/config/jobs/heartbeat-check.toml +30 -0
  17. package/config/jobs/memory-rollup.toml +46 -0
  18. package/config/jobs/workspace-health.toml +63 -0
  19. package/config/mcp.toml +16 -0
  20. package/config/output-contracts.toml +17 -0
  21. package/config/peers.toml +32 -0
  22. package/config/peers.toml.example +32 -0
  23. package/config/policies/memory-default.toml +10 -0
  24. package/config/policies/memory-heartbeat.toml +5 -0
  25. package/config/policies/memory-ops.toml +10 -0
  26. package/config/policies/tools-heartbeat-minimal.toml +8 -0
  27. package/config/policies/tools-interactive-safe.toml +8 -0
  28. package/config/policies/tools-ops-bounded.toml +8 -0
  29. package/config/policies/tools-orchestrator.toml +7 -0
  30. package/config/providers/anthropic.toml +15 -0
  31. package/config/providers/ollama.toml +5 -0
  32. package/config/providers/openai-codex.toml +9 -0
  33. package/config/providers/openrouter.toml +5 -0
  34. package/config/router.toml +22 -0
  35. package/config/runtime.toml +114 -0
  36. package/config/skills/self-improvement.toml +15 -0
  37. package/config/skills/telegram-onboarding-spec.md +240 -0
  38. package/config/skills/workspace-monitor.toml +15 -0
  39. package/config/task-router.toml +42 -0
  40. package/install.sh +50 -0
  41. package/package.json +90 -0
  42. package/src/auth/auth-profiles.js +169 -0
  43. package/src/auth/openai-codex-oauth.js +285 -0
  44. package/src/battle.js +449 -0
  45. package/src/cli/help.js +265 -0
  46. package/src/cli/output-filter.js +49 -0
  47. package/src/cli/runtime-control.js +704 -0
  48. package/src/cli-main.js +2763 -0
  49. package/src/cli.js +78 -0
  50. package/src/config/loader.js +332 -0
  51. package/src/config/schema-validator.js +214 -0
  52. package/src/config/toml-lite.js +8 -0
  53. package/src/daemon/action-handlers.js +71 -0
  54. package/src/daemon/healing-tick.js +87 -0
  55. package/src/daemon/health-probes.js +90 -0
  56. package/src/daemon/notifier.js +57 -0
  57. package/src/daemon/nurse.js +218 -0
  58. package/src/daemon/repair-log.js +106 -0
  59. package/src/daemon/rule-staging.js +90 -0
  60. package/src/daemon/rules.js +29 -0
  61. package/src/daemon/telegram-commands.js +54 -0
  62. package/src/daemon/updater.js +85 -0
  63. package/src/jobs/job-runner.js +78 -0
  64. package/src/mcp/consumer.js +129 -0
  65. package/src/memory/active-recall.js +171 -0
  66. package/src/memory/backend-manager.js +97 -0
  67. package/src/memory/backends/file-backend.js +38 -0
  68. package/src/memory/backends/qmd-backend.js +219 -0
  69. package/src/memory/embedding-guards.js +24 -0
  70. package/src/memory/embedding-index.js +118 -0
  71. package/src/memory/embedding-service.js +179 -0
  72. package/src/memory/file-index.js +177 -0
  73. package/src/memory/memory-signature.js +5 -0
  74. package/src/memory/memory-store.js +648 -0
  75. package/src/memory/retrieval-planner.js +66 -0
  76. package/src/memory/scoring.js +145 -0
  77. package/src/memory/simhash.js +78 -0
  78. package/src/memory/sqlite-active-store.js +824 -0
  79. package/src/memory/write-policy.js +36 -0
  80. package/src/onboarding/aliases.js +33 -0
  81. package/src/onboarding/auth/api-key.js +224 -0
  82. package/src/onboarding/auth/ollama-detect.js +42 -0
  83. package/src/onboarding/clack-prompter.js +77 -0
  84. package/src/onboarding/doctor.js +530 -0
  85. package/src/onboarding/lock.js +42 -0
  86. package/src/onboarding/model-catalog.js +344 -0
  87. package/src/onboarding/phases/auth.js +589 -0
  88. package/src/onboarding/phases/build.js +130 -0
  89. package/src/onboarding/phases/choose.js +82 -0
  90. package/src/onboarding/phases/detect.js +98 -0
  91. package/src/onboarding/phases/hatch.js +216 -0
  92. package/src/onboarding/phases/identity.js +79 -0
  93. package/src/onboarding/phases/ollama.js +345 -0
  94. package/src/onboarding/phases/scaffold.js +99 -0
  95. package/src/onboarding/phases/telegram.js +377 -0
  96. package/src/onboarding/phases/validate.js +204 -0
  97. package/src/onboarding/phases/verify.js +206 -0
  98. package/src/onboarding/platform.js +482 -0
  99. package/src/onboarding/status-bar.js +95 -0
  100. package/src/onboarding/templates.js +794 -0
  101. package/src/onboarding/toml-writer.js +38 -0
  102. package/src/onboarding/tui.js +250 -0
  103. package/src/onboarding/uninstall.js +153 -0
  104. package/src/onboarding/wizard.js +499 -0
  105. package/src/providers/anthropic.js +168 -0
  106. package/src/providers/base.js +247 -0
  107. package/src/providers/circuit-breaker.js +136 -0
  108. package/src/providers/ollama.js +163 -0
  109. package/src/providers/openai-codex.js +149 -0
  110. package/src/providers/openrouter.js +136 -0
  111. package/src/providers/registry.js +36 -0
  112. package/src/providers/router.js +16 -0
  113. package/src/runtime/bootstrap-cache.js +47 -0
  114. package/src/runtime/capabilities-prompt.js +25 -0
  115. package/src/runtime/completion-ping.js +99 -0
  116. package/src/runtime/config-validator.js +121 -0
  117. package/src/runtime/context-ledger.js +360 -0
  118. package/src/runtime/cutover-readiness.js +42 -0
  119. package/src/runtime/daemon.js +729 -0
  120. package/src/runtime/delivery-ack.js +195 -0
  121. package/src/runtime/delivery-adapters/local-file.js +41 -0
  122. package/src/runtime/delivery-adapters/openclaw-cli.js +94 -0
  123. package/src/runtime/delivery-adapters/openclaw-peer.js +98 -0
  124. package/src/runtime/delivery-adapters/shadow.js +13 -0
  125. package/src/runtime/delivery-adapters/standalone-http.js +98 -0
  126. package/src/runtime/delivery-adapters/telegram.js +104 -0
  127. package/src/runtime/delivery-adapters/tui.js +128 -0
  128. package/src/runtime/delivery-manager.js +807 -0
  129. package/src/runtime/delivery-store.js +168 -0
  130. package/src/runtime/dependency-health.js +118 -0
  131. package/src/runtime/envelope.js +114 -0
  132. package/src/runtime/evaluation.js +1089 -0
  133. package/src/runtime/exec-approvals.js +216 -0
  134. package/src/runtime/executor.js +500 -0
  135. package/src/runtime/failure-ping.js +67 -0
  136. package/src/runtime/flows.js +83 -0
  137. package/src/runtime/guards.js +45 -0
  138. package/src/runtime/handoff.js +51 -0
  139. package/src/runtime/identity-cache.js +28 -0
  140. package/src/runtime/improvement-engine.js +109 -0
  141. package/src/runtime/improvement-harness.js +581 -0
  142. package/src/runtime/input-sanitiser.js +72 -0
  143. package/src/runtime/interaction-contract.js +347 -0
  144. package/src/runtime/lane-readiness.js +226 -0
  145. package/src/runtime/migration.js +323 -0
  146. package/src/runtime/model-resolution.js +78 -0
  147. package/src/runtime/network.js +64 -0
  148. package/src/runtime/notification-store.js +97 -0
  149. package/src/runtime/notifier.js +256 -0
  150. package/src/runtime/orchestrator.js +53 -0
  151. package/src/runtime/orphan-reaper.js +41 -0
  152. package/src/runtime/output-contract-schema.js +139 -0
  153. package/src/runtime/output-contract-validator.js +439 -0
  154. package/src/runtime/peer-readiness.js +69 -0
  155. package/src/runtime/peer-registry.js +133 -0
  156. package/src/runtime/pilot-status.js +108 -0
  157. package/src/runtime/prompt-builder.js +261 -0
  158. package/src/runtime/provider-attempt.js +582 -0
  159. package/src/runtime/report-fallback.js +71 -0
  160. package/src/runtime/result-normalizer.js +183 -0
  161. package/src/runtime/retention.js +74 -0
  162. package/src/runtime/review.js +244 -0
  163. package/src/runtime/route-job.js +15 -0
  164. package/src/runtime/run-store.js +38 -0
  165. package/src/runtime/schedule.js +88 -0
  166. package/src/runtime/scheduler-state.js +434 -0
  167. package/src/runtime/scheduler.js +656 -0
  168. package/src/runtime/session-compactor.js +182 -0
  169. package/src/runtime/session-search.js +155 -0
  170. package/src/runtime/slack-inbound.js +249 -0
  171. package/src/runtime/ssrf.js +102 -0
  172. package/src/runtime/status-aggregator.js +330 -0
  173. package/src/runtime/task-contract.js +140 -0
  174. package/src/runtime/task-packet.js +107 -0
  175. package/src/runtime/task-router.js +140 -0
  176. package/src/runtime/telegram-inbound.js +1565 -0
  177. package/src/runtime/token-counter.js +134 -0
  178. package/src/runtime/token-estimator.js +59 -0
  179. package/src/runtime/tool-loop.js +200 -0
  180. package/src/runtime/transport-server.js +311 -0
  181. package/src/runtime/tui-server.js +411 -0
  182. package/src/runtime/ulid.js +44 -0
  183. package/src/security/ssrf-check.js +197 -0
  184. package/src/setup.js +369 -0
  185. package/src/shadow/bridge.js +303 -0
  186. package/src/skills/loader.js +84 -0
  187. package/src/tools/catalog.json +49 -0
  188. package/src/tools/cli-delegate.js +44 -0
  189. package/src/tools/mcp-client.js +106 -0
  190. package/src/tools/micro/cancel-task.js +6 -0
  191. package/src/tools/micro/complete-task.js +6 -0
  192. package/src/tools/micro/fail-task.js +6 -0
  193. package/src/tools/micro/http-fetch.js +74 -0
  194. package/src/tools/micro/index.js +36 -0
  195. package/src/tools/micro/lcm-recall.js +60 -0
  196. package/src/tools/micro/list-dir.js +17 -0
  197. package/src/tools/micro/list-skills.js +46 -0
  198. package/src/tools/micro/load-skill.js +38 -0
  199. package/src/tools/micro/memory-search.js +45 -0
  200. package/src/tools/micro/read-file.js +11 -0
  201. package/src/tools/micro/session-search.js +54 -0
  202. package/src/tools/micro/shell-exec.js +43 -0
  203. package/src/tools/micro/trigger-job.js +79 -0
  204. package/src/tools/micro/web-search.js +58 -0
  205. package/src/tools/micro/workspace-paths.js +39 -0
  206. package/src/tools/micro/write-file.js +14 -0
  207. package/src/tools/micro/write-memory.js +41 -0
  208. package/src/tools/registry.js +348 -0
  209. package/src/tools/tool-result-contract.js +36 -0
  210. package/src/tui/chat.js +835 -0
  211. package/src/tui/renderer.js +175 -0
  212. package/src/tui/socket-client.js +217 -0
  213. package/src/utils/canonical-json.js +29 -0
  214. package/src/utils/compaction.js +30 -0
  215. package/src/utils/env-loader.js +5 -0
  216. package/src/utils/errors.js +80 -0
  217. package/src/utils/fs.js +101 -0
  218. package/src/utils/ids.js +5 -0
  219. package/src/utils/model-context-limits.js +30 -0
  220. package/src/utils/token-budget.js +74 -0
  221. package/src/utils/usage-cost.js +25 -0
  222. package/src/utils/usage-metrics.js +14 -0
  223. package/vendor/smol-toml-1.5.2.tgz +0 -0
package/.env.example ADDED
@@ -0,0 +1,49 @@
1
+ # ============================================================
2
+ # Nemoris — Environment Variables
3
+ # Copy this file to .env and fill in your values
4
+ # Run: nemoris setup (walks you through the essentials)
5
+ # ============================================================
6
+
7
+ # ---- Anthropic (required for cloud AI) --------------------
8
+ NEMORIS_ANTHROPIC_API_KEY= # Get from console.anthropic.com
9
+
10
+ # ---- OpenRouter (optional — fallback + Perplexity search) --
11
+ OPENROUTER_API_KEY= # Get from openrouter.ai
12
+
13
+ # ---- Telegram (required for Telegram channel) -------------
14
+ NEMORIS_TELEGRAM_BOT_TOKEN= # From @BotFather on Telegram
15
+ NEMORIS_TELEGRAM_CHAT_ID= # Your Telegram user/chat ID
16
+ NEMORIS_ALLOW_ANY_CHAT=false # true = accept messages from any chat (dev only)
17
+ NEMORIS_ALLOW_TELEGRAM_DELIVERY=true # false = suppress outbound Telegram messages
18
+
19
+ # ---- Slack (optional) -------------------------------------
20
+ SLACK_BOT_TOKEN= # xoxb-... from Slack App dashboard
21
+ SLACK_SIGNING_SECRET= # From Slack App dashboard → Basic Info
22
+
23
+ # ---- Ollama (optional — local inference) ------------------
24
+ # Install from https://ollama.com then run: nemoris setup ollama
25
+ OLLAMA_BASE_URL=http://localhost:11434 # Override if Ollama runs on a different port
26
+ NEMORIS_OLLAMA_MODEL=kimi-k2.5 # Default local model
27
+
28
+ # ---- Runtime tuning (optional) ----------------------------
29
+ NEMORIS_RATE_LIMIT_MAX=10 # Max messages per window (default: 10)
30
+ NEMORIS_RATE_LIMIT_WINDOW_MS=60000 # Rate limit window in ms (default: 60000)
31
+ NEMORIS_IDENTITY_CACHE_TTL_MS=300000 # Identity cache TTL in ms (default: 5 min)
32
+
33
+ # ---- Provider mode (required at startup) ------------------
34
+ NEMORIS_ALLOW_PROVIDER_MODE=remote # "remote" or "local"
35
+ NEMORIS_ALLOW_REMOTE_PROVIDER_MODE=true
36
+
37
+ # ---- Advanced / internal ----------------------------------
38
+ NEMORIS_AGENT_NAME= # Override default agent name
39
+ NEMORIS_LIVE_ROOT= # Override live root path
40
+ NEMORIS_INIT_MODE= # "fresh" forces re-initialisation
41
+ NEMORIS_QUIET=false # Suppress startup logs
42
+ ANTHROPIC_THINKING_ENABLED=false # Enable /think extended thinking mode
43
+
44
+ # ---- Semantic embeddings (local via Ollama nomic-embed-text) --
45
+ # NEMORIS_ALLOW_EMBEDDINGS=1
46
+ # NEMORIS_ALLOW_REMOTE_EMBEDDINGS=0
47
+
48
+ # ---- Feature flags ----------------------------------------
49
+ NEMORIS_WEBHOOK_SECRET= # Optional — validates Telegram webhook payloads
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Lee Anderson
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,209 @@
1
+ <p align="left">
2
+ <img src="assets/logo.svg" alt="Nemoris" width="600">
3
+ </p>
4
+
5
+ [![npm](https://img.shields.io/npm/v/nemoris)](https://npmjs.com/package/nemoris)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
7
+ [![Tests](https://github.com/amzer24/nemoris/actions/workflows/main.yml/badge.svg)](https://github.com/amzer24/nemoris/actions/workflows/main.yml)
8
+ [![Node](https://img.shields.io/badge/node-%3E%3D22-brightgreen)](https://nodejs.org)
9
+
10
+ A personal AI agent runtime. Runs locally. Persistent memory, delivery guarantees, scheduled jobs, and self-healing — no cloud, no lock-in.
11
+
12
+ ```bash
13
+ npm install -g nemoris
14
+ ```
15
+
16
+ Most agent frameworks give you a chatbot that forgets everything between sessions and silently drops messages when something breaks.
17
+
18
+ ---
19
+
20
+ ## Why Nemoris
21
+
22
+ Nemoris fixes this with three things that actually work:
23
+
24
+ ### Active Memory
25
+ SQLite-backed semantic memory with embeddings, salience scoring, deduplication, and compaction. Your agents remember what matters across sessions — not just within them.
26
+
27
+ ### Delivery Guarantees
28
+ Criticality-classified message delivery with retry pipelines, ack tracking, and pending decision management. Messages don't get lost. Decisions don't fall through cracks.
29
+
30
+ ### Task Contracts
31
+ Structured task lifecycle with state machines, escalation chains, and explicit completion signals. When an agent starts something, it finishes it — or tells you why it didn't.
32
+
33
+ ---
34
+
35
+ ## Quick Start
36
+
37
+ ```bash
38
+ # Install globally
39
+ npm install -g nemoris
40
+
41
+ # Interactive setup (~2 minutes)
42
+ nemoris setup
43
+ ```
44
+
45
+ You'll need an API key from Anthropic or OpenRouter — or just use Ollama for free local models.
46
+
47
+ ```bash
48
+ # Start the daemon
49
+ nemoris start
50
+ ```
51
+
52
+ The setup wizard connects a provider, optionally wires up Telegram, and starts your first agent. Coming from OpenClaw? Run `nemoris migrate` — agents, jobs, and memory import in under 2 minutes.
53
+
54
+ ### Requirements
55
+
56
+ - **Node.js >= 22**
57
+ - **Ollama** (optional — free local models via [ollama.ai](https://ollama.ai))
58
+
59
+ ---
60
+
61
+ ## Providers
62
+
63
+ - **Anthropic** (Claude) — direct API with prompt caching
64
+ - **OpenRouter** — access to 100+ models
65
+ - **Ollama** — free local models, zero cloud dependency
66
+
67
+ ---
68
+
69
+ ## What You Get
70
+
71
+ | Feature | What it does |
72
+ |---------|-------------|
73
+ | **Active Memory** | Semantic search, embeddings, salience scoring, dedup, compaction — all in SQLite |
74
+ | **Self-Healing** | Nurse system with health probes, automatic repair, rule promotion, severity-tiered notifications |
75
+ | **Exec Approval** | Side-effect gating — approve or deny shell commands from Telegram before they run |
76
+ | **Task Contracts** | State machine lifecycle, escalation chains, completion pings, multi-agent coordination |
77
+ | **Context Compaction** | DAG-based session summarisation — long conversations stay fast and relevant |
78
+ | **Runtime Resilience** | Circuit breaker, near-duplicate detection, idempotent retries |
79
+ | **Session Search** | FTS5 full-text search over conversation history via `/search` and `session_search` tool |
80
+ | **MCP Consumer** | Connect external MCP servers as native tools — filesystem, GitHub, databases, anything |
81
+ | **Vision** | Telegram photos processed by vision-capable models |
82
+ | **Scheduled Jobs** | Cron-triggered and ad-hoc jobs land in the same unified queue as interactive messages |
83
+ | **Multi-Agent** | Agents trigger each other via task contracts and completion pings |
84
+ | **Telegram** | Chat with agents from your phone — slash commands, photos, reactions |
85
+ | **OpenClaw Migration** | Full import of agents, jobs, and memory |
86
+
87
+ ---
88
+
89
+ ## CLI Commands
90
+
91
+ ```bash
92
+ nemoris setup # Interactive setup wizard
93
+ nemoris start # Start the daemon
94
+ nemoris stop # Stop the daemon
95
+ nemoris status # Show running agents, jobs, providers
96
+ nemoris doctor # Health check and dependency report
97
+ nemoris migrate # Import from OpenClaw
98
+ nemoris mcp list # Show connected MCP servers and tools
99
+ ```
100
+
101
+ ## Telegram Commands
102
+
103
+ | Command | Description |
104
+ |---------|-------------|
105
+ | `/switch` | Switch who you're talking to |
106
+ | `/who` | Show current agent |
107
+ | `/status` | System status and usage |
108
+ | `/cost` | Today / week / month spending totals |
109
+ | `/search` | Search conversation history |
110
+ | `/logs` | Tail recent daemon logs |
111
+ | `/model` | Change AI model — `/model sonnet \| haiku \| opus` |
112
+ | `/clear` | Start a fresh conversation |
113
+ | `/stop` | Cancel current task |
114
+ | `/compact` | Free up memory (keeps recent turns) |
115
+ | `/exec_approve <id>` | Approve a pending exec command |
116
+ | `/exec_deny <id>` | Deny a pending exec command |
117
+ | `/agents` | List available agents |
118
+ | `/help` | Show all commands |
119
+
120
+ ---
121
+
122
+ ## Architecture
123
+
124
+ Nemoris runs as a single background daemon on your machine — no Docker, no cloud. Inbound messages enter a unified queue alongside scheduled jobs. The drain loop hydrates context (memory, history, tools), calls the LLM, executes tool calls with approval gating, writes to memory, and delivers responses. The Nurse watches everything and repairs what breaks.
125
+
126
+ ```
127
+ Telegram / MCP / CLI
128
+
129
+ ┌─────▼──────┐
130
+ │ Inbound │
131
+ │ Handler │
132
+ └─────┬──────┘
133
+
134
+ ┌─────▼──────┐ ┌────────────┐
135
+ │ Unified │◄────│ Scheduled │
136
+ │ Queue │ │ Jobs │
137
+ └─────┬──────┘ └────────────┘
138
+
139
+ ┌─────▼──────┐
140
+ │ Drain │
141
+ │ Loop │
142
+ └─────┬──────┘
143
+
144
+ ┌─────▼──────────────────────────────────┐
145
+ │ Executor │
146
+ │ ┌──────┐ ┌───────┐ ┌──────────────┐ │
147
+ │ │ LLM ├──► Tools ├──► Memory Write │ │
148
+ │ └──────┘ └───┬───┘ └──────────────┘ │
149
+ │ │ │
150
+ │ ┌──────▼──────┐ │
151
+ │ │ Exec Approve│ │
152
+ │ └─────────────┘ │
153
+ └─────┬──────────────────────────────────┘
154
+
155
+ ┌─────▼──────┐ ┌────────────┐
156
+ │ Delivery │ │ Nurse │
157
+ │ Pipeline │ │ (healing) │
158
+ └─────┬──────┘ └──────┬─────┘
159
+ │ │
160
+ ┌─────▼───┐ ┌────▼─────┐
161
+ │Telegram │ │ Probes & │
162
+ │Agent │ │ Repair │
163
+ │Webhook │ └──────────┘
164
+ └─────────┘
165
+ ```
166
+
167
+ ---
168
+
169
+ ## Platform Support
170
+
171
+ | Platform | Service Manager | Status |
172
+ |----------|----------------|--------|
173
+ | macOS | launchd | Full support |
174
+ | Linux | systemd (user) | Full support |
175
+ | Windows | PM2 | Supported (WSL2 recommended) |
176
+
177
+ ---
178
+
179
+ ## Development
180
+
181
+ Requires Node.js >= 22.
182
+
183
+ ```bash
184
+ git clone https://github.com/amzer24/nemoris.git
185
+ cd nemoris
186
+ npm install
187
+ npm test # 1179 tests
188
+ npm run test:e2e # End-to-end tests
189
+ ```
190
+
191
+ Agents are configured in TOML with their own identity files, memory, tool access, and workspace context. See `docs/` for specs and architecture decisions.
192
+
193
+ ---
194
+
195
+ ## Contributing
196
+
197
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup and guidelines.
198
+
199
+ Please read our [Code of Conduct](CODE_OF_CONDUCT.md) before participating.
200
+
201
+ ## Security
202
+
203
+ See [SECURITY.md](SECURITY.md) for our security policy and how to report vulnerabilities.
204
+
205
+ ---
206
+
207
+ ## License
208
+
209
+ [MIT](LICENSE)
package/SECURITY.md ADDED
@@ -0,0 +1,119 @@
1
+ # Security Policy
2
+
3
+ Nemoris is a local-first agent runtime for a single operator on a machine they control. It is powerful software: it can execute tools, talk to remote model providers, store local state, and deliver messages through channels like Telegram and Slack. Please read this file before deploying it on a machine that holds sensitive data.
4
+
5
+ ## Supported Versions
6
+
7
+ Security fixes are currently targeted at:
8
+
9
+ - the latest `main` branch
10
+ - the latest published npm release
11
+
12
+ Older versions may not receive backported fixes.
13
+
14
+ ## Reporting a Vulnerability
15
+
16
+ Please do not open public GitHub issues for security vulnerabilities.
17
+
18
+ Use one of these private channels instead:
19
+
20
+ - GitHub Security Advisories: [Report a vulnerability](https://github.com/amzer24/nemoris/security/advisories/new)
21
+ - Email fallback: `amzer24@gmail.com`
22
+
23
+ Please include:
24
+
25
+ - what you observed
26
+ - affected version or commit
27
+ - the smallest reliable reproduction
28
+ - impact assessment
29
+ - any mitigations you already tested
30
+
31
+ I will acknowledge a good-faith report as quickly as possible and work toward a coordinated fix before public disclosure.
32
+
33
+ ## Threat Model
34
+
35
+ Nemoris is designed for:
36
+
37
+ - a single user
38
+ - a machine or account they control
39
+ - explicitly configured workspaces and delivery channels
40
+ - operator-reviewed tool use and provider configuration
41
+
42
+ Nemoris is not designed to be:
43
+
44
+ - a hardened multi-tenant sandbox
45
+ - a safe environment for arbitrary untrusted users
46
+ - a drop-in remote execution service for strangers
47
+
48
+ If you need those guarantees, isolate Nemoris at the OS, VM, or container level rather than relying on prompt rules alone.
49
+
50
+ ## What Stays Local vs What Leaves the Machine
51
+
52
+ By default, Nemoris stores its runtime state locally under the install root, including:
53
+
54
+ - config manifests
55
+ - local state and SQLite databases
56
+ - auth profiles in `state/auth-profiles.json`
57
+ - daemon logs
58
+
59
+ Data leaves the machine when you enable external integrations, including:
60
+
61
+ - LLM provider calls to Anthropic, OpenRouter, OpenAI Codex, or other configured providers
62
+ - Telegram or Slack delivery and inbound messaging
63
+ - MCP servers or other network-capable tools
64
+
65
+ Treat those integrations as trust boundaries. Only enable the ones you intend to use.
66
+
67
+ ## Security Expectations and Non-Goals
68
+
69
+ Nemoris aims to be secure by default for a personal local runtime, but there are important limits:
70
+
71
+ - tool access is policy-bounded, but the runtime is still operating on your machine
72
+ - remote providers can receive prompt content, tool output, and uploaded content needed to complete a turn
73
+ - delivery adapters can send content to third-party services once enabled
74
+ - local state files should be treated as sensitive operator data
75
+
76
+ This means Nemoris should be run with the least privilege that still lets it do useful work.
77
+
78
+ ## Safe Deployment Guidance
79
+
80
+ Recommended:
81
+
82
+ - run Nemoris as your own user account, not a shared account
83
+ - keep workspaces narrow and intentional
84
+ - use least-privilege provider tokens
85
+ - leave delivery gates disabled until you are ready for live sends
86
+ - keep `.env` and `state/auth-profiles.json` private
87
+ - use explicit allowlists for Telegram/Slack users rather than broad access
88
+ - keep the runtime updated
89
+
90
+ Not recommended:
91
+
92
+ - pointing it at your whole home directory as a workspace
93
+ - running it as root
94
+ - sharing one install across untrusted users
95
+ - enabling remote delivery channels before validating auth and allowlists
96
+
97
+ ## Sensitive Files
98
+
99
+ Handle these as secrets:
100
+
101
+ - `.env`
102
+ - `state/auth-profiles.json`
103
+ - any provider or delivery tokens
104
+ - daemon logs that may contain identifiers or operational details
105
+
106
+ Do not paste those files into public issues.
107
+
108
+ ## Security-Focused Operations
109
+
110
+ Useful commands when validating a setup:
111
+
112
+ ```bash
113
+ nemoris doctor
114
+ nemoris status
115
+ nemoris logs
116
+ npm run publish:check
117
+ ```
118
+
119
+ If you are recovering from a token, install, or daemon problem, see [`docs/RECOVERY-FLOWS.md`](docs/RECOVERY-FLOWS.md).
package/bin/nemoris ADDED
@@ -0,0 +1,46 @@
1
+ #!/bin/sh
2
+ set -eu
3
+
4
+ SCRIPT_PATH=$0
5
+ while [ -L "$SCRIPT_PATH" ]; do
6
+ SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$SCRIPT_PATH")" && pwd)
7
+ LINK_TARGET=$(readlink "$SCRIPT_PATH")
8
+ case "$LINK_TARGET" in
9
+ /*) SCRIPT_PATH="$LINK_TARGET" ;;
10
+ *) SCRIPT_PATH="$SCRIPT_DIR/$LINK_TARGET" ;;
11
+ esac
12
+ done
13
+
14
+ ROOT_DIR=$(CDPATH= cd -- "$(dirname -- "$SCRIPT_PATH")/.." && pwd)
15
+ FILTERED_NODE_OPTIONS=""
16
+ SKIP_NEXT=0
17
+
18
+ for ARG in ${NODE_OPTIONS-}; do
19
+ if [ "$SKIP_NEXT" = "1" ]; then
20
+ SKIP_NEXT=0
21
+ case "$ARG" in
22
+ *disable_autoselectfamily.js*) continue ;;
23
+ *) FILTERED_NODE_OPTIONS="$FILTERED_NODE_OPTIONS $ARG"; continue ;;
24
+ esac
25
+ fi
26
+
27
+ case "$ARG" in
28
+ --require)
29
+ SKIP_NEXT=1
30
+ ;;
31
+ --require=*disable_autoselectfamily.js*)
32
+ ;;
33
+ *)
34
+ FILTERED_NODE_OPTIONS="$FILTERED_NODE_OPTIONS $ARG"
35
+ ;;
36
+ esac
37
+ done
38
+
39
+ FILTERED_NODE_OPTIONS=$(printf "%s" "$FILTERED_NODE_OPTIONS" | sed 's/^ //')
40
+ if [ -n "$FILTERED_NODE_OPTIONS" ]; then
41
+ export NODE_OPTIONS="$FILTERED_NODE_OPTIONS"
42
+ else
43
+ unset NODE_OPTIONS
44
+ fi
45
+
46
+ exec node "$ROOT_DIR/src/cli.js" "$@"
@@ -0,0 +1,28 @@
1
+ # Example agent configuration — copy this to create your own agent.
2
+ #
3
+ # cp agent.example.toml myagent.toml
4
+ # Then edit the values below.
5
+
6
+ id = "myagent"
7
+ primary_lane = "interactive_primary"
8
+ memory_policy = "default"
9
+ tool_policy = "interactive_safe"
10
+ soul_ref = "config/identity/myagent-soul.md"
11
+ purpose_ref = "config/identity/myagent-purpose.md"
12
+
13
+ # Where this agent reads/writes workspace files.
14
+ # Relative to the Nemoris install directory.
15
+ workspace_root = "workspace"
16
+
17
+ # Files loaded into context at the start of each turn (optional).
18
+ # workspace_context_files = ["MEMORY.md"]
19
+ # workspace_context_cap = 8000
20
+
21
+ [limits]
22
+ max_tokens_per_turn = 16000
23
+ max_tool_calls_per_turn = 6
24
+ max_runtime_seconds = 120
25
+
26
+ [access]
27
+ workspace = "rw"
28
+ network = "restricted"
@@ -0,0 +1,22 @@
1
+ id = "assistant"
2
+ primary_lane = "interactive_primary"
3
+ memory_policy = "default"
4
+ tool_policy = "interactive_safe"
5
+ soul_ref = "config/identity/default-soul.md"
6
+ purpose_ref = "config/identity/default-purpose.md"
7
+ workspace_root = "~/.nemoris/workspace"
8
+
9
+ [interaction_contract]
10
+ ack_mode = "immediate"
11
+ progress_mode = "milestone"
12
+ notify_on_done = true
13
+ notify_on_error = true
14
+
15
+ [limits]
16
+ max_tokens_per_turn = 16000
17
+ max_tool_calls_per_turn = 6
18
+ max_runtime_seconds = 120
19
+
20
+ [access]
21
+ workspace = "rw"
22
+ network = "restricted"
@@ -0,0 +1,18 @@
1
+ id = "orchestrator"
2
+ soul_ref = "config/identity/orchestrator-soul.md"
3
+ purpose_ref = "config/identity/orchestrator-purpose.md"
4
+ primary_lane = "local_cheap"
5
+ fallback_lane = "interactive_fallback"
6
+ tool_policy = "orchestrator"
7
+ memory_policy = "orchestrator"
8
+
9
+ [limits]
10
+ max_tokens_per_turn = 2700
11
+
12
+ [routing.static]
13
+ "heartbeat-check" = "heartbeat"
14
+
15
+ [routing.dynamic]
16
+ enabled = true
17
+ model_lane = "local_cheap"
18
+ max_routing_tokens = 500
@@ -0,0 +1,73 @@
1
+ default_interactive_profile = "gateway_telegram_main"
2
+ default_scheduler_profile = "shadow_scheduler"
3
+ default_interactive_profile_standalone = "standalone_operator"
4
+ default_peer_profile_standalone = "standalone_peer"
5
+
6
+ [profiles.shadow_scheduler]
7
+ adapter = "shadow"
8
+ enabled = true
9
+ target = "scheduler_log"
10
+
11
+ [profiles.gateway_preview_main]
12
+ adapter = "openclaw_cli"
13
+ enabled = true
14
+ channel = "telegram"
15
+ account_id = "default"
16
+ chat_id = "7781763328"
17
+ silent = true
18
+ dry_run = true
19
+
20
+ [profiles.gateway_telegram_main]
21
+ adapter = "openclaw_cli"
22
+ enabled = false
23
+ channel = "telegram"
24
+ account_id = "default"
25
+ chat_id = "7781763328"
26
+ silent = true
27
+ dry_run = false
28
+
29
+ [profiles.peer_preview]
30
+ adapter = "openclaw_peer"
31
+ enabled = true
32
+ dry_run = true
33
+ timeout_ms = 15000
34
+
35
+ [profiles.peer_live]
36
+ adapter = "openclaw_peer"
37
+ enabled = false
38
+ dry_run = false
39
+ timeout_ms = 15000
40
+
41
+ [profiles.telegram_main]
42
+ adapter = "telegram"
43
+ enabled = false
44
+ channel = "telegram"
45
+ account_id = "default"
46
+ chat_id = "7781763328"
47
+ bot_token_env = "NEMORIS_TELEGRAM_BOT_TOKEN"
48
+
49
+ [profiles.standalone_operator]
50
+ adapter = "local_file"
51
+ enabled = true
52
+ target = "operator"
53
+
54
+ [profiles.standalone_peer]
55
+ adapter = "local_file"
56
+ enabled = true
57
+ target = "peer_queue"
58
+
59
+ [profiles.standalone_http_operator]
60
+ adapter = "standalone_http"
61
+ enabled = false
62
+ dry_run = false
63
+ base_url = "${NEMORIS_TRANSPORT_URL}"
64
+ auth_token_env = "NEMORIS_TRANSPORT_TOKEN"
65
+ timeout_ms = 5000
66
+
67
+ [profiles.standalone_http_peer]
68
+ adapter = "standalone_http"
69
+ enabled = false
70
+ dry_run = false
71
+ base_url = "${NEMORIS_TRANSPORT_URL}"
72
+ auth_token_env = "NEMORIS_TRANSPORT_TOKEN"
73
+ timeout_ms = 5000
@@ -0,0 +1,5 @@
1
+ enabled = true
2
+ provider = "ollama"
3
+ model = "ollama/nomic-embed-text"
4
+ dimensions = 128
5
+ index_on_write = true
@@ -0,0 +1 @@
1
+ Help the user accomplish their goals efficiently.
@@ -0,0 +1,3 @@
1
+ You are a helpful, direct assistant.
2
+ Be concise. Be honest. If you don't know something, say so.
3
+ When closing a task: confirm what was done, not just that you tried.
@@ -0,0 +1 @@
1
+ Route incoming jobs to the most appropriate agent based on job type, agent capabilities, and current load.
@@ -0,0 +1 @@
1
+ You are the Nemoris orchestrator — a routing and coordination agent that decides which agent handles each job.
@@ -0,0 +1,15 @@
1
+ [targets.workspace_health]
2
+ job_id = "workspace-health"
3
+ default_mode = "provider"
4
+ default_model_override = "ollama/qwen3:8b"
5
+ default_timeout_ms = 60000
6
+ allowed_knobs = ["report_guidance", "retrieval_blend", "model_override"]
7
+ recommended_variants = ["baseline", "focus_concrete", "retrieval_lexical_heavy", "retrieval_embedding_heavy", "report_model_bump"]
8
+
9
+ [targets.memory_rollup]
10
+ job_id = "memory-rollup"
11
+ default_mode = "provider"
12
+ default_model_override = "ollama/qwen3:8b"
13
+ default_timeout_ms = 75000
14
+ allowed_knobs = ["report_guidance", "retrieval_blend", "model_override"]
15
+ recommended_variants = ["baseline", "focus_concrete", "retrieval_lexical_heavy", "retrieval_embedding_heavy", "report_model_bump"]
@@ -0,0 +1,30 @@
1
+ id = "heartbeat-check"
2
+ trigger = "every:30m"
3
+ task_type = "heartbeat"
4
+ agent_id = "assistant"
5
+ model_lane = "local_cheap"
6
+ output_target = "inbox"
7
+ idempotency_key = "heartbeat-check"
8
+
9
+ [budget]
10
+ max_tokens = 3000
11
+ max_runtime_seconds = 20
12
+
13
+ [retry]
14
+ max_attempts = 1
15
+
16
+ [stop]
17
+ halt_on_policy_error = true
18
+ halt_on_budget_exceeded = true
19
+
20
+ [interaction_contract]
21
+ ack_mode = "silent"
22
+ progress_mode = "none"
23
+ notify_on_done = false
24
+ notify_on_error = true
25
+ requires_pingback = false
26
+ pingback_target = "scheduler_log"
27
+ completion_signal = "heartbeat_ok"
28
+ failure_signal = "heartbeat_error"
29
+ handoff_format = "concise_status"
30
+ completion_sections = ["status"]