mercury-agent 0.5.0 → 0.5.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.
Files changed (125) hide show
  1. package/README.md +452 -451
  2. package/container/Dockerfile +127 -127
  3. package/container/Dockerfile.base +109 -109
  4. package/container/Dockerfile.power +17 -17
  5. package/container/agent-package.json +8 -8
  6. package/container/build.sh +54 -54
  7. package/docs/ROADMAP.md +3 -4
  8. package/docs/archive/summarization/2026-07-02-recent-dev-summary.md +71 -0
  9. package/docs/auth/dashboard.md +28 -28
  10. package/docs/auth/overview.md +109 -109
  11. package/docs/auth/whatsapp.md +173 -173
  12. package/docs/authoring-profiles.md +174 -174
  13. package/docs/configuration.md +54 -54
  14. package/docs/container-lifecycle.md +349 -349
  15. package/docs/{bugs/bwrap-privileged-linux-docker.md → debug/major/2026-07-02-bwrap-privileged-linux-docker.md} +21 -1
  16. package/docs/{bugs/e2big-prompt-delivery-fix.md → debug/major/2026-07-02-e2big-prompt-delivery-fix.md} +27 -1
  17. package/docs/{bugs/registry-pull-no-local-fallback.md → debug/major/2026-07-02-registry-pull-no-local-fallback.md} +27 -1
  18. package/docs/debug/summarization/2026-07-02-common-bug-patterns.md +72 -0
  19. package/docs/deployment.md +199 -199
  20. package/docs/extensions.md +375 -375
  21. package/docs/graceful-shutdown.md +62 -62
  22. package/docs/kb-distillation.md +77 -77
  23. package/docs/media/overview.md +140 -140
  24. package/docs/media/whatsapp.md +171 -171
  25. package/docs/memory.md +137 -137
  26. package/docs/permissions.md +217 -217
  27. package/docs/pipeline.md +228 -228
  28. package/docs/prd-chat-memory.md +76 -76
  29. package/docs/prd-config-load.md +82 -82
  30. package/docs/rate-limiting.md +229 -229
  31. package/docs/runbooks/publish-checklist.md +9 -1
  32. package/docs/scheduler.md +288 -288
  33. package/docs/setup-discord.md +100 -100
  34. package/docs/setup-slack.md +119 -119
  35. package/docs/setup-whatsapp.md +94 -94
  36. package/docs/subagents.md +166 -166
  37. package/docs/web-search.md +62 -62
  38. package/examples/extensions/README.md +12 -12
  39. package/examples/extensions/charts/index.ts +13 -13
  40. package/examples/extensions/charts/skill/SKILL.md +98 -98
  41. package/examples/extensions/gws/README.md +52 -52
  42. package/examples/extensions/gws/skill/SKILL.md +57 -57
  43. package/examples/extensions/gws/skill/references/calendar.md +101 -101
  44. package/examples/extensions/gws/skill/references/docs.md +65 -65
  45. package/examples/extensions/gws/skill/references/drive.md +79 -79
  46. package/examples/extensions/gws/skill/references/gmail.md +85 -85
  47. package/examples/extensions/gws/skill/references/sheets.md +60 -60
  48. package/examples/extensions/napkin/skill/SKILL.md +728 -728
  49. package/examples/extensions/pdf/skill/LICENSE.txt +30 -30
  50. package/examples/extensions/pdf/skill/SKILL.md +314 -314
  51. package/examples/extensions/pdf/skill/forms.md +294 -294
  52. package/examples/extensions/pdf/skill/reference.md +611 -611
  53. package/examples/extensions/pdf/skill/scripts/check_bounding_boxes.py +65 -65
  54. package/examples/extensions/pdf/skill/scripts/check_fillable_fields.py +11 -11
  55. package/examples/extensions/pdf/skill/scripts/convert_pdf_to_images.py +33 -33
  56. package/examples/extensions/pdf/skill/scripts/create_validation_image.py +37 -37
  57. package/examples/extensions/pdf/skill/scripts/extract_form_field_info.py +122 -122
  58. package/examples/extensions/pdf/skill/scripts/extract_form_structure.py +115 -115
  59. package/examples/extensions/pdf/skill/scripts/fill_fillable_fields.py +98 -98
  60. package/examples/extensions/pdf/skill/scripts/fill_pdf_form_with_annotations.py +107 -107
  61. package/examples/extensions/permission-guard/index.ts +65 -65
  62. package/examples/extensions/pinchtab/skill/SKILL.md +224 -224
  63. package/examples/extensions/pinchtab/skill/TRUST.md +69 -69
  64. package/examples/extensions/pinchtab/skill/references/api.md +297 -297
  65. package/examples/extensions/pinchtab/skill/references/env.md +45 -45
  66. package/examples/extensions/pinchtab/skill/references/profiles.md +107 -107
  67. package/examples/extensions/tradestation/host/refresh.ts +102 -102
  68. package/examples/extensions/tradestation/index.ts +153 -153
  69. package/examples/extensions/tradestation/skill/SKILL.md +67 -67
  70. package/examples/extensions/voice-synth/index.ts +94 -94
  71. package/examples/extensions/voice-synth/skill/SKILL.md +38 -38
  72. package/examples/extensions/voice-transcribe/requirements.txt +8 -8
  73. package/examples/extensions/voice-transcribe/scripts/transcribe.py +179 -179
  74. package/examples/extensions/voice-transcribe/skill/SKILL.md +53 -53
  75. package/examples/extensions/yahoo-mail/cli/package.json +13 -13
  76. package/examples/extensions/yahoo-mail/skill/SKILL.md +78 -78
  77. package/package.json +106 -106
  78. package/resources/agents/explore.md +50 -50
  79. package/resources/agents/worker.md +24 -24
  80. package/resources/connection-env-vars.json +25 -25
  81. package/resources/pi-extensions/subagent/agents.ts +126 -126
  82. package/resources/pi-extensions/subagent/index.ts +964 -964
  83. package/resources/profiles/coding/AGENTS.md +43 -43
  84. package/resources/profiles/coding/mercury-profile.yaml +15 -15
  85. package/resources/profiles/general/AGENTS.md +31 -31
  86. package/resources/profiles/general/mercury-profile.yaml +15 -15
  87. package/resources/profiles/research/AGENTS.md +40 -40
  88. package/resources/profiles/research/mercury-profile.yaml +15 -15
  89. package/resources/skills/config/SKILL.md +25 -25
  90. package/resources/skills/context/SKILL.md +33 -33
  91. package/resources/skills/conversation-recap/SKILL.md +19 -19
  92. package/resources/skills/mutes/SKILL.md +31 -31
  93. package/resources/skills/permissions/SKILL.md +19 -19
  94. package/resources/skills/preferences/SKILL.md +31 -31
  95. package/resources/skills/recall/SKILL.md +24 -24
  96. package/resources/skills/roles/SKILL.md +18 -18
  97. package/resources/skills/spaces/SKILL.md +18 -18
  98. package/resources/skills/tasks/SKILL.md +45 -45
  99. package/resources/templates/AGENTS.md +157 -157
  100. package/resources/templates/env.template +38 -38
  101. package/resources/templates/mercury.example.yaml +99 -99
  102. package/src/agent/container-entry.ts +1 -1
  103. package/src/agent/container-runner.ts +1345 -1346
  104. package/src/cli/mercury.ts +39 -7
  105. package/src/cli/mrctl.ts +636 -636
  106. package/src/config-file.ts +540 -540
  107. package/src/config.ts +339 -339
  108. package/src/core/api.ts +125 -125
  109. package/src/core/caller-token.ts +101 -101
  110. package/src/core/permissions.ts +228 -228
  111. package/src/core/profiles.ts +271 -271
  112. package/src/core/routes/capability.ts +70 -70
  113. package/src/core/routes/index.ts +15 -15
  114. package/src/core/runtime.ts +1530 -1530
  115. package/src/dashboard/index.html +729 -729
  116. package/src/extensions/api.ts +273 -273
  117. package/src/extensions/loader.ts +286 -286
  118. package/src/extensions/types.ts +517 -517
  119. package/src/main.ts +605 -605
  120. package/docs/pending-updates/applicative-profiles.md +0 -15
  121. package/docs/pending-updates/caller-bound-capability-token.md +0 -15
  122. package/docs/pending-updates/dm-auto-space.md +0 -15
  123. /package/docs/archive/{2026-07-01-applicative-profiles.md → applicative-profiles/2026-07-01-applicative-profiles.md} +0 -0
  124. /package/docs/archive/{2026-07-01-caller-bound-capability-token.md → applicative-profiles/2026-07-01-caller-bound-capability-token.md} +0 -0
  125. /package/docs/archive/{2026-07-01-dm-auto-space.md → applicative-profiles/2026-07-01-dm-auto-space.md} +0 -0
@@ -1,8 +1,10 @@
1
1
  # Bug: bwrap fails to mount /proc on Linux Docker Engine (non-Desktop)
2
2
 
3
+ **Status:** Fixed
3
4
  **Severity:** P1 — blocks all agent responses on standard Linux Docker hosts
4
5
  **Affected:** Linux servers running Docker Engine (not Docker Desktop, not gVisor)
5
- **File:** `src/agent/container-runner.ts`, bwrap compat branch (~line 980)
6
+ **File:** `src/agent/container-runner.ts`, bwrap compat branch (~line 980)
7
+ **Last updated:** 2026-07-02
6
8
 
7
9
  ## Symptom
8
10
 
@@ -138,3 +140,21 @@ EOF
138
140
  2. Start mercury: `pm2 restart all` or `mercury service install`
139
141
  3. Run: `mercury chat 'hello'`
140
142
  4. Check logs — should see successful container run, no bwrap errors
143
+
144
+ ---
145
+
146
+ ## Post-Mortem
147
+
148
+ ### Investigation
149
+ Reconciled this hanging bug doc against the current code during `/f-doc-sync` triage. Read the bwrap compat branch in `src/agent/container-runner.ts` (grep for `privileged`/`containerBwrapDockerCompat`/`isDockerDesktop`).
150
+
151
+ ### Root Cause
152
+ On standard Linux Docker Engine, the lighter compat flags (`seccomp=unconfined` + `apparmor=unconfined` + `CAP_SYS_ADMIN`) don't permit `mount(2)` inside a user namespace, so bwrap failed with `Can't mount proc on /newroot/proc: Operation not permitted`. Only `--privileged` restores the permissions bwrap needs.
153
+
154
+ ### Fix
155
+ **Option A was already implemented** — no new code required. In `container-runner.ts` (lines 1003–1008), the compat branch now pushes `--privileged` when `containerBwrapDockerCompat` is explicitly `true` (with a log line "Enabling bwrap Docker compat with --privileged"), while Docker Desktop auto-detection keeps the lighter `seccomp/apparmor/SYS_ADMIN` flags. This matches the recommended fix exactly.
156
+
157
+ ### Lessons
158
+ - Reconcile hanging bug docs against the code before opening a fix session — this P1 was already resolved but never archived.
159
+ - Container-sandbox permissions differ between Docker Desktop (permissive VM kernel) and bare Linux Docker Engine; gate the heavier `--privileged` escalation behind an explicit opt-in rather than applying it everywhere.
160
+ - `docs/bugs/` and `docs/debug/` are gitignored working docs — archival here is a local move only.
@@ -1,8 +1,10 @@
1
1
  # Fix: E2BIG — Argument list too long on bwrap/pi spawn
2
2
 
3
+ **Status:** Fixed
3
4
  **Severity:** P0 — causes container crash on long conversations
4
5
  **Affected:** All runtimes (bwrap + gVisor/direct), Docker Desktop especially
5
- **File:** `src/agent/container-entry.ts`
6
+ **File:** `src/agent/container-entry.ts`
7
+ **Last updated:** 2026-07-02
6
8
 
7
9
  ## Symptom
8
10
 
@@ -354,3 +356,27 @@ output to confirm the full prompt arrived.
354
356
  | Cleanup system prompt file | close + error handlers | 4 lines |
355
357
  | **Total** | | **~22 lines changed** |
356
358
  | Byte-budget history (optional companion) | `buildHistoryXml` | Replace function body |
359
+
360
+ ---
361
+
362
+ ## Post-Mortem
363
+
364
+ ### Investigation
365
+ Verified the current state of `src/agent/container-entry.ts` against this fix guide before doing any work (bug was flagged as a hanging doc during `/f-doc-sync`, never archived). Grepped and read the relevant functions: `buildBwrapArgs` (line 676), `invokePiOnce` (line 728), `buildHistoryXml` (line 534), and both spawn sites (line 810).
366
+
367
+ ### Root Cause
368
+ `invokePiOnce()` passed the system prompt and the full conversation-history XML as `argv` strings to `posix_spawn('bwrap'|'pi', …)`. On long conversations the combined argv + envp size exceeded Linux `ARG_MAX` (~2MB), so `execve` failed with `E2BIG` and the container exited 1.
369
+
370
+ ### Fix
371
+ The complete fix described in this guide was **already implemented** in the tree — no new code was required:
372
+ - `unlinkSync` imported and used in the `close`/`error` handlers (lines 854, 865).
373
+ - `buildBwrapArgs(workspace, command, ioDir?)` binds `IO_DIR` read-only into the sandbox (line 679 signature; line 716 `--ro-bind ioDir ioDir`).
374
+ - System prompt written to `IO_DIR/system-prompt.txt` and passed as a file path (pi's `resolvePromptInput` reads it) — lines 765–771.
375
+ - User prompt removed from `argv` and piped via stdin (`proc.stdin?.end(userPrompt, "utf8")`) with both spawn sites using `stdio: ["pipe","pipe","pipe"]` — lines 814–831.
376
+ - Temp system-prompt file cleaned up on close and error — lines 852–865.
377
+ - Optional companion `HISTORY_CHAR_BUDGET = 400_000` applied in `buildHistoryXml` (lines 534, 571) as defense-in-depth.
378
+
379
+ ### Lessons
380
+ - Hanging bug docs should be reconciled against the code before opening a fix session — this one was fully resolved but never archived, so it lingered as an apparent P0.
381
+ - Never pass unbounded, caller-influenced data (conversation history) through `argv`; use stdin or a file whose path is the only thing in `argv`. Pair the delivery fix with a size budget so history growth can't regress the limit.
382
+ - `docs/bugs/` and `docs/debug/` are gitignored working docs — archival here is a local move only, with no commit/push.
@@ -1,8 +1,10 @@
1
1
  # Bug: mercury run fails when registry pull fails but local build exists
2
2
 
3
+ **Status:** Fixed
3
4
  **Severity:** P1 — blocks users who build locally but have a registry image configured
4
5
  **Introduced in:** 0.4.22 (commit 75e8e71)
5
- **File:** `src/cli/mercury.ts`, `runAction()` (~line 187)
6
+ **File:** `src/cli/mercury.ts`, `runAction()` (~line 187)
7
+ **Last updated:** 2026-07-02
6
8
 
7
9
  ## Symptom
8
10
 
@@ -166,3 +168,27 @@ configured image not found?
166
168
  4. Run `mercury run` — should fall back to local image with info message
167
169
  5. Remove local image: `docker rmi mercury-agent:latest`
168
170
  6. Run `mercury run` — should error with both `docker login` and `mercury build` suggestions
171
+
172
+ ---
173
+
174
+ ## Post-Mortem
175
+
176
+ ### Investigation
177
+ Triaged from a hanging bug doc during `/f-doc-sync`. First confirmed the fix was NOT already present: grepped `src/` for any local-fallback logic (`Using locally built`, `localTag`, `resolved`) — zero hits — and read `runAction()` in `src/cli/mercury.ts` (lines 186–216), which was still the buggy 0.4.22 version that hard-exits on pull failure. Fixed in an isolated worktree.
178
+
179
+ ### Root Cause
180
+ The 0.4.22 auto-pull rewrite dropped the pre-existing local-image fallback. When the configured image was a registry ref and `docker pull` failed (private registry / no auth / offline), `runAction()` called `process.exit(1)` immediately, never checking whether a locally built `mercury-agent:latest` existed.
181
+
182
+ ### Fix
183
+ `src/cli/mercury.ts`, `runAction()` (committed to main as `1c120bf`):
184
+ - Introduced a `resolved` flag. A registry pull sets it on success; on failure, control falls through instead of exiting.
185
+ - Added a fallback block: if unresolved and the configured image isn't already `mercury-agent:latest`, `docker image inspect mercury-agent:latest`; if present, use it with an info message.
186
+ - Only after both paths fail does it `process.exit(1)`, now suggesting **both** `docker login` and `mercury build`.
187
+ - **Beyond the original fix guide:** the child is spawned with `env: { ...process.env, ...envVars }`, and `envVars` (loaded from `.env`, which typically pins `MERCURY_AGENT_IMAGE` to the registry) wins that merge. Setting only `process.env.MERCURY_AGENT_IMAGE` would have been silently clobbered — the repro scenario itself. The fix therefore also sets `envVars.MERCURY_AGENT_IMAGE = localTag`. Confirmed load-bearing by the session code review.
188
+
189
+ Verification: `bun run typecheck` + `bun run lint` clean; `bun test` → 1039 pass / 0 fail; session code review returned "No issues found."
190
+
191
+ ### Lessons
192
+ - When a spawn merges multiple env sources (`{ ...process.env, ...envVars }`), an override must be written to the **last-wins** source, not just `process.env` — otherwise it's silently reverted.
193
+ - Behavior-replacing rewrites (the 0.4.22 auto-pull change) should preserve existing fallbacks explicitly; a regression test for "pull fails but local image exists" would have caught this.
194
+ - Reconcile hanging bug docs against current code before opening a fix — two sibling P0/P1 docs (`e2big`, `bwrap-privileged`) turned out already fixed; only this one needed work.
@@ -0,0 +1,72 @@
1
+ # Common Bug Patterns
2
+
3
+ **Date:** 2026-07-02
4
+ **Covers:** 1 bug report (1 major, 0 moderate, 0 minor) · 2026-07-01 → 2026-07-01
5
+
6
+ This is the first bug-pattern summary. It covers a single major incident — the strict-YAML-schema crash — but that one bug braids together several distinct, reusable failure patterns worth capturing before they recur: over-strict input validation, unbounded restart loops, and the fragile-transport amplification that turns any crash into extended downtime. The dominant theme is **conflation**: treating "unknown input" and "invalid input" as the same failure, and treating "one crash" as harmless when the surrounding system amplifies it.
7
+
8
+ ## Findings
9
+
10
+ ### 1. Over-strict input validation (unknown key ≠ invalid value)
11
+
12
+ Schemas that reject unrecognized input with the same severity as malformed input turn benign drift (typos, renamed fields, version skew) into hard failures.
13
+
14
+ | Bug | What went wrong |
15
+ |-----|-----------------|
16
+ | strict-yaml-schema-crash | `mercuryFileSchema` used Zod `.strict()` on all 13 nested objects, so a single unknown `mercury.yaml` key (e.g. renamed `admin_numbers` → `admin_ids`) crashed startup with the same severity as an invalid value. |
17
+
18
+ **Rule:** Separate "unknown key" (warn, strip, continue) from "invalid value" (fail fast). Default config schemas to strip-and-warn on unrecognized keys; reserve hard failure for values that are actually wrong.
19
+
20
+ ### 2. Version-skew intolerance
21
+
22
+ Config that must be exactly in sync with the running binary breaks on every field rename, punishing the normal lifecycle of upgrades and rollbacks.
23
+
24
+ | Bug | What went wrong |
25
+ |-----|-----------------|
26
+ | strict-yaml-schema-crash | A field renamed between 0.4.26 and 0.4.27 (`admin_numbers` → `admin_ids`) crashed any deployment whose yaml hadn't been updated in lockstep. |
27
+
28
+ **Rule:** Any feature that adds or renames a config field must assume a user on version N may run a yaml from version N±1. Forward/backward-unknown keys should degrade gracefully, not crash.
29
+
30
+ ### 3. Unbounded restart loops amplify a single failure
31
+
32
+ A deterministic startup error plus an unbounded auto-restarter converts one crash into an infinite crash loop, removing any window for human intervention.
33
+
34
+ | Bug | What went wrong |
35
+ |-----|-----------------|
36
+ | strict-yaml-schema-crash | PM2's default unlimited restarts retried the identical failing config forever, each attempt failing the same way. |
37
+
38
+ **Rule:** Configure `max_restarts` + `min_uptime` on process supervisors so a deterministic failure stops after N attempts and alerts, rather than looping. A restart policy is not a substitute for handling the error.
39
+
40
+ ### 4. Fragile-transport amplification
41
+
42
+ When a downstream dependency punishes rapid reconnection, an unrelated crash loop escalates into a much costlier outage than the original bug.
43
+
44
+ | Bug | What went wrong |
45
+ |-----|-----------------|
46
+ | strict-yaml-schema-crash | The crash loop drove rapid WhatsApp/Baileys reconnects, which Meta treats as abuse → session revoked (reason=401) → manual QR re-scan required for recovery. |
47
+
48
+ **Rule:** Treat any crash loop as catastrophic when a session-based/unofficial transport is in play. Isolate transport-session lifecycle from process restarts, and prefer a circuit breaker that keeps the host alive while surfacing the error.
49
+
50
+ ## Summary table
51
+
52
+ | Pattern | Count | Worst severity |
53
+ |---------|-------|----------------|
54
+ | Over-strict input validation | 1 | major |
55
+ | Version-skew intolerance | 1 | major |
56
+ | Unbounded restart loops | 1 | major |
57
+ | Fragile-transport amplification | 1 | major |
58
+
59
+ ## Comparison with previous summary
60
+
61
+ None — this is the first bug-pattern summary. Future summaries should track whether validation-strictness and restart-loop patterns recur once the fixes above land.
62
+
63
+ ## Decisions
64
+
65
+ 1. **Adopt strip-and-warn as the config default** across all schemas; audit remaining `.strict()` usages for the same class of crash.
66
+ 2. **Set supervisor restart limits** (`max_restarts`, `min_uptime`) plus an alert on limit-hit, so no deterministic failure can loop indefinitely.
67
+ 3. **Design a container/transport circuit breaker** (the bug's own Phase 2) so container-level errors log-and-recover instead of crashing the host and endangering the WhatsApp session.
68
+
69
+ ## Open Questions
70
+
71
+ - Should config validation ever hard-fail on unknown keys in a "strict mode" opt-in for CI, while defaulting to warn in production?
72
+ - What is the right `max_restarts` threshold given Baileys' revocation sensitivity — and should transport reconnection back off independently of process restarts?
@@ -1,199 +1,199 @@
1
- # Deployment
2
-
3
- Mercury can run as a background daemon with automatic restart on crash.
4
-
5
- For **environment variables vs `mercury.yaml`**, see [configuration.md](configuration.md).
6
-
7
- ## Quick Setup
8
-
9
- ```bash
10
- # Install as user service (recommended)
11
- mercury service install
12
-
13
- # Check status
14
- mercury service status
15
-
16
- # View logs
17
- mercury service logs -f
18
-
19
- # Uninstall when needed
20
- mercury service uninstall
21
- ```
22
-
23
- ## Platform Support
24
-
25
- ### Linux (systemd)
26
-
27
- Mercury installs as a systemd user service by default:
28
-
29
- ```bash
30
- # Install as user service (no sudo required)
31
- mercury service install
32
-
33
- # Or explicitly specify user mode
34
- mercury service install --user
35
- ```
36
-
37
- The service file is written to `~/.config/systemd/user/mercury.service`.
38
-
39
- **Manual systemd commands:**
40
-
41
- ```bash
42
- # Check status
43
- systemctl --user status mercury
44
-
45
- # Restart service
46
- systemctl --user restart mercury
47
-
48
- # Stop service
49
- systemctl --user stop mercury
50
-
51
- # View logs (follow mode)
52
- journalctl --user -u mercury -f
53
- ```
54
-
55
- **User service notes:**
56
- - No root/sudo required
57
- - Service runs under your user account
58
- - Starts automatically on user login
59
- - For 24/7 operation without login, enable lingering: `loginctl enable-linger $USER`
60
-
61
- ### macOS (launchd)
62
-
63
- Mercury installs as a launchd user agent:
64
-
65
- ```bash
66
- mercury service install
67
- ```
68
-
69
- The plist is written to `~/Library/LaunchAgents/com.mercury.agent.plist`.
70
-
71
- Logs are written to `.mercury/logs/` in your project directory:
72
- - `mercury.log` — stdout
73
- - `mercury.error.log` — stderr
74
-
75
- **Manual launchd commands:**
76
-
77
- ```bash
78
- # Check if running
79
- launchctl list com.mercury.agent
80
-
81
- # Stop service
82
- launchctl stop com.mercury.agent
83
-
84
- # Start service
85
- launchctl start com.mercury.agent
86
-
87
- # Unload completely
88
- launchctl unload ~/Library/LaunchAgents/com.mercury.agent.plist
89
-
90
- # View logs
91
- tail -f .mercury/logs/mercury.log
92
- ```
93
-
94
- ### Windows
95
-
96
- Not currently supported via `mercury service`. Options:
97
-
98
- 1. **Task Scheduler**: Create a task that runs `mercury run` at startup
99
- 2. **NSSM**: Use [NSSM](https://nssm.cc/) to wrap Mercury as a Windows service
100
- 3. **PM2**: Use `pm2 start "mercury run" --name mercury`
101
-
102
- ## Auto-Restart Behavior
103
-
104
- Both systemd and launchd are configured to automatically restart Mercury if it crashes:
105
-
106
- - **systemd**: `Restart=on-failure` with 10-second delay
107
- - **launchd**: `KeepAlive=true` for immediate restart
108
-
109
- ## Working Directory
110
-
111
- The service is configured to run from the directory where you ran `mercury service install`. This means:
112
-
113
- - Your `.env` file is loaded from that directory
114
- - Relative paths in configuration resolve from there
115
- - The `.mercury/` data directory is in that location
116
-
117
- If you move your Mercury project, you'll need to uninstall and reinstall the service.
118
-
119
- ## Logs
120
-
121
- ### Linux
122
-
123
- Logs go to the systemd journal:
124
-
125
- ```bash
126
- # View recent logs
127
- mercury service logs
128
-
129
- # Follow logs in real-time
130
- mercury service logs -f
131
-
132
- # Or use journalctl directly
133
- journalctl --user -u mercury -n 100
134
- journalctl --user -u mercury --since "1 hour ago"
135
- ```
136
-
137
- ### macOS
138
-
139
- Logs go to files in `.mercury/logs/`:
140
-
141
- ```bash
142
- # View recent logs
143
- mercury service logs
144
-
145
- # Follow logs in real-time
146
- mercury service logs -f
147
-
148
- # Or use tail directly
149
- tail -f .mercury/logs/mercury.log
150
- ```
151
-
152
- ## Troubleshooting
153
-
154
- ### Service fails to start
155
-
156
- 1. Run `mercury doctor` to check for common issues
157
- 2. Check that `mercury run` works manually first
158
- 3. Verify `.env` exists and is configured
159
- 4. Check logs for errors: `mercury service logs`
160
-
161
- ### Permission denied (Linux)
162
-
163
- If you see permission errors with system-level install, use user mode:
164
-
165
- ```bash
166
- mercury service install --user
167
- ```
168
-
169
- ### Service not found after reboot (Linux)
170
-
171
- Enable user lingering so services start without login:
172
-
173
- ```bash
174
- loginctl enable-linger $USER
175
- ```
176
-
177
- ### Logs not appearing (macOS)
178
-
179
- Check that the log directory exists:
180
-
181
- ```bash
182
- mkdir -p .mercury/logs
183
- ```
184
-
185
- Then reinstall the service:
186
-
187
- ```bash
188
- mercury service uninstall
189
- mercury service install
190
- ```
191
-
192
- ### Multiple instances
193
-
194
- Each Mercury project should be installed as a separate service from its own directory. The service name is always `mercury`, so only one instance can be managed per user account.
195
-
196
- For multiple instances, consider:
197
- - Running different instances under different user accounts
198
- - Using Docker/Podman with separate containers
199
- - Manual systemd service files with unique names
1
+ # Deployment
2
+
3
+ Mercury can run as a background daemon with automatic restart on crash.
4
+
5
+ For **environment variables vs `mercury.yaml`**, see [configuration.md](configuration.md).
6
+
7
+ ## Quick Setup
8
+
9
+ ```bash
10
+ # Install as user service (recommended)
11
+ mercury service install
12
+
13
+ # Check status
14
+ mercury service status
15
+
16
+ # View logs
17
+ mercury service logs -f
18
+
19
+ # Uninstall when needed
20
+ mercury service uninstall
21
+ ```
22
+
23
+ ## Platform Support
24
+
25
+ ### Linux (systemd)
26
+
27
+ Mercury installs as a systemd user service by default:
28
+
29
+ ```bash
30
+ # Install as user service (no sudo required)
31
+ mercury service install
32
+
33
+ # Or explicitly specify user mode
34
+ mercury service install --user
35
+ ```
36
+
37
+ The service file is written to `~/.config/systemd/user/mercury.service`.
38
+
39
+ **Manual systemd commands:**
40
+
41
+ ```bash
42
+ # Check status
43
+ systemctl --user status mercury
44
+
45
+ # Restart service
46
+ systemctl --user restart mercury
47
+
48
+ # Stop service
49
+ systemctl --user stop mercury
50
+
51
+ # View logs (follow mode)
52
+ journalctl --user -u mercury -f
53
+ ```
54
+
55
+ **User service notes:**
56
+ - No root/sudo required
57
+ - Service runs under your user account
58
+ - Starts automatically on user login
59
+ - For 24/7 operation without login, enable lingering: `loginctl enable-linger $USER`
60
+
61
+ ### macOS (launchd)
62
+
63
+ Mercury installs as a launchd user agent:
64
+
65
+ ```bash
66
+ mercury service install
67
+ ```
68
+
69
+ The plist is written to `~/Library/LaunchAgents/com.mercury.agent.plist`.
70
+
71
+ Logs are written to `.mercury/logs/` in your project directory:
72
+ - `mercury.log` — stdout
73
+ - `mercury.error.log` — stderr
74
+
75
+ **Manual launchd commands:**
76
+
77
+ ```bash
78
+ # Check if running
79
+ launchctl list com.mercury.agent
80
+
81
+ # Stop service
82
+ launchctl stop com.mercury.agent
83
+
84
+ # Start service
85
+ launchctl start com.mercury.agent
86
+
87
+ # Unload completely
88
+ launchctl unload ~/Library/LaunchAgents/com.mercury.agent.plist
89
+
90
+ # View logs
91
+ tail -f .mercury/logs/mercury.log
92
+ ```
93
+
94
+ ### Windows
95
+
96
+ Not currently supported via `mercury service`. Options:
97
+
98
+ 1. **Task Scheduler**: Create a task that runs `mercury run` at startup
99
+ 2. **NSSM**: Use [NSSM](https://nssm.cc/) to wrap Mercury as a Windows service
100
+ 3. **PM2**: Use `pm2 start "mercury run" --name mercury`
101
+
102
+ ## Auto-Restart Behavior
103
+
104
+ Both systemd and launchd are configured to automatically restart Mercury if it crashes:
105
+
106
+ - **systemd**: `Restart=on-failure` with 10-second delay
107
+ - **launchd**: `KeepAlive=true` for immediate restart
108
+
109
+ ## Working Directory
110
+
111
+ The service is configured to run from the directory where you ran `mercury service install`. This means:
112
+
113
+ - Your `.env` file is loaded from that directory
114
+ - Relative paths in configuration resolve from there
115
+ - The `.mercury/` data directory is in that location
116
+
117
+ If you move your Mercury project, you'll need to uninstall and reinstall the service.
118
+
119
+ ## Logs
120
+
121
+ ### Linux
122
+
123
+ Logs go to the systemd journal:
124
+
125
+ ```bash
126
+ # View recent logs
127
+ mercury service logs
128
+
129
+ # Follow logs in real-time
130
+ mercury service logs -f
131
+
132
+ # Or use journalctl directly
133
+ journalctl --user -u mercury -n 100
134
+ journalctl --user -u mercury --since "1 hour ago"
135
+ ```
136
+
137
+ ### macOS
138
+
139
+ Logs go to files in `.mercury/logs/`:
140
+
141
+ ```bash
142
+ # View recent logs
143
+ mercury service logs
144
+
145
+ # Follow logs in real-time
146
+ mercury service logs -f
147
+
148
+ # Or use tail directly
149
+ tail -f .mercury/logs/mercury.log
150
+ ```
151
+
152
+ ## Troubleshooting
153
+
154
+ ### Service fails to start
155
+
156
+ 1. Run `mercury doctor` to check for common issues
157
+ 2. Check that `mercury run` works manually first
158
+ 3. Verify `.env` exists and is configured
159
+ 4. Check logs for errors: `mercury service logs`
160
+
161
+ ### Permission denied (Linux)
162
+
163
+ If you see permission errors with system-level install, use user mode:
164
+
165
+ ```bash
166
+ mercury service install --user
167
+ ```
168
+
169
+ ### Service not found after reboot (Linux)
170
+
171
+ Enable user lingering so services start without login:
172
+
173
+ ```bash
174
+ loginctl enable-linger $USER
175
+ ```
176
+
177
+ ### Logs not appearing (macOS)
178
+
179
+ Check that the log directory exists:
180
+
181
+ ```bash
182
+ mkdir -p .mercury/logs
183
+ ```
184
+
185
+ Then reinstall the service:
186
+
187
+ ```bash
188
+ mercury service uninstall
189
+ mercury service install
190
+ ```
191
+
192
+ ### Multiple instances
193
+
194
+ Each Mercury project should be installed as a separate service from its own directory. The service name is always `mercury`, so only one instance can be managed per user account.
195
+
196
+ For multiple instances, consider:
197
+ - Running different instances under different user accounts
198
+ - Using Docker/Podman with separate containers
199
+ - Manual systemd service files with unique names