storymaps 1.3.1 → 1.3.3

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/README.md CHANGED
@@ -38,6 +38,16 @@ npm install
38
38
  npm link
39
39
  ```
40
40
 
41
+ ## Use with AI Coding Agents
42
+
43
+ A story map makes a good specification for an AI coding agent: the YAML lists every step of the journey and the cards under each one, slice by slice. **Build with AI** on storymaps.io writes the command for you:
44
+
45
+ ```bash
46
+ npx storymaps pull --force storymaps.io/abc123 && claude "The storymap file @storymap.yml describes a product plan in user story map format. Use it as a structured specification. Your task: build a functional prototype of the features listed in the 'MVP' slice."
47
+ ```
48
+
49
+ From there you steer the agent a slice or a feature at a time ("now build search from the V1 slice"). When a feature has been through QA, set its cards to `status: done` in `storymap.yml` and `storymaps push`, so the map shows the progress to everyone else. Pull again before the next round to pick up changes made in the browser.
50
+
41
51
  ## Quick Start
42
52
 
43
53
  ```bash
@@ -160,17 +170,47 @@ storymaps unlock # session unlock
160
170
  storymaps unlock --remove # permanently remove the lock
161
171
  ```
162
172
 
163
- ### `backup` / `backups` / `restore`
173
+ ### `backup`
174
+
175
+ Backs up the map on the server. Add a note to tell the backup apart later.
164
176
 
165
177
  ```bash
166
- storymaps backup # back up the map on the server
178
+ storymaps backup # back up the map in storymap.yml
167
179
  storymaps backup -m "Before the workshop" # with a note
168
- storymaps backups # list the backups, newest first
169
- storymaps restore 7ed8450a830a # restore one, after backing up the map as it is now
170
- storymaps restore 7ed8450a830a --force # restore without asking first
180
+ storymaps backup storymaps.io/abc123 # back up a map you haven't pulled
181
+ ```
182
+
183
+ The backup shows in the map's activity log, and in **Menu → Backups** in the app.
184
+
185
+ ### `backups`
186
+
187
+ Lists a map's backups, newest first, with the ID you need to restore one.
188
+
189
+ ```bash
190
+ > storymaps backups
191
+
192
+ 6e40f124ae7e 13:25 63 cards Before the workshop
193
+ 998e16f31f84 11:02 58 cards (no note)
171
194
  ```
172
195
 
173
- These are the same backups as **Menu → Backups** in the app, and the server keeps the newest 8 of each map. A restore changes the map on the server, not your local file, so run `storymaps pull` afterwards. Until you do, `storymaps push` stops with a conflict, so an old local file can't undo the restore. On a locked map, restore asks for the password, or uses the one saved by `storymaps unlock`. A self-hosted server needs updating before the CLI can make backups on it.
196
+ ### `restore`
197
+
198
+ Puts the map back the way it was in one of its backups. Give it the backup ID from `storymaps backups`.
199
+
200
+ ```bash
201
+ storymaps restore 6e40f124ae7e # asks before it restores
202
+ storymaps restore 6e40f124ae7e --force # restores without asking
203
+ ```
204
+
205
+ - **It backs up first.** Before restoring, the CLI backs up the map as it is now, so a restore can be undone with another restore.
206
+ - **It changes the server, not your file.** Run `storymaps pull` afterwards to get the restored map. Until you do, `storymaps push` stops with a conflict, so an old local file can't undo the restore by accident.
207
+ - **Locked maps** use the password saved by `storymaps unlock`, or ask for it.
208
+
209
+ ### About backups
210
+
211
+ - The CLI and the app share the same backups. A backup made in the app shows in `storymaps backups`, and one made with the CLI shows in the app.
212
+ - The server keeps the newest 8 backups of each map.
213
+ - A self-hosted server needs updating before the CLI can make backups on it. An older one turns the request away, and the CLI says so.
174
214
 
175
215
  ### `validate`
176
216
 
@@ -182,7 +222,7 @@ storymaps validate storymap.yml # check YAML structure
182
222
 
183
223
  A target can be a map ID, `domain/id`, or a full URL, including a map inside a project link (`storymaps.io/p/<project>/<map>`).
184
224
 
185
- `pull`, `push`, `open`, `lock`, `unlock`, `status` and `log` take `-f, --file <path>` to use a file other than `storymap.yml`.
225
+ `pull`, `push`, `open`, `lock`, `unlock`, `status`, `log`, `backup`, `backups` and `restore` take `-f, --file <path>` to use a file other than `storymap.yml`.
186
226
 
187
227
  ### `convert`
188
228
 
@@ -287,16 +327,6 @@ Cards support: `name`, `body`, `color`, `status` (done / in-progress / planned /
287
327
 
288
328
  Slices support: `name`, `stories`, `goal` (up to 200 characters), `targetDate` (`YYYY-MM-DD`), and `collapsed` with `closedReason` (complete / closed).
289
329
 
290
- ## Use with AI Coding Agents
291
-
292
- A story map makes a good specification for an AI coding agent: the YAML lists every step of the journey and the cards under each one, slice by slice. **Build with AI** on storymaps.io writes the command for you:
293
-
294
- ```bash
295
- npx storymaps pull --force storymaps.io/abc123 && claude "The storymap file @storymap.yml describes a product plan in user story map format. Use it as a structured specification. Your task: build a functional prototype of the features listed in the 'MVP' slice."
296
- ```
297
-
298
- From there you steer the agent a slice or a feature at a time ("now build search from the V1 slice"). When a feature has been through QA, set its cards to `status: done` in `storymap.yml` and `storymaps push`, so the map shows the progress to everyone else. Pull again before the next round to pick up changes made in the browser.
299
-
300
330
  ## Self-Hosting
301
331
 
302
332
  The CLI works with any storymaps.io instance:
package/bin/storymaps.js CHANGED
@@ -128,7 +128,7 @@ program
128
128
  program
129
129
  .command('restore')
130
130
  .description('Restore a map from one of its backups, after backing up the map as it is now')
131
- .argument('<backup>', 'backup ID, from storymaps backups')
131
+ .argument('<backup-id>', 'the ID of a backup, from storymaps backups')
132
132
  .argument('[target]', 'map ID, domain/ID, or full URL')
133
133
  .option('-f, --file <path>', 'local file path', 'storymap.yml')
134
134
  .option('--force', 'restore without asking first')
@@ -33,7 +33,7 @@ export async function backupsCommand(target, opts) {
33
33
  const imported = b.imported ? chalk.dim(' imported') : '';
34
34
  console.log(`${chalk.cyan(b.id)} ${chalk.dim(formatTime(b.timestamp))} ${cards(b.cardCount).padEnd(9)} ${note}${imported}`);
35
35
  }
36
- console.log(chalk.dim(`\nRestore one with ${chalk.cyan('storymaps restore <backup>')}`));
36
+ console.log(chalk.dim(`\nRestore one with ${chalk.cyan('storymaps restore <backup ID>')}`));
37
37
  }
38
38
 
39
39
  // The lock password for a locked map, checked with the server before anything changes.
@@ -83,7 +83,7 @@ export async function restoreCommand(backupId, target, opts) {
83
83
 
84
84
  // Like the app: a backup of the map as it is now, so the restore can be undone
85
85
  const safety = await createBackup(baseUrl, id, 'Auto: before restore');
86
- await putMap(baseUrl, id, backup.data, { contentType: 'application/json', lockPasswordHash });
86
+ await putMap(baseUrl, id, backup.data, { contentType: 'application/json', lockPasswordHash, restoredBackup: backup.id });
87
87
 
88
88
  console.log(chalk.green(`Restored map ${id} from backup ${backup.id}`));
89
89
  console.log(chalk.dim(`The map before the restore is backup ${safety.id}.`));
package/lib/util/api.js CHANGED
@@ -47,10 +47,12 @@ export async function getMap(baseUrl, id, format = 'yaml') {
47
47
  return { data, etag };
48
48
  }
49
49
 
50
- export async function putMap(baseUrl, id, body, { etag, contentType = 'text/yaml', lockPasswordHash } = {}) {
50
+ export async function putMap(baseUrl, id, body, { etag, contentType = 'text/yaml', lockPasswordHash, restoredBackup } = {}) {
51
51
  const headers = { 'Content-Type': contentType };
52
52
  if (etag) headers['If-Match'] = etag;
53
53
  if (lockPasswordHash) headers['X-Lock-Password'] = lockPasswordHash;
54
+ // Tells the server this push is a restore, so the activity log says so
55
+ if (restoredBackup) headers['X-Restored-Backup'] = restoredBackup;
54
56
  const res = await request(`${baseUrl}/api/maps/${id}`, {
55
57
  method: 'PUT',
56
58
  headers,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "storymaps",
3
- "version": "1.3.1",
3
+ "version": "1.3.3",
4
4
  "description": "CLI tool for storymaps.io - import, export, validate, and manage user story maps from the terminal",
5
5
  "type": "module",
6
6
  "bin": {