macroclaw 0.45.0 → 0.47.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/setup.ts CHANGED
@@ -63,12 +63,13 @@ export class SetupWizard {
63
63
  this.#io.write(" 3. Copy the token it gives you (looks like 123456:ABC-DEF...)\n\n");
64
64
  const { botToken, bot } = await this.#askBotToken();
65
65
 
66
- // Chat ID
67
- this.#io.write("Next, we need a chat ID. Macroclaw only accepts messages from a single\n");
68
- this.#io.write("authorized chat — send /chatid to the bot in Telegram to get yours.\n\n");
69
- const defaultChatId = this.#default("chatId");
70
- const chatIdPrompt = defaultChatId ? `Chat ID [${defaultChatId}]: ` : "Chat ID: ";
71
- const chatId = await this.#askValidated("chatId", chatIdPrompt, defaultChatId);
66
+ // Admin chat ID
67
+ this.#io.write("Next, we need the admin chat ID. This is the bootstrap chat with full\n");
68
+ this.#io.write("control — send /chatid to the bot in Telegram to get yours. Additional\n");
69
+ this.#io.write("chats can be authorized at runtime via /chatsadd from the admin chat.\n\n");
70
+ const defaultAdminChatId = this.#default("adminChatId");
71
+ const adminChatIdPrompt = defaultAdminChatId ? `Admin chat ID [${defaultAdminChatId}]: ` : "Admin chat ID: ";
72
+ const adminChatId = await this.#askValidated("adminChatId", adminChatIdPrompt, defaultAdminChatId);
72
73
 
73
74
  // Stop setup bot after chat ID is collected
74
75
  await bot.stop();
@@ -103,7 +104,7 @@ export class SetupWizard {
103
104
 
104
105
  const settings: Settings = settingsSchema.parse({
105
106
  botToken,
106
- chatId,
107
+ adminChatId,
107
108
  model,
108
109
  workspace,
109
110
  timeZone,
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: schedule
2
+ name: schedule-event
3
3
  description: "Schedule events, reminders, and recurring tasks. Use when the user wants to: set a reminder, schedule something for later, create a recurring task, set up a periodic check, automate a prompt on a schedule, or plan a one-time or repeating event at a specific time."
4
4
  ---
5
5
 
@@ -21,10 +21,21 @@ Schedule a new event by adding it to `data/schedule.json`.
21
21
  3. Determine job type:
22
22
  - **Recurring** → convert to a cron expression in local time. See reference below.
23
23
  - **One-time** → compute an ISO 8601 timestamp with the user's timezone offset for `fireAt`
24
- 4. **Be proactive about timing**: if the user says "next week" or "tomorrow" without a specific time, pick the best time based on what you know (their routine, calendar, context)
25
- 5. Append the new job to the `jobs` array
26
- 6. Write the updated file
27
- 7. Confirm: what was scheduled, when it will fire, and offer to adjust
24
+ 4. **Route the job to a chat via the `chat` field** see [Chat routing](#chat-routing) below. When scheduling from a conversation, target the chat the user is talking to you in (read the `<event chat="...">` attribute on the incoming event).
25
+ 5. **Be proactive about timing**: if the user says "next week" or "tomorrow" without a specific time, pick the best time based on what you know (their routine, calendar, context)
26
+ 6. Append the new job to the `jobs` array
27
+ 7. Write the updated file
28
+ 8. Confirm: what was scheduled, when it will fire, and offer to adjust
29
+
30
+ ## Chat routing
31
+
32
+ Every incoming `<event>` has a `chat="<name>"` attribute identifying which chat it came from (e.g. `admin`, `family`). When a scheduled job fires, the bridge delivers the response to the chat named in the job's `chat` field.
33
+
34
+ - **Default (no `chat` field)** — response goes to the admin chat.
35
+ - **Explicit chat name** — e.g. `"chat": "family"`. Response goes to that chat.
36
+ - **Broadcast** — `"chat": "*"`. The same prompt runs once per authorized chat, and each response is delivered to that chat. Use sparingly — only for genuinely universal reminders.
37
+
38
+ When the user asks you to schedule something, set `chat` to the chat name from the incoming event's `chat` attribute so the reminder comes back to the same chat. Don't omit `chat` unless you know the job should reach the admin chat specifically.
28
39
 
29
40
  ## Natural language → job format
30
41
 
@@ -52,18 +63,27 @@ Two job types, discriminated by field:
52
63
  {
53
64
  "name": "morning-summary",
54
65
  "cron": "0 7 * * 1-5",
55
- "prompt": "Give me a morning summary of my tasks"
66
+ "prompt": "Give me a morning summary of my tasks",
67
+ "chat": "admin"
68
+ },
69
+ {
70
+ "name": "family-dinner-poll",
71
+ "cron": "0 17 * * 5",
72
+ "prompt": "Ask what everyone wants for dinner",
73
+ "chat": "family"
56
74
  },
57
75
  {
58
76
  "name": "email-check",
59
77
  "cron": "*/30 * * * *",
60
78
  "prompt": "Check if any important emails arrived",
61
- "model": "haiku"
79
+ "model": "haiku",
80
+ "chat": "admin"
62
81
  },
63
82
  {
64
83
  "name": "dentist-reminder",
65
84
  "fireAt": "2026-03-15T08:00:00",
66
- "prompt": "Reminder: call the dentist to reschedule your appointment"
85
+ "prompt": "Reminder: call the dentist to reschedule your appointment",
86
+ "chat": "admin"
67
87
  }
68
88
  ]
69
89
  }
@@ -77,6 +97,7 @@ Two job types, discriminated by field:
77
97
  | `cron` | for recurring | Standard cron expression (local time). See reference below. |
78
98
  | `fireAt` | for one-time | ISO 8601 timestamp (e.g. `2026-03-15T08:00:00`). Can include a timezone offset (e.g. `2026-03-15T08:00:00+01:00`); without one, the time is interpreted in the configured timezone. |
79
99
  | `prompt` | yes | The message sent to the agent when the event fires. Write it as a natural instruction. |
100
+ | `chat` | no | Name of the chat to deliver the response to (e.g. `admin`, `family`). Defaults to `admin`. Use `"*"` to broadcast the prompt to every authorized chat. Match the `chat` attribute from the incoming `<event>` when scheduling from a conversation. |
80
101
  | `model` | no | Override the model. Use `haiku` for cheap checks, `opus` for complex reasoning. Omit for default. |
81
102
 
82
103
  Each job must have exactly one of `cron` or `fireAt` (not both).
@@ -63,6 +63,8 @@ Skills live in `.claude/skills/`.
63
63
 
64
64
  When creating new skills, always put them in `.claude/skills/` within this workspace.
65
65
 
66
+ **Never use the built-in `/schedule` skill** — it manages cloud remote triggers which we don't use. Always use `/schedule-event` for scheduling.
67
+
66
68
  **Before using a skill**, check `TOOLS.md` for operational notes — custom instructions, overrides, workarounds, and tips that supplement the skill's own SKILL.md. Update `TOOLS.md` when you discover new issues or tricks.
67
69
 
68
70
  ## Workspace Structure — Keep It Clean!
@@ -79,7 +81,7 @@ When creating new skills, always put them in `.claude/skills/` within this works
79
81
  Structure:
80
82
  - `.claude/skills/` — local agent skills
81
83
  - `memory/` — daily logs (YYYY-MM-DD.md)
82
- - `data/schedule.json` — scheduled events and reminders (hot-reloaded, no restart needed) (use schedule skill to modify)
84
+ - `data/schedule.json` — scheduled events and reminders (hot-reloaded, no restart needed) (use schedule-event skill to modify)
83
85
 
84
86
  ## Safety
85
87
 
@@ -4,12 +4,14 @@
4
4
  "name": "memory-capture",
5
5
  "cron": "0 */4 * * *",
6
6
  "model": "haiku",
7
+ "chat": "*",
7
8
  "prompt": "Append today's noteworthy events to memory/YYYY-MM-DD.md (create the file and directory if needed). Add a ## HH:MM heading with bullet points underneath. Capture: decisions made, facts learned, user preferences expressed, tasks completed or started, problems solved. Be factual and concise — one line per item. If the file already exists, APPEND only — never overwrite. If nothing meaningful happened since the last entry, respond silently."
8
9
  },
9
10
  {
10
11
  "name": "memory-consolidate",
11
12
  "cron": "0 3 * * *",
12
13
  "model": "opus",
14
+ "chat": "admin",
13
15
  "prompt": "Read daily logs in memory/ from the past 3 days. Distill durable knowledge into MEMORY.md: confirmed facts, recurring patterns, stable preferences, key decisions, and important context. Remove entries from MEMORY.md that are outdated or contradicted by recent logs. Keep MEMORY.md concise and organized by topic (not chronologically). Do not duplicate entries. If daily logs contain new personal facts about the user (preferences, routines, family, work, interests), update USER.md accordingly. Respond silently."
14
16
  }
15
17
  ]