Skip to content

Commit e8d5c60

Browse files
committed
feat: add remind batch dismiss, normalize, and range support
ctx remind dismiss now accepts multiple IDs and ranges (e.g., dismiss 3 5-7). Reuses parse.IDs from the pad package. New: ctx remind normalize reassigns IDs as 1..N. Removes dead One() dismiss function and InvalidID error constructor (parsing now handled by shared parse.IDs). Spec: specs/pad-stable-ids.md Signed-off-by: Jose Alekhinne <jose@ctx.ist>
1 parent 713a8de commit e8d5c60

22 files changed

Lines changed: 244 additions & 81 deletions

File tree

docs/cli/tools.md

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -594,15 +594,33 @@ ctx pad show 2 --out ./recovered.yaml
594594

595595
#### `ctx pad rm`
596596

597-
Remove an entry by number.
597+
Remove one or more entries by stable ID. Supports individual IDs and
598+
ranges.
598599

599600
```bash
600-
ctx pad rm <n>
601+
ctx pad rm <id> [id...]
601602
```
602603

603604
**Arguments**:
604605

605-
* `n`: 1-based entry number
606+
* `id`: One or more entry IDs (e.g., `3`, `1 4`, `3-5`)
607+
608+
**Examples**:
609+
610+
```bash
611+
ctx pad rm 2
612+
ctx pad rm 1 4
613+
ctx pad rm 3-5
614+
```
615+
616+
#### `ctx pad normalize`
617+
618+
Reassign entry IDs as a contiguous sequence 1..N, closing any gaps
619+
left by deletions.
620+
621+
```bash
622+
ctx pad normalize
623+
```
606624

607625
#### `ctx pad edit`
608626

@@ -806,16 +824,17 @@ ctx remind list
806824

807825
#### `ctx remind dismiss`
808826

809-
Remove a reminder by ID, or remove all reminders with `--all`.
827+
Remove one or more reminders by ID, or remove all with `--all`.
828+
Supports individual IDs and ranges.
810829

811830
```bash
812-
ctx remind dismiss <id>
831+
ctx remind dismiss <id> [id...]
813832
ctx remind dismiss --all
814833
```
815834

816835
**Arguments**:
817836

818-
- `id`: Reminder ID (shown in `list` output)
837+
- `id`: One or more reminder IDs (e.g., `3`, `3 5-7`)
819838

820839
**Flags**:
821840

@@ -829,9 +848,19 @@ ctx remind dismiss --all
829848

830849
```bash
831850
ctx remind dismiss 3
851+
ctx remind dismiss 3 5-7
832852
ctx remind dismiss --all
833853
```
834854

855+
#### `ctx remind normalize`
856+
857+
Reassign reminder IDs as a contiguous sequence 1..N, closing any gaps
858+
left by dismissals.
859+
860+
```bash
861+
ctx remind normalize
862+
```
863+
835864
---
836865

837866
### `ctx pause`

docs/home/common-workflows.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,9 @@ ctx remind "check CI after the deploy" --after 2026-02-25
6767
# List pending reminders
6868
ctx remind list
6969

70-
# Dismiss a reminder by ID
70+
# Dismiss reminders by ID (supports ranges)
7171
ctx remind dismiss 1
72+
ctx remind dismiss 3 5-7
7273
```
7374

7475
Reminders are relayed verbatim at session start by the `check-reminders` hook

docs/recipes/scratchpad-sync.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ chmod 600 ~/.ctx/.ctx.key # 3. secure it
4545
|-------------------------|-------------|--------------------------------------------------------|
4646
| `ctx init` | CLI command | Initialize context (*generates the key automatically*) |
4747
| `ctx pad add` | CLI command | Add a scratchpad entry |
48-
| `ctx pad rm` | CLI command | Remove a scratchpad entry |
48+
| `ctx pad rm` | CLI command | Remove entries by stable ID (supports ranges) |
4949
| `ctx pad edit` | CLI command | Edit a scratchpad entry |
5050
| `ctx pad resolve` | CLI command | Show both sides of a merge conflict |
5151
| `ctx pad merge` | CLI command | Merge entries from other scratchpad files |

docs/recipes/scratchpad-with-claude.md

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ Use the `/ctx-pad` skill to manage entries from inside your AI session.
3939
| `ctx pad edit` | CLI command | Replace, append to, or prepend to an entry |
4040
| `ctx pad add --file` | CLI command | Ingest a file as a blob entry |
4141
| `ctx pad show N --out` | CLI command | Extract a blob entry to a file |
42-
| `ctx pad rm` | CLI command | Remove an entry |
42+
| `ctx pad rm` | CLI command | Remove entries by stable ID (supports ranges) |
43+
| `ctx pad normalize` | CLI command | Reassign entry IDs as 1..N |
4344
| `ctx pad mv` | CLI command | Reorder entries |
4445
| `ctx pad --tag` | CLI command | Filter entries by tag |
4546
| `ctx pad tags` | CLI command | List all tags with counts |
@@ -120,7 +121,8 @@ Agent: [runs ctx pad mv 4 1]
120121
You: "remove entry 2, it's done"
121122
122123
Agent: [runs ctx pad rm 2]
123-
"Removed entry 2. 3 entries remaining."
124+
"Removed entry 2. 3 entries remaining.
125+
(IDs are stable — remaining entries keep their IDs.)"
124126
```
125127

126128
### Step 7: Store a File as a Blob
@@ -212,8 +214,9 @@ Agent: [runs ctx pad --tag later]
212214
3. review PR feedback #later #ci"
213215
```
214216

215-
Entry numbers stay the same when filtering — `ctx pad rm 3` still
216-
targets entry 3 regardless of active filters.
217+
Entry IDs are stable — they don't shift when other entries are deleted,
218+
so `ctx pad rm 3` always targets the same entry regardless of deletions
219+
or active filters. Use `ctx pad normalize` to reassign IDs as 1..N.
217220

218221
Exclude a tag with `~`:
219222

@@ -262,6 +265,8 @@ Once the skill is active, it translates intent into commands:
262265
| "show my scratchpad" / "what's on my pad" | `ctx pad` |
263266
| "show me entry 3" | `ctx pad show 3` |
264267
| "delete the third one" / "remove entry 3" | `ctx pad rm 3` |
268+
| "remove entries 3 through 5" | `ctx pad rm 3-5` |
269+
| "renumber my scratchpad" | `ctx pad normalize` |
265270
| "change entry 2 to ..." | `ctx pad edit 2 "new text"` |
266271
| "append ' +important' to entry 3" | `ctx pad edit 3 --append " +important"` |
267272
| "prepend 'URGENT:' to entry 1" | `ctx pad edit 1 --prepend "URGENT: "` |

docs/recipes/session-reminders.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ scratchpad entries don't announce themselves.
1919
```bash
2020
ctx remind "refactor the swagger definitions"
2121
ctx remind list
22-
ctx remind dismiss 1
22+
ctx remind dismiss 1 # or batch: ctx remind dismiss 1 3-5
2323
```
2424

2525
Reminders surface automatically at session start: VERBATIM, every
@@ -98,6 +98,10 @@ You: "dismiss reminder 1"
9898
Agent: [runs ctx remind dismiss 1]
9999
"Dismissed:
100100
- [1] refactor the swagger definitions"
101+
102+
# Batch dismiss also works:
103+
# "dismiss reminders 3, 5 through 7"
104+
# → ctx remind dismiss 3 5-7
101105
```
102106

103107
Or clear everything:
@@ -137,6 +141,7 @@ You: /ctx-remind dismiss reminder 3
137141
| "remind me next week to check staging" | `ctx remind "check staging" --after 2026-03-02` |
138142
| "what reminders do I have?" | `ctx remind list` |
139143
| "dismiss reminder 3" | `ctx remind dismiss 3` |
144+
| "dismiss reminders 3, 5 through 7" | `ctx remind dismiss 3 5-7` |
140145
| "clear all reminders" | `ctx remind dismiss --all` |
141146

142147
## Reminders vs Scratchpad vs Tasks

docs/reference/scratchpad.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,14 @@ Because the key is `.gitignore`d and the data is committed, you get:
4848
| `ctx pad` | List all entries (numbered 1-based) |
4949
| `ctx pad show N` | Output raw text of entry N (no prefix, pipe-friendly) |
5050
| `ctx pad add "text"` | Append a new entry |
51-
| `ctx pad rm N` | Remove entry at position N |
51+
| `ctx pad rm ID [ID...]` | Remove entries by stable ID (supports ranges: `3-5`) |
5252
| `ctx pad edit N "text"` | Replace entry N with new text |
5353
| `ctx pad edit N --append "text"` | Append text to the end of entry N |
5454
| `ctx pad edit N --prepend "text"` | Prepend text to the beginning of entry N |
5555
| `ctx pad edit N --tag tagname` | Add a tag to entry N |
5656
| `ctx pad add TEXT --file PATH` | Ingest a file as a blob entry (TEXT is the label) |
5757
| `ctx pad show N --out PATH` | Write decoded blob content to a file |
58+
| `ctx pad normalize` | Reassign entry IDs as 1..N |
5859
| `ctx pad mv N M` | Move entry from position N to position M |
5960
| `ctx pad resolve` | Show both sides of a merge conflict for resolution |
6061
| `ctx pad import FILE` | Bulk-import lines from a file (or stdin with `-`) |
@@ -92,7 +93,7 @@ ctx pad edit 1 --append "$(ctx pad show 2)"
9293
# Reorder
9394
ctx pad mv 2 1
9495

95-
# Clean up
96+
# Clean up (IDs are stable — they don't shift when entries are deleted)
9697
ctx pad rm 2
9798
```
9899

@@ -141,8 +142,9 @@ ctx pad edit 1 --append "checked" --tag done
141142
ctx pad edit 1 "check DNS propagation"
142143
```
143144

144-
Entry numbers are preserved when filtering — `ctx pad rm 3` targets the
145-
same entry regardless of active filters. Tags are case-sensitive and support
145+
Entry IDs are stable — they don't shift when other entries are deleted, so
146+
`ctx pad rm 3` always targets the same entry. Use `ctx pad normalize` to
147+
reassign IDs as 1..N if gaps bother you. Tags are case-sensitive and support
146148
letters, digits, hyphens, and underscores (`#high-priority`, `#v2`, `#my_tag`).
147149

148150
For blob entries, tags are extracted from the label only.

internal/assets/commands/commands.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -874,6 +874,8 @@ remind.dismiss:
874874
short: Dismiss one or all reminders
875875
remind.list:
876876
short: Show all pending reminders
877+
remind.normalize:
878+
short: Reassign reminder IDs as 1..N, closing gaps
877879
resume:
878880
long: |-
879881
Resume context hooks after a pause. Silent no-op if not paused.

internal/assets/commands/text/errors.yaml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -402,8 +402,6 @@ err.journal.source.reindex-file-write:
402402
short: 'failed to write %s: %w'
403403
err.journal.source.stats-glob:
404404
short: 'globbing stats files: %w'
405-
err.reminder.invalid-id:
406-
short: invalid ID %q
407405
err.reminder.parse-reminders:
408406
short: 'parse reminders: %w'
409407
err.reminder.read-reminders:

internal/assets/commands/text/write.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,8 @@ write.reminder-dismissed:
520520
short: ' - [%d] %s'
521521
write.reminder-dismissed-all:
522522
short: Dismissed %d reminders.
523+
write.reminder-normalized:
524+
short: Normalized %d reminders (IDs reassigned as 1..N).
523525
write.reminder-item:
524526
short: ' [%d] %s%s'
525527
write.reminder-none:

internal/cli/pad/cmd/normalize/doc.go

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,22 @@
44
// \ Copyright 2026-present Context contributors.
55
// SPDX-License-Identifier: Apache-2.0
66

7-
// Package normalize provides the pad normalize subcommand.
7+
// Package normalize implements the "ctx pad normalize"
8+
// subcommand for compacting stable entry IDs.
89
//
9-
// It reassigns entry IDs as 1..N in current file order,
10-
// closing all gaps left by deletions. This invalidates
11-
// previously-seen IDs.
10+
// Pad entries carry stable IDs that persist across
11+
// additions and deletions. Over time, gaps accumulate
12+
// (e.g., 1, 3, 7) as entries are removed. Normalize
13+
// closes those gaps by reassigning IDs sequentially
14+
// starting from 1, preserving the current file order.
15+
//
16+
// This is a deliberate user action, not automatic: it
17+
// invalidates any IDs the user may have noted or that
18+
// appear in prior session transcripts. The command
19+
// prints a confirmation with the count of entries
20+
// renumbered.
21+
//
22+
// The underlying ID reassignment logic lives in
23+
// [parse.Normalize]; this package handles the CLI
24+
// wiring, file I/O, and user output.
1225
package normalize

0 commit comments

Comments
 (0)