Install
openclaw skills install savenowSave durable notes from the current OpenClaw + Telegram conversation into today's memory/YYYY-MM-DD.md, with a semantic-dedupe preview/apply flow and inline Apply/Cancel buttons. Use for /savenow on Telegram-backed sessions.
openclaw skills install savenowUse this skill when the user wants to persist the current conversation into the active agent's daily memory file.
The command name is /savenow.
Scope: OpenClaw + Telegram only. Relies on sessions_list / sessions_history, the runtime MessageThreadId, and Telegram inline keyboards. Vanilla Claude Code, CLI, and web surfaces are not supported by design.
Supported forms:
/savenow — preview only. Extract candidates, compare semantically against today's memory, show markdown diff + Apply/Cancel inline buttons. Writes nothing./savenow apply — write the most recent pending preview (within the 30-minute TTL and from the same session/topic)./savenow cancel — discard the pending preview without writing./savenow auto — extract + compare + write directly. Skip preview and buttons./savenow auto <sessionKey> — auto on an explicit session./savenow list — show same-topic candidate sessions without writing./savenow <sessionKey> — preview against an explicit session.Write only durable, high-value notes to memory/YYYY-MM-DD.md in the current agent workspace.
Do not patch built-in commands. Do not change Telegram settings. Do not write MEMORY.md.
Keep:
Skip:
Inspect the raw command argument first and pick a branch:
| Arg | Branch | Writes? |
|---|---|---|
| (empty) | preview | no |
list | list (unchanged) | no |
apply | apply | yes, from pending |
cancel | cancel | no, deletes pending |
auto | auto on resolved session | yes |
auto <key> | auto on explicit key | yes |
| other token | explicit-session preview | no |
/savenow (and explicit-session preview)Resolve the target session.
CommandTargetSessionKey, use it.list/apply/cancel/auto, treat it as the explicit sessionKey.MessageThreadId from runtime, call sessions_list, filter strictly:
:slash:cron, hook, node kinds/savenow <sessionKey>. Do not write.Read the transcript. Call sessions_history against the resolved target session with includeTools: false, limit: 120..180.
Read today's memory file (new step). Use the Read tool on memory/YYYY-MM-DD.md so the agent can perform semantic comparison. If the file does not exist yet, proceed as if empty.
Extract 0..5 candidate memory entries. Each entry must be specific, reusable, short, self-contained. For each candidate, perform semantic comparison against existing sections in the memory file and assign an action:
"add" — net-new durable note"merge" — substantial overlap with an existing section; adds new bullets to it (set merge_target_title to the exact existing title)"skip" — semantically already covered, or not durable enoughJSON shape (write to temp/savenow-entries.json):
[
{
"candidate_index": 0,
"title": "Gateway token mismatch fix",
"bullets": [
"Resolved `unauthorized: gateway token mismatch` by updating `gateway.cmd` and the related env variables.",
"Next time a similar error appears, check token and env alignment first."
],
"action": "add",
"reason": ""
},
{
"candidate_index": 1,
"title": "Telegram inline button rules",
"bullets": ["Inline keyboards use a single-row, 3-button layout."],
"action": "merge",
"merge_target_title": "Telegram UI conventions",
"reason": "New rule belongs to the same existing topic."
}
]
Backward-compat: { "title": "...", "bullets": [...] } without action is treated as "add".
Run the preview script from the workspace root:
node "{baseDir}/scripts/preview-diff.mjs" \
--entries-file "temp/savenow-entries.json" \
--memory-path "memory/YYYY-MM-DD.md" \
--pending-file "temp/savenow-pending.json" \
--session-key "<resolved sessionKey>" \
--message-thread-id "<MessageThreadId>" \
--ttl-minutes 30
Pipe the script's stdout to the chat as the user-facing reply.
Render a Telegram inline keyboard below the markdown reply, two buttons in a single row:
✅ Apply → callback /savenow apply❌ Cancel → callback /savenow cancelIf the script reports 0 candidates, do not render the keyboard (nothing to apply).
/savenow applyRead temp/savenow-pending.json. Reject with a one-liner if:
"No pending preview, run /savenow first."expiresAt < now → "Preview expired (X min ago), rerun /savenow."sessionKey or messageThreadId mismatches the current runtime → "Pending preview is from a different topic. Rerun /savenow here."Run the merge script using entriesFile from the pending JSON:
node "{baseDir}/scripts/merge-daily-memory.mjs" --entries-file "<pending.entriesFile>"
On success delete temp/savenow-pending.json (and the entries file if you wish to clean up).
Reply briefly (no buttons):
Saved to memory/2026-05-15.md: Gateway token mismatch fix (+2 bullets to "Telegram UI conventions").
Mini summary: saved gateway auth fix and a Telegram button rule.
Mention added titles, merged titles (with bullet counts), and any fallbackAdded / fallbackSkipped events from the script's JSON output.
/savenow canceltemp/savenow-pending.json exists, delete it. Also delete temp/savenow-entries.json if it exists.Pending preview cancelled. Nothing written.No pending preview to cancel. (not an error.)/savenow auto [sessionKey]Run steps 1–4 from the preview branch (resolve session, pull transcript, read today's memory, extract candidates with actions).
Skip the preview script and pending file.
Run the merge script directly:
node "{baseDir}/scripts/merge-daily-memory.mjs" --entries-file "temp/savenow-entries.json"
Reply with the same "Saved to memory/… + mini summary" format. No buttons.
/savenow listCall sessions_list and return same-topic candidate sessions only. Do not write.
# YYYY-MM-DD
## HH:MM - Short title
- bullet
- bullet
For merges, the script appends new bullets in-place to the matched section and adds a trailing - (merged HH:MM) marker bullet. A second merge into the same section replaces the previous marker rather than stacking.
/savenow never writes — it previews and shows Apply/Cancel buttons.apply or auto.