@geminixiang/mama 0.2.0-beta.2 → 0.2.0-beta.21

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 (264) hide show
  1. package/README.md +157 -391
  2. package/dist/adapter.d.ts +31 -7
  3. package/dist/adapter.d.ts.map +1 -1
  4. package/dist/adapter.js.map +1 -1
  5. package/dist/adapters/discord/bot.d.ts +10 -5
  6. package/dist/adapters/discord/bot.d.ts.map +1 -1
  7. package/dist/adapters/discord/bot.js +347 -115
  8. package/dist/adapters/discord/bot.js.map +1 -1
  9. package/dist/adapters/discord/context.d.ts +1 -1
  10. package/dist/adapters/discord/context.d.ts.map +1 -1
  11. package/dist/adapters/discord/context.js +118 -25
  12. package/dist/adapters/discord/context.js.map +1 -1
  13. package/dist/adapters/shared.d.ts +91 -0
  14. package/dist/adapters/shared.d.ts.map +1 -0
  15. package/dist/adapters/shared.js +191 -0
  16. package/dist/adapters/shared.js.map +1 -0
  17. package/dist/adapters/slack/bot.d.ts +21 -22
  18. package/dist/adapters/slack/bot.d.ts.map +1 -1
  19. package/dist/adapters/slack/bot.js +530 -221
  20. package/dist/adapters/slack/bot.js.map +1 -1
  21. package/dist/adapters/slack/branch-manager.d.ts +28 -0
  22. package/dist/adapters/slack/branch-manager.d.ts.map +1 -0
  23. package/dist/adapters/slack/branch-manager.js +107 -0
  24. package/dist/adapters/slack/branch-manager.js.map +1 -0
  25. package/dist/adapters/slack/context.d.ts +4 -1
  26. package/dist/adapters/slack/context.d.ts.map +1 -1
  27. package/dist/adapters/slack/context.js +193 -75
  28. package/dist/adapters/slack/context.js.map +1 -1
  29. package/dist/adapters/slack/session.d.ts +38 -0
  30. package/dist/adapters/slack/session.d.ts.map +1 -0
  31. package/dist/adapters/slack/session.js +66 -0
  32. package/dist/adapters/slack/session.js.map +1 -0
  33. package/dist/adapters/slack/tools/attach.d.ts +1 -1
  34. package/dist/adapters/slack/tools/attach.d.ts.map +1 -1
  35. package/dist/adapters/slack/tools/attach.js.map +1 -1
  36. package/dist/adapters/telegram/bot.d.ts.map +1 -1
  37. package/dist/adapters/telegram/bot.js +140 -153
  38. package/dist/adapters/telegram/bot.js.map +1 -1
  39. package/dist/adapters/telegram/context.d.ts +1 -1
  40. package/dist/adapters/telegram/context.d.ts.map +1 -1
  41. package/dist/adapters/telegram/context.js +74 -20
  42. package/dist/adapters/telegram/context.js.map +1 -1
  43. package/dist/agent.d.ts +13 -3
  44. package/dist/agent.d.ts.map +1 -1
  45. package/dist/agent.js +677 -552
  46. package/dist/agent.js.map +1 -1
  47. package/dist/commands/auto-reply.d.ts +16 -0
  48. package/dist/commands/auto-reply.d.ts.map +1 -0
  49. package/dist/commands/auto-reply.js +72 -0
  50. package/dist/commands/auto-reply.js.map +1 -0
  51. package/dist/commands/index.d.ts +5 -0
  52. package/dist/commands/index.d.ts.map +1 -0
  53. package/dist/commands/index.js +18 -0
  54. package/dist/commands/index.js.map +1 -0
  55. package/dist/commands/login.d.ts +5 -0
  56. package/dist/commands/login.d.ts.map +1 -0
  57. package/dist/commands/login.js +91 -0
  58. package/dist/commands/login.js.map +1 -0
  59. package/dist/commands/model.d.ts +14 -0
  60. package/dist/commands/model.d.ts.map +1 -0
  61. package/dist/commands/model.js +112 -0
  62. package/dist/commands/model.js.map +1 -0
  63. package/dist/commands/new.d.ts +9 -0
  64. package/dist/commands/new.d.ts.map +1 -0
  65. package/dist/commands/new.js +28 -0
  66. package/dist/commands/new.js.map +1 -0
  67. package/dist/commands/registry.d.ts +4 -0
  68. package/dist/commands/registry.d.ts.map +1 -0
  69. package/dist/commands/registry.js +9 -0
  70. package/dist/commands/registry.js.map +1 -0
  71. package/dist/commands/sandbox.d.ts +10 -0
  72. package/dist/commands/sandbox.d.ts.map +1 -0
  73. package/dist/commands/sandbox.js +88 -0
  74. package/dist/commands/sandbox.js.map +1 -0
  75. package/dist/commands/session-view.d.ts +5 -0
  76. package/dist/commands/session-view.d.ts.map +1 -0
  77. package/dist/commands/session-view.js +62 -0
  78. package/dist/commands/session-view.js.map +1 -0
  79. package/dist/commands/types.d.ts +41 -0
  80. package/dist/commands/types.d.ts.map +1 -0
  81. package/dist/commands/types.js +2 -0
  82. package/dist/commands/types.js.map +1 -0
  83. package/dist/commands/utils.d.ts +8 -0
  84. package/dist/commands/utils.d.ts.map +1 -0
  85. package/dist/commands/utils.js +14 -0
  86. package/dist/commands/utils.js.map +1 -0
  87. package/dist/config.d.ts +46 -8
  88. package/dist/config.d.ts.map +1 -1
  89. package/dist/config.js +306 -67
  90. package/dist/config.js.map +1 -1
  91. package/dist/context.d.ts +10 -42
  92. package/dist/context.d.ts.map +1 -1
  93. package/dist/context.js +14 -127
  94. package/dist/context.js.map +1 -1
  95. package/dist/events.d.ts +2 -0
  96. package/dist/events.d.ts.map +1 -1
  97. package/dist/events.js +148 -67
  98. package/dist/events.js.map +1 -1
  99. package/dist/execution-resolver.d.ts +12 -7
  100. package/dist/execution-resolver.d.ts.map +1 -1
  101. package/dist/execution-resolver.js +150 -21
  102. package/dist/execution-resolver.js.map +1 -1
  103. package/dist/file-guards.d.ts +9 -0
  104. package/dist/file-guards.d.ts.map +1 -0
  105. package/dist/file-guards.js +56 -0
  106. package/dist/file-guards.js.map +1 -0
  107. package/dist/fs-atomic.d.ts +10 -0
  108. package/dist/fs-atomic.d.ts.map +1 -0
  109. package/dist/fs-atomic.js +45 -0
  110. package/dist/fs-atomic.js.map +1 -0
  111. package/dist/index.d.ts +7 -0
  112. package/dist/index.d.ts.map +1 -0
  113. package/dist/index.js +4 -0
  114. package/dist/index.js.map +1 -0
  115. package/dist/instrument.d.ts.map +1 -1
  116. package/dist/instrument.js +2 -3
  117. package/dist/instrument.js.map +1 -1
  118. package/dist/log.d.ts +1 -12
  119. package/dist/log.d.ts.map +1 -1
  120. package/dist/log.js +12 -143
  121. package/dist/log.js.map +1 -1
  122. package/dist/{login.d.ts → login/index.d.ts} +16 -3
  123. package/dist/login/index.d.ts.map +1 -0
  124. package/dist/{login.js → login/index.js} +94 -17
  125. package/dist/login/index.js.map +1 -0
  126. package/dist/{link-server.d.ts → login/portal.d.ts} +6 -4
  127. package/dist/login/portal.d.ts.map +1 -0
  128. package/dist/login/portal.js +1544 -0
  129. package/dist/login/portal.js.map +1 -0
  130. package/dist/login/session.d.ts +26 -0
  131. package/dist/login/session.d.ts.map +1 -0
  132. package/dist/{link-token.js → login/session.js} +10 -22
  133. package/dist/login/session.js.map +1 -0
  134. package/dist/main.d.ts.map +1 -1
  135. package/dist/main.js +138 -352
  136. package/dist/main.js.map +1 -1
  137. package/dist/provisioner.d.ts +42 -11
  138. package/dist/provisioner.d.ts.map +1 -1
  139. package/dist/provisioner.js +273 -64
  140. package/dist/provisioner.js.map +1 -1
  141. package/dist/runtime/conversation-orchestrator.d.ts +40 -0
  142. package/dist/runtime/conversation-orchestrator.d.ts.map +1 -0
  143. package/dist/runtime/conversation-orchestrator.js +183 -0
  144. package/dist/runtime/conversation-orchestrator.js.map +1 -0
  145. package/dist/runtime/index.d.ts +2 -0
  146. package/dist/runtime/index.d.ts.map +1 -0
  147. package/dist/runtime/index.js +2 -0
  148. package/dist/runtime/index.js.map +1 -0
  149. package/dist/runtime/session-runtime.d.ts +26 -0
  150. package/dist/runtime/session-runtime.d.ts.map +1 -0
  151. package/dist/runtime/session-runtime.js +221 -0
  152. package/dist/runtime/session-runtime.js.map +1 -0
  153. package/dist/sandbox/cloudflare.d.ts +15 -0
  154. package/dist/sandbox/cloudflare.d.ts.map +1 -0
  155. package/dist/sandbox/cloudflare.js +137 -0
  156. package/dist/sandbox/cloudflare.js.map +1 -0
  157. package/dist/sandbox/container.d.ts +2 -1
  158. package/dist/sandbox/container.d.ts.map +1 -1
  159. package/dist/sandbox/container.js +18 -2
  160. package/dist/sandbox/container.js.map +1 -1
  161. package/dist/sandbox/firecracker.d.ts +2 -1
  162. package/dist/sandbox/firecracker.d.ts.map +1 -1
  163. package/dist/sandbox/firecracker.js +6 -0
  164. package/dist/sandbox/firecracker.js.map +1 -1
  165. package/dist/sandbox/host.d.ts +2 -1
  166. package/dist/sandbox/host.d.ts.map +1 -1
  167. package/dist/sandbox/host.js +4 -0
  168. package/dist/sandbox/host.js.map +1 -1
  169. package/dist/sandbox/index.d.ts +6 -4
  170. package/dist/sandbox/index.d.ts.map +1 -1
  171. package/dist/sandbox/index.js +9 -6
  172. package/dist/sandbox/index.js.map +1 -1
  173. package/dist/sandbox/path-context.d.ts +4 -0
  174. package/dist/sandbox/path-context.d.ts.map +1 -0
  175. package/dist/sandbox/path-context.js +20 -0
  176. package/dist/sandbox/path-context.js.map +1 -0
  177. package/dist/sandbox/types.d.ts +17 -1
  178. package/dist/sandbox/types.d.ts.map +1 -1
  179. package/dist/sandbox/types.js.map +1 -1
  180. package/dist/sentry.d.ts +20 -1
  181. package/dist/sentry.d.ts.map +1 -1
  182. package/dist/sentry.js +58 -8
  183. package/dist/sentry.js.map +1 -1
  184. package/dist/session-policy.d.ts +13 -0
  185. package/dist/session-policy.d.ts.map +1 -0
  186. package/dist/session-policy.js +23 -0
  187. package/dist/session-policy.js.map +1 -0
  188. package/dist/session-store.d.ts +33 -2
  189. package/dist/session-store.d.ts.map +1 -1
  190. package/dist/session-store.js +179 -13
  191. package/dist/session-store.js.map +1 -1
  192. package/dist/session-view/command.d.ts +5 -0
  193. package/dist/session-view/command.d.ts.map +1 -0
  194. package/dist/session-view/command.js +11 -0
  195. package/dist/session-view/command.js.map +1 -0
  196. package/dist/session-view/portal.d.ts +16 -0
  197. package/dist/session-view/portal.d.ts.map +1 -0
  198. package/dist/session-view/portal.js +1822 -0
  199. package/dist/session-view/portal.js.map +1 -0
  200. package/dist/session-view/service.d.ts +34 -0
  201. package/dist/session-view/service.d.ts.map +1 -0
  202. package/dist/session-view/service.js +427 -0
  203. package/dist/session-view/service.js.map +1 -0
  204. package/dist/session-view/store.d.ts +18 -0
  205. package/dist/session-view/store.d.ts.map +1 -0
  206. package/dist/session-view/store.js +36 -0
  207. package/dist/session-view/store.js.map +1 -0
  208. package/dist/store.d.ts +3 -6
  209. package/dist/store.d.ts.map +1 -1
  210. package/dist/store.js +22 -48
  211. package/dist/store.js.map +1 -1
  212. package/dist/tool-diagnostics.d.ts +2 -0
  213. package/dist/tool-diagnostics.d.ts.map +1 -0
  214. package/dist/tool-diagnostics.js +7 -0
  215. package/dist/tool-diagnostics.js.map +1 -0
  216. package/dist/tools/bash.d.ts +2 -2
  217. package/dist/tools/bash.d.ts.map +1 -1
  218. package/dist/tools/bash.js.map +1 -1
  219. package/dist/tools/edit.d.ts +2 -2
  220. package/dist/tools/edit.d.ts.map +1 -1
  221. package/dist/tools/edit.js.map +1 -1
  222. package/dist/tools/event.d.ts +42 -2
  223. package/dist/tools/event.d.ts.map +1 -1
  224. package/dist/tools/event.js +43 -9
  225. package/dist/tools/event.js.map +1 -1
  226. package/dist/tools/index.d.ts +2 -2
  227. package/dist/tools/index.d.ts.map +1 -1
  228. package/dist/tools/index.js +2 -2
  229. package/dist/tools/index.js.map +1 -1
  230. package/dist/tools/read.d.ts +2 -2
  231. package/dist/tools/read.d.ts.map +1 -1
  232. package/dist/tools/read.js.map +1 -1
  233. package/dist/tools/write.d.ts +2 -2
  234. package/dist/tools/write.d.ts.map +1 -1
  235. package/dist/tools/write.js.map +1 -1
  236. package/dist/trigger.d.ts +31 -0
  237. package/dist/trigger.d.ts.map +1 -0
  238. package/dist/trigger.js +98 -0
  239. package/dist/trigger.js.map +1 -0
  240. package/dist/vault-routing.d.ts +2 -7
  241. package/dist/vault-routing.d.ts.map +1 -1
  242. package/dist/vault-routing.js +6 -42
  243. package/dist/vault-routing.js.map +1 -1
  244. package/dist/vault.d.ts +22 -56
  245. package/dist/vault.d.ts.map +1 -1
  246. package/dist/vault.js +155 -263
  247. package/dist/vault.js.map +1 -1
  248. package/package.json +11 -11
  249. package/dist/bindings.d.ts +0 -44
  250. package/dist/bindings.d.ts.map +0 -1
  251. package/dist/bindings.js +0 -74
  252. package/dist/bindings.js.map +0 -1
  253. package/dist/link-server.d.ts.map +0 -1
  254. package/dist/link-server.js +0 -899
  255. package/dist/link-server.js.map +0 -1
  256. package/dist/link-token.d.ts +0 -32
  257. package/dist/link-token.d.ts.map +0 -1
  258. package/dist/link-token.js.map +0 -1
  259. package/dist/login.d.ts.map +0 -1
  260. package/dist/login.js.map +0 -1
  261. package/dist/sandbox.d.ts +0 -2
  262. package/dist/sandbox.d.ts.map +0 -1
  263. package/dist/sandbox.js +0 -2
  264. package/dist/sandbox.js.map +0 -1
package/README.md CHANGED
@@ -1,71 +1,35 @@
1
- # mama
1
+ # mama (Multi-Agent Mischief Assistant)
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/@geminixiang/mama.svg)](https://www.npmjs.com/package/@geminixiang/mama)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
5
 
6
- A multi-platform AI agent bot for Slack, Telegram, and Discord — based on [pi-mom](https://github.com/badlogic/pi-mono), with the goal of merging improvements back upstream.
6
+ A multi-platform AI assistant for Slack, Telegram, and Discord.
7
7
 
8
- ## 📜 Attribution & Origins
9
-
10
- This project is a **forked and extended version** of the `mom` package from [`badlogic/pi-mono`](https://github.com/badlogic/pi-mono) by Mario Zechner, licensed under MIT.
11
-
12
- - **Original project**: [pi-mom](https://github.com/badlogic/pi-mono/tree/main/packages/mom) (22K+ stars)
13
- - **Base version**: forked from pi-mom v0.57.1 (synchronized with `@mariozechner/*` packages)
14
- - **Primary motivation**: Internal services urgently needed a multi-platform bot — this fork enables rapid iteration while preparing changes to contribute back upstream
15
-
16
- ## 🎯 Positioning & Roadmap
17
-
18
- | Aspect | Description |
19
- | ------------------ | ------------------------------------------------------------------------------ |
20
- | **Current Status** | Temporary standalone fork for urgent internal deployment |
21
- | **Ultimate Goal** | Merge all improvements back into pi-mono monorepo |
22
- | **Unique Value** | Multi-platform support (Slack + Telegram + Discord) to be contributed upstream |
23
-
24
- ### Why a temporary fork?
25
-
26
- Our internal services urgently needed a multi-platform bot, and we couldn't wait for upstream release cycles. This fork allows us to:
27
-
28
- 1. **Ship fast**: Deploy to production immediately while internal demand is high
29
- 2. **Iterate freely**: Test multi-platform adapters (Slack, Telegram, Discord) without monorepo constraints
30
- 3. **Contribute back**: All work here is intended to be merged into pi-mono — `mama` is not a replacement for `mom`
31
-
32
- ### Contribution Philosophy 🔄
33
-
34
- > "This is not a separate product — it's a **temporary fork** for urgent internal needs, and all improvements will be contributed back to pi-mono."
35
-
36
- We actively track the upstream `pi-mom` and plan to:
37
-
38
- - ✅ Submit PRs for platform adapters (Telegram, Discord)
39
- - ✅ Contribute cross-platform abstractions
40
- - ✅ Keep dependencies synchronized with pi-mono releases
41
- - ✅ Document what we learn from production use
42
-
43
- ---
8
+ Forked from [`badlogic/pi-mono`](https://github.com/badlogic/pi-mono)'s `mom` package (MIT, by Mario Zechner) at v0.57.1. This fork adds Telegram and Discord adapters and exists to ship internally while we prepare changes to upstream.
44
9
 
45
10
  ## Features
46
11
 
47
- - **Multi-platform** — Slack, Telegram, and Discord adapters out of the box
48
- - **Persistent sessions** — session behavior is adapted per platform instead of forcing one thread model everywhere
49
- - **Concurrent conversations** — Slack threads, Discord replies/threads, and Telegram reply chains can run independently
50
- - **Sandbox execution** — run agent commands on host, in a shared container, in a managed per-user container, or in a Firecracker VM
51
- - **Credential vaults** — `/login` stores credentials under `--state-dir` and injects env only into container/image/Firecracker runs
52
- - **Persistent memory** — workspace-level and channel-level `MEMORY.md` files
53
- - **Skills** — drop custom CLI tools into `skills/` directories
54
- - **Event system** — schedule one-shot or recurring tasks via JSON files
55
- - **Multi-provider** — configure any provider/model supported by `pi-ai`
12
+ - **Multi-platform** — Slack, Telegram, Discord adapters
13
+ - **Concurrent conversations** — Slack threads, Discord replies/threads, and Telegram reply chains run as independent sessions
14
+ - **Sandbox execution** — host, shared container, per-user managed container, Firecracker (alpha), or Cloudflare bridge (experimental)
15
+ - **Credential vaults** — `/login` stores credentials under `--state-dir` and injects env into sandbox runs
16
+ - **Web session viewer** — read-only web view of the current session via `session` / `/session`
17
+ - **Persistent memory** — workspace-level and channel-level `MEMORY.md`
18
+ - **Skills** — drop CLI tools into `skills/`
19
+ - **Events** — schedule one-shot or recurring tasks via JSON files
20
+ - **Multi-provider** — any provider/model supported by `pi-ai`
56
21
 
57
22
  ## Platform Session Model
58
23
 
59
- | Platform | User Interaction Structure | `sessionKey` Rule | Default Session Model | Special Handling Needed | Notes |
60
- | -------- | ----------------------------------------- | -------------------------------------------------------------------- | ------------------------------------------------------------------------------------ | ----------------------- | ------------------------------------------------------------------------------------------------ |
61
- | Slack | channel top-level + thread replies | top-level: `channelId`; thread: `channelId:threadTs` | channel keeps one persistent session; thread forks from channel into its own session | High | channel -> thread inherits context via fork; thread -> channel does not merge back automatically |
62
- | Discord | normal messages, replies, thread channels | `channelId:threadTsOrMsgId` | replies / thread channels naturally map to isolated sessions | Low | no aliasing layer needed; session identity is determined directly from the Discord event |
63
- | Telegram | private chats, group replies | private chat: `chatId`; group reply chain: `chatId:replyToIdOrMsgId` | private chats use one long session; groups split by reply chain | Medium | Telegram has no native thread model; group sessions are modeled from reply chains |
24
+ | Platform | `sessionKey` Rule | Notes |
25
+ | -------- | --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
26
+ | Slack | top-level / DM: `conversationId`; thread: `conversationId:threadTs` | thread inherits parent context at fork time only; branch changes do not merge back |
27
+ | Discord | DM: `channelId`; shared top-level: `channelId:messageId`; reply/thread: rooted id | replies in shared channels continue the root message session; DM replies do not fork |
28
+ | Telegram | private: `chatId`; shared top-level: `chatId:messageId`; reply chain: root reply | no native thread model; shared sessions are inferred from reply chains |
64
29
 
65
30
  ## Requirements
66
31
 
67
32
  - Node.js >= 20
68
- - One of the platform integrations below
69
33
 
70
34
  ## Installation
71
35
 
@@ -73,442 +37,244 @@ We actively track the upstream `pi-mom` and plan to:
73
37
  npm install -g @geminixiang/mama
74
38
  ```
75
39
 
76
- Or run directly after cloning:
40
+ Or from source:
77
41
 
78
42
  ```bash
79
- npm install
80
- npm run build
43
+ npm install && npm run build
81
44
  ```
82
45
 
83
- ---
84
-
85
46
  ## Quick Start
86
47
 
87
- ### Slack
88
-
89
- 1. Create a Slack app with **Socket Mode** enabled ([setup guide](docs/slack-bot-minimal-guide.md)).
90
- 2. Add the following **OAuth Bot Token Scopes**:
91
- - `app_mentions:read`, `channels:history`, `channels:read`, `chat:write`
92
- - `files:read`, `files:write`, `groups:history`, `groups:read`
93
- - `im:history`, `im:read`, `im:write`, `users:read`
94
- - `assistant:write` — required for native "Thinking" status indicator
95
- 3. Enable the **Home Tab** and **Agent mode**:
96
- - **App Home → Show Tabs** — toggle **Home Tab** on
97
- - **App Home → Agents & AI Apps** — toggle **Agent or Assistant** on
98
- 4. Subscribe to **Bot Events**:
99
- - `app_home_opened`, `app_mention`
100
- - `assistant_thread_context_changed`, `assistant_thread_started`
101
- - `message.channels`, `message.groups`, `message.im`
102
- 5. Enable **Interactivity** (Settings → Interactivity & Shortcuts → toggle on).
103
- 6. (Optional) Add **Slash Commands** such as `/pi-login` and `/pi-new` in the Slack app settings if you want dedicated commands with less naming conflict. `/pi-new` is intended for DM use only.
104
- 7. Copy the **App-Level Token** (`xapp-…`) and **Bot Token** (`xoxb-…`).
105
-
106
- Or import this **App Manifest** directly (Settings → App Manifest → paste JSON):
107
-
108
- <details>
109
- <summary>Example App Manifest</summary>
48
+ All platforms share the same CLI:
110
49
 
111
- ```json
112
- {
113
- "display_information": {
114
- "name": "mama"
115
- },
116
- "features": {
117
- "app_home": {
118
- "home_tab_enabled": true,
119
- "messages_tab_enabled": false,
120
- "messages_tab_read_only_enabled": false
121
- },
122
- "bot_user": {
123
- "display_name": "mama",
124
- "always_online": false
125
- }
126
- },
127
- "oauth_config": {
128
- "scopes": {
129
- "bot": [
130
- "app_mentions:read",
131
- "assistant:write",
132
- "channels:history",
133
- "channels:read",
134
- "chat:write",
135
- "files:read",
136
- "files:write",
137
- "groups:history",
138
- "groups:read",
139
- "im:history",
140
- "im:read",
141
- "im:write",
142
- "users:read"
143
- ]
144
- }
145
- },
146
- "settings": {
147
- "event_subscriptions": {
148
- "bot_events": [
149
- "app_home_opened",
150
- "app_mention",
151
- "assistant_thread_context_changed",
152
- "assistant_thread_started",
153
- "message.channels",
154
- "message.groups",
155
- "message.im"
156
- ]
157
- },
158
- "interactivity": {
159
- "is_enabled": true
160
- },
161
- "org_deploy_enabled": false,
162
- "socket_mode_enabled": true,
163
- "token_rotation_enabled": false
164
- }
165
- }
50
+ ```bash
51
+ mama [--state-dir=~/.mama] [--sandbox=<mode>] <working-directory>
166
52
  ```
167
53
 
168
- </details>
54
+ Set the platform tokens you need (you can run multiple platforms at once):
169
55
 
170
56
  ```bash
171
- export MOM_SLACK_APP_TOKEN=xapp-...
172
- export MOM_SLACK_BOT_TOKEN=xoxb-...
173
-
174
- mama [--state-dir=~/.mama] [--sandbox=host|container:<container>|image:<image>|firecracker:<vm-id>:<path>] <working-directory>
57
+ export MAMA_SLACK_APP_TOKEN=xapp-...
58
+ export MAMA_SLACK_BOT_TOKEN=xoxb-...
59
+ export MAMA_TELEGRAM_BOT_TOKEN=123456:ABC-...
60
+ export MAMA_DISCORD_BOT_TOKEN=MTI...
175
61
  ```
176
62
 
177
- The bot responds when `@mentioned` in any channel or via DM.
63
+ ### Slack
178
64
 
179
- - **Top-level channel messages** share one persistent channel session.
180
- - **Thread replies** — fork from the channel session into an isolated thread session.
181
- - **Thread memory** — inherited at fork time only; thread changes do not merge back into the channel automatically.
182
-
183
- ---
65
+ Create a Socket Mode app with the scopes and event subscriptions listed in [docs/slack-bot-minimal-guide.md](docs/slack-bot-minimal-guide.md). The bot responds when `@mentioned` in channels and to all DMs.
184
66
 
185
67
  ### Telegram
186
68
 
187
- 1. Message [@BotFather](https://t.me/BotFather) `/newbot` to create a bot and get the **Bot Token**.
188
- 2. Optionally disable privacy mode (`/setprivacy → Disable`) so the bot can read group messages without being `@mentioned`.
69
+ Create a bot via [@BotFather](https://t.me/BotFather) and copy the token. The bot responds to all private messages, and to `@mention` or reply chains in groups. Use `/login`, `/session`, `/new`, and `/stop` for controls.
189
70
 
190
- ```bash
191
- export MOM_TELEGRAM_BOT_TOKEN=123456:ABC-...
71
+ ### Discord
192
72
 
193
- mama [--state-dir=~/.mama] [--sandbox=host|container:<container>|image:<image>|firecracker:<vm-id>:<path>] <working-directory>
194
- ```
73
+ Create an application in the [Discord Developer Portal](https://discord.com/developers/applications), enable **Message Content Intent**, and invite the bot with `Send Messages`, `Read Message History`, `Attach Files`. The bot responds to `@mentions` in servers and to all DMs.
195
74
 
196
- - **Private chats** — every message is forwarded to the bot automatically.
197
- - **Group chats** — the bot only responds when `@mentioned` by username.
198
- - **Reply chains** — replying to a previous message continues the same session.
199
- - Say `stop` or `/stop` to cancel a running task.
75
+ ## Sandbox Modes
200
76
 
201
- ---
77
+ | Mode | Description |
78
+ | ---------------------------- | ---------------------------------------------------------------------- |
79
+ | `host` (default) | Run on host; no vault env injection |
80
+ | `container:<name>` | Run in an existing shared container; uses vault key `container-<name>` |
81
+ | `image:<image>` | Auto-provision one Docker container per resolved vault/user |
82
+ | `firecracker:<vm-id>:<path>` | Firecracker microVM (alpha; not recommended) |
83
+ | `cloudflare:<sandbox-id>` | Cloudflare Worker bridge (experimental; no auto workspace sync) |
202
84
 
203
- ### Discord
85
+ Vault routing: `image`, `firecracker`, and `cloudflare` resolve a vault per platform userId. See [docs/sandbox.md](docs/sandbox.md) for the full matrix.
204
86
 
205
- 1. Go to the [Discord Developer Portal](https://discord.com/developers/applications) → **New Application**.
206
- 2. Under **Bot**, enable **Message Content Intent** (required to read message text).
207
- 3. Under **OAuth2 → URL Generator**, select scopes `bot` + permissions `Send Messages`, `Read Message History`, `Attach Files`. Invite the bot to your server with the generated URL.
208
- 4. Copy the **Bot Token**.
87
+ ### Managed per-user containers (`image:*`)
209
88
 
210
89
  ```bash
211
- export MOM_DISCORD_BOT_TOKEN=MTI...
212
-
213
- mama [--state-dir=~/.mama] [--sandbox=host|container:<container>|image:<image>|firecracker:<vm-id>:<path>] <working-directory>
90
+ docker pull ghcr.io/geminixiang/mama-sandbox:latest
91
+ mama --sandbox=image:ghcr.io/geminixiang/mama-sandbox:latest /path/to/workspace
214
92
  ```
215
93
 
216
- - **Server channels** — the bot responds when `@mentioned`.
217
- - **DMs** — every message is forwarded automatically.
218
- - **Threads** — messages inside a Discord thread share a single session.
219
- - **Reply chains** — replying to a message continues that session.
220
- - Say `stop` or `/stop` to cancel a running task.
221
-
222
- ---
223
-
224
- ## Options
225
-
226
- | Option | Default | Description |
227
- | -------------------------------------- | --------- | ----------------------------------------------------------------- |
228
- | `--state-dir=<dir>` | `~/.mama` | Store settings, credential vaults, and bindings outside workspace |
229
- | `--sandbox=host` | ✓ | Run commands directly on host; vault env is not injected |
230
- | `--sandbox=container:<name>` | | Run commands in an existing shared container |
231
- | `--sandbox=image:<image>` | | Auto-provision one Docker container per platform user |
232
- | `--sandbox=firecracker:<vm-id>:<path>` | | Run commands inside a Firecracker microVM |
233
- | `--download <channel-id>` | | Download channel history to stdout and exit (Slack only) |
234
-
235
- ### Sandbox and Vault Semantics
236
-
237
- - `host`: no vault env injection.
238
- - `container:<name>`: one container maps to one shared vault key: `container-<name>`.
239
- - `image:<image>`: mama creates one container per resolved vault/user and injects that vault's env and file mounts.
240
- - `firecracker:*`: per-user vault routing via `bindings.json` first, then direct userId vault.
241
- - `docker:*` is not supported; use `container:*` or `image:*`.
242
-
243
- See [docs/sandbox.md](docs/sandbox.md) for the full sandbox/vault behavior matrix.
244
-
245
- ### Download channel history (Slack)
94
+ Or build locally:
246
95
 
247
96
  ```bash
248
- mama --download C0123456789
97
+ docker build -f docker/mama-sandbox.Dockerfile -t mama-sandbox:tools .
249
98
  ```
250
99
 
251
- ## `/login` Credential Onboarding
100
+ mama creates one container per vault, attaches each to its own bridge network, mounts the workspace at `/workspace`, injects vault env, mounts declared credential files, and stops idle containers.
252
101
 
253
- For normal deployments, set `MOM_LINK_URL` to the externally reachable base URL of the web credential onboarding flow:
254
-
255
- ```bash
256
- export MOM_LINK_URL="https://mama.example.com"
257
- # optional; defaults to 8181 when MOM_LINK_URL is set
258
- export MOM_LINK_PORT=8181
259
- ```
102
+ ### Firecracker / Cloudflare
260
103
 
261
- For local-only testing, you can set `MOM_LINK_PORT` without `MOM_LINK_URL`; mama will use `http://localhost:<port>` for the onboarding link.
104
+ See [docs/firecracker-setup.md](docs/firecracker-setup.md) and [examples/cloudflare-sandbox-bridge/README.md](examples/cloudflare-sandbox-bridge/README.md).
262
105
 
263
- Users can then run `/login` in a private conversation with the bot. mama returns a 15-minute link for storing API keys or using built-in OAuth providers. `/login` is rejected in shared channels to avoid leaking onboarding links.
106
+ ## `/login` and Web Session Viewer
264
107
 
265
- On Slack, you can also register native slash commands such as `/pi-login` and `/pi-new`.
108
+ ```bash
109
+ export MAMA_LINK_URL="https://mama.example.com" # public base URL
110
+ export MAMA_LINK_PORT=8181 # optional, defaults to 8181
111
+ ```
266
112
 
267
- - `/pi-login` in a shared channel opens a DM and continues the credential flow there.
268
- - `/pi-new` only works in a Slack DM and resets that DM session context.
113
+ For local testing you can set just `MAMA_LINK_PORT`; mama will use `http://localhost:<port>`.
269
114
 
270
- Built-in OAuth guides:
115
+ - `/login` / `/pi-login` (DM only) returns a 15-minute link to store API keys or run built-in OAuth flows ([GitHub](docs/oauth/github.md), [Google Workspace](docs/oauth/google-workspace.md), [Google Cloud SDK / gcloud](docs/oauth/google-cloud-sdk.md)).
116
+ - `session` / `/session` (DM only) returns a read-only link showing the current session timeline.
117
+ - `new` / `/new` (DM only) resets the current session and starts fresh.
118
+ - `model` / `/model` / `/pi-model provider/model[:thinking]` switches the LLM for the current conversation, e.g. `/pi-model anthropic/claude-sonnet-4-6:off`.
119
+ - `auto-reply` / `/pi-auto-reply on|off|status` controls group/channel auto-reply for the current conversation. Rules live in the conversation's `auto-reply` marker file.
120
+ - `stop` / `/stop` stops the current run. On Slack, use text commands so thread-local stop routing remains accurate.
121
+ - On Slack you can also register native commands like `/pi-login`, `/pi-session`, `/pi-model`, `/pi-auto-reply`, and `/pi-new`.
271
122
 
272
- - [GitHub OAuth](docs/oauth/github.md)
273
- - [Google Workspace CLI OAuth](docs/oauth/google-workspace.md)
123
+ Credentials are stored under `<state-dir>/vaults` (default `~/.mama/vaults`). Vault env is only injected in `container`, `image`, `firecracker`, and `cloudflare` modes.
274
124
 
275
- Credentials are stored under `<state-dir>/vaults` (default `~/.mama/vaults`). Runtime env injection only happens in `container`, `image`, and `firecracker` modes.
125
+ Shared login profiles live under `<state-dir>/vaults/shared/<name>`. `/pi-login copy <name>` merge-copies that shared profile into the current conversation vault: shared env keys overwrite matching conversation env keys, conversation-only env keys are kept, and files from the shared profile overwrite files at the same relative path. To seed every new managed sandbox vault from a shared profile, fill in `sandbox.defaultSharedVault` in `<state-dir>/settings.json` (onboard creates it as an empty string), for example `{ "sandbox": { "defaultSharedVault": "claw" } }`. Empty string disables the default. The default profile is copied only when the target vault does not exist yet.
276
126
 
277
127
  ## Configuration
278
128
 
279
- mama loads settings from `<state-dir>/settings.json` first, then falls back to `<working-directory>/settings.json` if the state-dir file is absent. For shared bot deployments, prefer the state-dir copy:
129
+ mama reads global settings from `<state-dir>/settings.json` (default `~/.mama/settings.json`, override via `--state-dir` or `MAMA_STATE_DIR`). This file is required and is created explicitly with `mama --onboard`. Per-conversation settings live at `<workingDir>/<conversationId>/settings.json` and override global settings for that conversation.
280
130
 
281
131
  ```json
282
132
  {
283
- "provider": "anthropic",
284
- "model": "claude-sonnet-4-5",
285
- "thinkingLevel": "off",
286
- "sessionScope": "thread",
287
- "logFormat": "console",
288
- "logLevel": "info",
289
- "sentryDsn": "https://examplePublicKey@o0.ingest.sentry.io/0"
133
+ "llm": {
134
+ "provider": "anthropic",
135
+ "model": "claude-sonnet-4-6",
136
+ "thinkingLevel": "off"
137
+ },
138
+ "sentry": {
139
+ "dsn": "https://examplePublicKey@o0.ingest.sentry.io/0"
140
+ },
141
+ "sandbox": {
142
+ "cpus": "0.5",
143
+ "memory": "512m",
144
+ "boost": {
145
+ "cpus": "2",
146
+ "memory": "4g"
147
+ }
148
+ }
290
149
  }
291
150
  ```
292
151
 
293
- | Field | Default | Description |
294
- | --------------- | ------------------- | -------------------------------------------------------- |
295
- | `provider` | `anthropic` | AI provider (env: `MOM_AI_PROVIDER`) |
296
- | `model` | `claude-sonnet-4-5` | Model name (env: `MOM_AI_MODEL`) |
297
- | `thinkingLevel` | `off` | `off` / `low` / `medium` / `high` |
298
- | `sessionScope` | `thread` | `thread` (per thread/reply chain) or `channel` |
299
- | `logFormat` | `console` | `console` (colored stdout) or `json` (GCP Cloud Logging) |
300
- | `logLevel` | `info` | `trace` / `debug` / `info` / `warn` / `error` |
301
- | `sentryDsn` | unset | Sentry DSN (preferred over env `SENTRY_DSN`) |
302
-
303
- When `sentryDsn` is set, mama sends Sentry events with sensitive prompt/tool content redacted before upload.
152
+ | Field | Default | Description |
153
+ | ---------------------- | ------------------- | ----------------------------------------------------- |
154
+ | `llm.provider` | `anthropic` | AI provider |
155
+ | `llm.model` | `claude-sonnet-4-6` | Model name |
156
+ | `llm.thinkingLevel` | `off` | `off` / `low` / `medium` / `high` |
157
+ | `sentry.dsn` | unset | Sentry DSN; sensitive prompt/tool content is redacted |
158
+ | `sandbox.cpus` | unset | CPU limit for managed containers |
159
+ | `sandbox.memory` | unset | Memory limit for managed containers |
160
+ | `sandbox.boost.cpus` | unset | Temporary CPU limit used by `/pi-sandbox boost` |
161
+ | `sandbox.boost.memory` | unset | Temporary memory limit used by `/pi-sandbox boost` |
304
162
 
305
- ### GCP Cloud Logging (Compute Engine)
163
+ `/pi-sandbox` shows the current managed-container CPU/memory limits. `/pi-sandbox boost` temporarily applies `sandbox.boost` to the current conversation; the boost ends when that sandbox container is stopped.
306
164
 
307
- Set `logFormat: "json"` to send structured logs directly to Cloud Logging via API no Ops Agent or log file configuration needed.
308
-
309
- **Requirements:**
310
-
311
- 1. VM service account has `roles/logging.logWriter`
312
- 2. `GOOGLE_CLOUD_PROJECT` env var is set
313
-
314
- ```bash
315
- GOOGLE_CLOUD_PROJECT=<your-project-id> mama <working-directory>
316
- ```
317
-
318
- In `<state-dir>/settings.json` (or `<working-directory>/settings.json` as a fallback):
165
+ Conversation-local settings written by `/pi-model` use the same shape and usually only include the override:
319
166
 
320
167
  ```json
321
168
  {
322
- "logFormat": "json",
323
- "logLevel": "info"
169
+ "llm": {
170
+ "provider": "anthropic",
171
+ "model": "claude-sonnet-4-6",
172
+ "thinkingLevel": "off"
173
+ }
324
174
  }
325
175
  ```
326
176
 
327
- Logs appear in Cloud Logging under **Log name: `mama`**. Console output (stdout) is unaffected and continues to work alongside Cloud Logging.
177
+ mama writes logs to stdout/stderr. Use your process manager or host platform (for example PM2, systemd, Docker, or a cloud logging agent) to route logs to your preferred backend.
328
178
 
329
- ## State Directory Layout
179
+ ## Layout
330
180
 
331
181
  ```
332
182
  <state-dir>/
333
- ├── settings.json # Preferred provider/model/logging/Sentry config
183
+ ├── settings.json
334
184
  └── vaults/
335
- ├── bindings.json # Platform user -> vault mapping
336
- ├── vault.json # Vault metadata
337
185
  └── <vault-id>/
338
- ├── env # Injected env vars
339
- └── ... # Credential files (e.g. gws.json, .ssh/)
340
- ```
341
-
342
- ## Working Directory Layout
186
+ ├── env
187
+ └── ... # credential files
343
188
 
344
- ```
345
189
  <working-directory>/
346
- ├── settings.json # Optional fallback config if <state-dir>/settings.json is absent
347
- ├── MEMORY.md # Global memory (all channels)
348
- ├── SYSTEM.md # Installed packages / env changes log
349
- ├── skills/ # Global skills (CLI tools)
350
- ├── events/ # Scheduled event files
351
- └── <channel-id>/
352
- ├── MEMORY.md # Channel-specific memory
353
- ├── log.jsonl # Full message history
354
- ├── attachments/ # Downloaded user files
355
- ├── scratch/ # Agent working directory
356
- ├── skills/ # Channel-specific skills
190
+ ├── MEMORY.md # global memory
191
+ ├── SYSTEM.md # installed packages / env log
192
+ ├── skills/ # global skills
193
+ ├── events/ # scheduled events
194
+ └── <conversation-id>/
195
+ ├── MEMORY.md
196
+ ├── auto-reply[.disabled] # optional channel auto-reply rules
197
+ ├── log.jsonl
198
+ ├── attachments/
199
+ ├── scratch/
200
+ ├── skills/
357
201
  └── sessions/
358
- ├── current # Pointer for the channel-level session
359
- ├── 2026-04-05T18-04-31-010Z_1d92b3ad.jsonl
360
- └── <thread-ts>.jsonl # Fixed-path thread session
361
202
  ```
362
203
 
363
- ## Container Sandbox
364
-
365
- ```bash
366
- # Create a container (mount your working directory to /workspace)
367
- docker run -d --name mama-tools \
368
- -v /path/to/workspace:/workspace \
369
- alpine:latest sleep infinity
370
-
371
- # Start mama with container sandbox
372
- mama --sandbox=container:mama-tools /path/to/workspace
373
- ```
204
+ ## Events
374
205
 
375
- `container:mama-tools` uses vault key `container-mama-tools`. If multiple users share the same container, they share that container vault.
206
+ Drop JSON files into `<working-directory>/events/`:
376
207
 
377
- ## Managed Per-User Container Sandbox
208
+ ```json
209
+ // Immediate
210
+ {"type": "immediate", "platform": "slack", "conversationId": "C0123456789", "conversationKind": "shared", "text": "Deploy finished"}
378
211
 
379
- ```bash
380
- # Build the bundled image once
381
- docker build -f docker/mama-sandbox.Dockerfile -t mama-sandbox:tools .
212
+ // One-shot
213
+ {"type": "one-shot", "platform": "telegram", "conversationId": "574247312", "conversationKind": "direct", "text": "Standup", "at": "2025-12-15T09:00:00+08:00"}
382
214
 
383
- # Start mama with managed image sandboxes
384
- mama --sandbox=image:mama-sandbox:tools /path/to/workspace
215
+ // Periodic (cron)
216
+ {"type": "periodic", "platform": "discord", "conversationId": "1498975469343739948", "conversationKind": "shared", "text": "Check inbox", "schedule": "0 9 * * 1-5", "timezone": "Asia/Taipei"}
385
217
  ```
386
218
 
387
- In this mode mama creates one Docker container per resolved vault/user, mounts the workspace at `/workspace`, injects vault env on execution, mounts any credential files declared in the vault, and stops idle containers automatically.
388
-
389
- ## Firecracker Sandbox
390
-
391
- Firecracker provides lightweight VM isolation with the security benefits of a hypervisor. Unlike Docker containers, Firecracker runs a full Linux kernel, providing stronger isolation.
392
-
393
- ### Requirements
394
-
395
- - SSH access to the Firecracker VM
396
- - SSH key-based authentication configured
397
- - Host workspace must be mounted at `/workspace` inside the VM
398
-
399
- ### Format
219
+ ## Skills
400
220
 
401
221
  ```
402
- --sandbox=firecracker:<vm-id>:<host-path>[:<ssh-user>[:<ssh-port>]]
222
+ skills/my-tool/
223
+ ├── SKILL.md # name + description frontmatter, usage docs
224
+ └── run.sh
403
225
  ```
404
226
 
405
- | Parameter | Default | Description |
406
- | ----------- | ------- | ------------------------------ |
407
- | `vm-id` | - | VM identifier (hostname or IP) |
408
- | `host-path` | - | Working directory on the host |
409
- | `ssh-user` | `root` | SSH username |
410
- | `ssh-port` | `22` | SSH port |
411
-
412
- ### Examples
413
-
414
- ```bash
415
- # Basic usage (VM at 192.168.1.100, default ssh user root:22)
416
- mama --sandbox=firecracker:192.168.1.100:/home/user/workspace /home/user/workspace
417
-
418
- # Custom SSH user
419
- mama --sandbox=firecracker:192.168.1.100:/home/user/workspace:ubuntu /home/user/workspace
227
+ ```yaml
228
+ ---
229
+ name: my-tool
230
+ description: Does something useful
231
+ ---
420
232
 
421
- # Custom SSH port
422
- mama --sandbox=firecracker:192.168.1.100:/home/user/workspace:root:2222 /home/user/workspace
233
+ Usage: {baseDir}/run.sh <args>
423
234
  ```
424
235
 
425
- ### Setup
426
-
427
- 1. **Start a Firecracker VM** with your preferred method (fc-agent, firecracker-ctl, or manual)
428
-
429
- 2. **Configure SSH access** inside the VM:
430
-
431
- ```bash
432
- # Inside the VM - allow password-less SSH for mama
433
- sudo systemctl enable ssh
434
- sudo sed -i 's/^#*PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config
435
- sudo sed -i 's/^#*PubkeyAuthentication.*/PubkeyAuthentication yes/' /etc/ssh/sshd_config
436
- sudo systemctl restart ssh
437
- ```
438
-
439
- 3. **Mount your workspace** at `/workspace` inside the VM:
440
-
441
- ```bash
442
- # Option A: 9pfs (recommended, from host)
443
- sudo mount -t 9p -o trans=virtio,version=9p2000.L host0 /workspace
444
-
445
- # Option B: NFS
446
- sudo mount -t nfs <host-ip>:/path/to/workspace /workspace
447
- ```
448
-
449
- 4. **Test SSH connectivity** from host:
450
- ```bash
451
- ssh root@192.168.1.100 "echo works"
452
- ```
236
+ ## Slack: Download channel history
453
237
 
454
- The host path is mounted as `/workspace` inside the Firecracker VM. All bash commands will execute inside the VM.
238
+ ```bash
239
+ mama --download C0123456789
240
+ ```
455
241
 
456
- ## Events
242
+ ## Production deployment (PM2)
457
243
 
458
- Drop JSON files into `<working-directory>/events/` to trigger the agent:
244
+ For long-running deployments, use [PM2](https://pm2.keymetrics.io/) as a process supervisor. It daemonizes mama, restarts on crash, and survives reboots.
459
245
 
460
- ```json
461
- // Immediate triggers as soon as mama sees the file
462
- {"type": "immediate", "conversationId": "C0123456789", "conversationKind": "shared", "text": "New deployment finished"}
246
+ ```bash
247
+ # 1. Install mama and pm2
248
+ npm i -g @geminixiang/mama pm2
463
249
 
464
- // One-shot triggers once at a specific time
465
- {"type": "one-shot", "conversationId": "C0123456789", "conversationKind": "shared", "text": "Daily standup reminder", "at": "2025-12-15T09:00:00+08:00"}
250
+ # 2. Start the sandbox container (long-lived; mama execs into it)
251
+ docker pull ghcr.io/geminixiang/mama-sandbox:latest
466
252
 
467
- // Periodic triggers on a cron schedule
468
- {"type": "periodic", "conversationId": "C0123456789", "conversationKind": "shared", "text": "Check inbox", "schedule": "0 9 * * 1-5", "timezone": "Asia/Taipei"}
253
+ # 3. Grab the ecosystem file, edit args + env tokens, then start
254
+ curl -O https://raw.githubusercontent.com/geminixiang/mama/main/deploy/pm2/ecosystem.config.cjs
255
+ pm2 start ecosystem.config.cjs
256
+ pm2 save
257
+ pm2 startup # run the printed command to enable boot autostart
469
258
  ```
470
259
 
471
- ## Skills
472
-
473
- Create reusable CLI tools by adding a directory with a `SKILL.md`:
260
+ Upgrade flow:
474
261
 
475
- ```
476
- skills/
477
- └── my-tool/
478
- ├── SKILL.md # name + description frontmatter, usage docs
479
- └── run.sh # the actual script
262
+ ```bash
263
+ npm i -g @geminixiang/mama && pm2 reload mama
480
264
  ```
481
265
 
482
- `SKILL.md` frontmatter:
266
+ `pm2 reload` sends SIGTERM and waits up to `kill_timeout` (60s in the shipped config) before SIGKILL. mama's internal graceful shutdown drains in-flight LLM turns within that window, so reloads do not interrupt active conversations.
483
267
 
484
- ```yaml
485
- ---
486
- name: my-tool
487
- description: Does something useful
488
- ---
489
-
490
- Usage: {baseDir}/run.sh <args>
491
- ```
268
+ See [`deploy/pm2/ecosystem.config.cjs`](deploy/pm2/ecosystem.config.cjs) for all tunables.
492
269
 
493
270
  ## Development
494
271
 
495
272
  ```bash
496
273
  npm run dev # watch mode
497
- npm test # run tests
498
- npm run build # production build
274
+ npm test
275
+ npm run build
499
276
  ```
500
277
 
501
- ## 📦 Dependencies & Versions
502
-
503
- | Package | mama Version | pi-mom Synced Version |
504
- | ------------------------------- | ------------ | -------------------------------- |
505
- | `@mariozechner/pi-agent-core` | `^0.69.0` | ✅ Synchronized |
506
- | `@mariozechner/pi-ai` | `^0.69.0` | ✅ Synchronized |
507
- | `@mariozechner/pi-coding-agent` | `^0.69.0` | ✅ Synchronized |
508
- | `@anthropic-ai/sandbox-runtime` | `^0.0.49` | ⚠️ Newer than original fork base |
509
-
510
278
  ## License
511
279
 
512
- MIT — see [LICENSE](LICENSE).
513
-
514
- **Note**: This project inherits the MIT license from pi-mom and aims to keep its contributions compatible with the upstream ecosystem.
280
+ MIT — see [LICENSE](LICENSE). Inherits from pi-mom.