@seed-hypermedia/cli 0.0.1

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 (4) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +1645 -0
  3. package/dist/index.js +119761 -0
  4. package/package.json +69 -0
package/README.md ADDED
@@ -0,0 +1,1645 @@
1
+ # Seed Hypermedia CLI
2
+
3
+ A command-line interface for interacting with the Seed Hypermedia network. Create, read, update, and delete documents;
4
+ manage accounts, comments, contacts, and capabilities; sign content with Ed25519 keys — all from your terminal.
5
+
6
+ **Package:** `@seed-hypermedia/cli` **Version:** 0.1.1 **License:** MIT **Requires:** Node.js >= 18.0.0
7
+
8
+ ## Table of Contents
9
+
10
+ - [Installation](#installation)
11
+ - [Quick Start](#quick-start)
12
+ - [Global Options](#global-options)
13
+ - [Configuration](#configuration)
14
+ - [Document Commands](#document-commands)
15
+ - [document get](#document-get)
16
+ - [document create](#document-create)
17
+ - [document update](#document-update)
18
+ - [document delete](#document-delete)
19
+ - [document fork](#document-fork)
20
+ - [document move](#document-move)
21
+ - [document redirect](#document-redirect)
22
+ - [document changes](#document-changes)
23
+ - [document stats](#document-stats)
24
+ - [document cid](#document-cid)
25
+ - [Account Commands](#account-commands)
26
+ - [account get](#account-get)
27
+ - [account list](#account-list)
28
+ - [account contacts](#account-contacts)
29
+ - [account capabilities](#account-capabilities)
30
+ - [Comment Commands](#comment-commands)
31
+ - [comment get](#comment-get)
32
+ - [comment list](#comment-list)
33
+ - [comment create](#comment-create)
34
+ - [comment delete](#comment-delete)
35
+ - [comment discussions](#comment-discussions)
36
+ - [Contact Commands](#contact-commands)
37
+ - [contact create](#contact-create)
38
+ - [contact delete](#contact-delete)
39
+ - [contact list](#contact-list)
40
+ - [Capability Commands](#capability-commands)
41
+ - [capability create](#capability-create)
42
+ - [Key Management Commands](#key-management-commands)
43
+ - [key generate](#key-generate)
44
+ - [key import](#key-import)
45
+ - [key list](#key-list)
46
+ - [key show](#key-show)
47
+ - [key default](#key-default)
48
+ - [key remove](#key-remove)
49
+ - [key rename](#key-rename)
50
+ - [key derive](#key-derive)
51
+ - [Search & Discovery Commands](#search--discovery-commands)
52
+ - [search](#search)
53
+ - [query](#query)
54
+ - [children](#children)
55
+ - [citations](#citations)
56
+ - [activity](#activity)
57
+ - [Hypermedia ID Format](#hypermedia-id-format)
58
+ - [Output Formats](#output-formats)
59
+ - [Markdown Conversion](#markdown-conversion)
60
+ - [Key Storage & Cryptography](#key-storage--cryptography)
61
+ - [Signing & Blob Architecture](#signing--blob-architecture)
62
+ - [Environment Variables](#environment-variables)
63
+ - [Error Handling](#error-handling)
64
+ - [Scripting Examples](#scripting-examples)
65
+ - [Development](#development)
66
+
67
+ ---
68
+
69
+ ## Installation
70
+
71
+ ```bash
72
+ # Install globally via npm
73
+ npm install -g @seed-hypermedia/cli
74
+
75
+ # Or run directly with npx (no install needed)
76
+ npx -y @seed-hypermedia/cli --help
77
+ ```
78
+
79
+ After installation, the CLI is available as both `seed-cli` and `seed-hypermedia`.
80
+
81
+ ### Development Mode
82
+
83
+ ```bash
84
+ cd frontend/apps/cli
85
+
86
+ # Run directly with bun
87
+ bun run src/index.ts [command]
88
+
89
+ # Or use the dev script
90
+ bun run dev [command]
91
+ ```
92
+
93
+ ---
94
+
95
+ ## Quick Start
96
+
97
+ ```bash
98
+ # 1. Generate a signing key
99
+ seed-cli key generate -n mykey --show-mnemonic
100
+
101
+ # 2. Create a document
102
+ seed-cli document create z6MkrbYs... --title "My First Document" --body "Hello, world!"
103
+
104
+ # 3. Read it back
105
+ seed-cli document get hm://z6MkrbYs.../my-first-document --md
106
+
107
+ # 4. Search for content
108
+ seed-cli search "hello world"
109
+
110
+ # 5. List all accounts
111
+ seed-cli account list
112
+ ```
113
+
114
+ ---
115
+
116
+ ## Global Options
117
+
118
+ These options apply to every command and must appear before the subcommand:
119
+
120
+ | Option | Description |
121
+ | -------------------- | ------------------------------------------------------------- |
122
+ | `-s, --server <url>` | Server URL (default: `https://hyper.media` or `$SEED_SERVER`) |
123
+ | `--json` | JSON output (default) |
124
+ | `--yaml` | YAML output |
125
+ | `--pretty` | Pretty-formatted colorized output |
126
+ | `-q, --quiet` | Minimal output (tab-separated values for scripting) |
127
+ | `--dev` | Use development keyring (`seed-daemon-dev`) |
128
+ | `-V, --version` | Display version number |
129
+ | `-h, --help` | Display help |
130
+
131
+ **Examples:**
132
+
133
+ ```bash
134
+ # Use a different server
135
+ seed-cli --server http://localhost:4000 account list
136
+
137
+ # Get YAML output
138
+ seed-cli account list --yaml
139
+
140
+ # Pretty-printed colorized JSON
141
+ seed-cli account get z6Mk... --pretty
142
+
143
+ # Quiet mode for piping
144
+ seed-cli account list -q | head -5
145
+
146
+ # Use development keyring
147
+ seed-cli --dev key list
148
+ ```
149
+
150
+ ---
151
+
152
+ ## Configuration
153
+
154
+ The CLI stores configuration in `~/.seed/config.json` (mode `0600`).
155
+
156
+ ### `config`
157
+
158
+ Manage CLI configuration.
159
+
160
+ | Option | Description |
161
+ | ---------------- | -------------------------- |
162
+ | `--server <url>` | Set default server URL |
163
+ | `--show` | Show current configuration |
164
+
165
+ ```bash
166
+ # Show current config
167
+ seed-cli config --show
168
+
169
+ # Set default server
170
+ seed-cli config --server https://my-server.example.com
171
+ ```
172
+
173
+ **Config fields:**
174
+
175
+ | Field | Description |
176
+ | ---------------- | ------------------------------------- |
177
+ | `server` | Default server URL |
178
+ | `defaultAccount` | Account ID of the default signing key |
179
+
180
+ ---
181
+
182
+ ## Document Commands
183
+
184
+ All document commands live under `seed-cli document <subcommand>`.
185
+
186
+ ### document get
187
+
188
+ Fetch a document, comment, or entity by Hypermedia ID.
189
+
190
+ ```
191
+ seed-cli document get <id> [options]
192
+ ```
193
+
194
+ | Option | Description |
195
+ | ---------------- | ------------------------------------------------------- |
196
+ | `-m, --metadata` | Fetch metadata only (faster, skips content) |
197
+ | `--md` | Output as Markdown |
198
+ | `--frontmatter` | Include YAML frontmatter (requires `--md`) |
199
+ | `-r, --resolve` | Resolve embeds, mentions, and queries (requires `--md`) |
200
+ | `-q, --quiet` | Print document title only (or ID if untitled) |
201
+
202
+ **Examples:**
203
+
204
+ ```bash
205
+ # Get full document as JSON
206
+ seed-cli document get hm://z6Mk.../my-doc
207
+
208
+ # Get as Markdown
209
+ seed-cli document get hm://z6Mk.../my-doc --md
210
+
211
+ # Get as Markdown with YAML frontmatter and resolved embeds
212
+ seed-cli document get hm://z6Mk.../my-doc --md --frontmatter --resolve
213
+
214
+ # Get metadata only (name, summary, etc.)
215
+ seed-cli document get hm://z6Mk.../my-doc -m
216
+
217
+ # Get a specific version
218
+ seed-cli document get "hm://z6Mk.../my-doc?v=bafy2bzace..."
219
+
220
+ # Get a nested child document
221
+ seed-cli document get hm://z6Mk.../projects/alpha
222
+
223
+ # Get just the title
224
+ seed-cli document get hm://z6Mk.../my-doc -q
225
+
226
+ # Also works for comments
227
+ seed-cli document get "hm://z6Mk...?c=bafy..."
228
+ ```
229
+
230
+ **Behavior:**
231
+
232
+ - When the resource is a `document`, outputs document content.
233
+ - When the resource is a `comment`, outputs comment content.
234
+ - With `--md`, converts block content to GitHub-flavored Markdown.
235
+ - With `--md --resolve`, fetches embedded documents and query results, inlining their content.
236
+ - With `--metadata`, fetches only the lightweight metadata payload.
237
+
238
+ ---
239
+
240
+ ### document create
241
+
242
+ Create a new document from Markdown or HMBlockNodes JSON.
243
+
244
+ ```
245
+ seed-cli document create <account> [options]
246
+ ```
247
+
248
+ | Option | Description |
249
+ | ---------------------- | ---------------------------------------- |
250
+ | `--title <title>` | **Required.** Document title |
251
+ | `-p, --path <path>` | Document path (default: slugified title) |
252
+ | `--body <text>` | Markdown content (inline) |
253
+ | `--body-file <file>` | Read Markdown content from a file |
254
+ | `--blocks <json>` | HMBlockNodes JSON (inline) |
255
+ | `--blocks-file <file>` | Read HMBlockNodes JSON from a file |
256
+ | `-k, --key <name>` | Signing key name or account ID |
257
+
258
+ **Constraints:**
259
+
260
+ - Exactly one content source is required: `--body`, `--body-file`, `--blocks`, or `--blocks-file`.
261
+ - `--body`/`--body-file` and `--blocks`/`--blocks-file` are mutually exclusive.
262
+ - The `--title` option is required.
263
+
264
+ **Examples:**
265
+
266
+ ```bash
267
+ # Create with inline Markdown
268
+ seed-cli document create z6Mk... --title "My Article" --body "# Introduction\n\nHello!"
269
+
270
+ # Create from a Markdown file
271
+ seed-cli document create z6Mk... --title "My Article" --body-file article.md
272
+
273
+ # Create from HMBlockNodes JSON
274
+ seed-cli document create z6Mk... --title "Structured Doc" --blocks-file blocks.json
275
+
276
+ # Create with custom path
277
+ seed-cli document create z6Mk... --title "My Article" --path "articles/2024/my-article" --body "content"
278
+
279
+ # Create with a specific signing key
280
+ seed-cli document create z6Mk... --title "My Article" --body "content" --key author
281
+ ```
282
+
283
+ **Under the hood:**
284
+
285
+ 1. Creates a genesis change blob (empty, signed).
286
+ 2. Creates a document change blob containing the title and content operations.
287
+ 3. Creates a version ref blob pointing to the change.
288
+ 4. Publishes all three blobs to the server.
289
+
290
+ **Output:**
291
+
292
+ ```
293
+ ✓ Document created: hm://z6Mk.../my-article
294
+ ℹ Title: My Article
295
+ ℹ Path: /my-article
296
+ ℹ Genesis CID: bafy2bzace...
297
+ ℹ Change CID: bafy2bzace...
298
+ ```
299
+
300
+ ---
301
+
302
+ ### document update
303
+
304
+ Update document metadata, append content, replace content, or delete blocks.
305
+
306
+ ```
307
+ seed-cli document update <id> [options]
308
+ ```
309
+
310
+ | Option | Description |
311
+ | ----------------------- | -------------------------------------------------------------------------------------- |
312
+ | `-f, --file <path>` | Input file (format detected by extension: .md, .json). Diffs against existing content. |
313
+ | `--title <title>` | Set document title |
314
+ | `--summary <summary>` | Set document summary |
315
+ | `--parent <blockId>` | Parent block ID for new content (default: root) |
316
+ | `--delete-blocks <ids>` | Comma-separated block IDs to delete |
317
+ | `-k, --key <name>` | Signing key name or account ID |
318
+
319
+ **Constraints:**
320
+
321
+ - At least one update option must be specified.
322
+
323
+ **Examples:**
324
+
325
+ ```bash
326
+ # Update the title
327
+ seed-cli document update hm://z6Mk.../my-doc --title "New Title"
328
+
329
+ # Update content from a Markdown file (smart diff — only changed blocks are submitted)
330
+ seed-cli document update hm://z6Mk.../my-doc -f updated.md
331
+
332
+ # Delete specific blocks
333
+ seed-cli document update hm://z6Mk.../my-doc --delete-blocks "blk-abc123,blk-def456"
334
+
335
+ # Combine metadata and content updates
336
+ seed-cli document update hm://z6Mk.../my-doc --title "Updated" --summary "A summary" -f content.md
337
+ ```
338
+
339
+ **Smart diff (`-f`):**
340
+
341
+ When `-f` is used, the CLI performs a per-block diff against the existing document:
342
+
343
+ 1. Each input block's ID is checked against the old document's block map.
344
+ 2. If the ID exists: content is compared, and only changed blocks get a `ReplaceBlock` op.
345
+ 3. If the ID doesn't exist: the block is treated as new (emits `ReplaceBlock`).
346
+ 4. Old blocks whose IDs are absent from the input are deleted (`DeleteBlocks`).
347
+ 5. Block ordering is updated via `MoveBlocks`.
348
+
349
+ This means editing a document exported with `document get` (which includes `<!-- id:... -->` comments in Markdown, or
350
+ block IDs in JSON) produces minimal updates. Plain Markdown without ID comments results in a full body replacement,
351
+ since none of the generated IDs will match the existing document.
352
+
353
+ ---
354
+
355
+ ### document delete
356
+
357
+ Delete a document by publishing a tombstone ref.
358
+
359
+ ```
360
+ seed-cli document delete <id> [options]
361
+ ```
362
+
363
+ | Option | Description |
364
+ | ------------------ | ------------------------------ |
365
+ | `-k, --key <name>` | Signing key name or account ID |
366
+
367
+ ```bash
368
+ seed-cli document delete hm://z6Mk.../my-doc --key author
369
+ ```
370
+
371
+ The document isn't physically removed — a tombstone ref is published, which tells clients the document has been
372
+ intentionally deleted.
373
+
374
+ ---
375
+
376
+ ### document fork
377
+
378
+ Fork a document to a new location (creates a copy).
379
+
380
+ ```
381
+ seed-cli document fork <sourceId> <destinationId> [options]
382
+ ```
383
+
384
+ | Option | Description |
385
+ | ------------------ | ------------------------------ |
386
+ | `-k, --key <name>` | Signing key name or account ID |
387
+
388
+ ```bash
389
+ seed-cli document fork hm://z6Mk.../original hm://z6Mk.../copy --key author
390
+ ```
391
+
392
+ **Behavior:**
393
+
394
+ - Creates a version ref at the destination pointing to the source's genesis and version.
395
+ - Does **not** create a redirect at the source (unlike `move`).
396
+ - The fork is an independent copy that shares the same genesis.
397
+
398
+ ---
399
+
400
+ ### document move
401
+
402
+ Move a document to a new location (fork + redirect at source).
403
+
404
+ ```
405
+ seed-cli document move <sourceId> <destinationId> [options]
406
+ ```
407
+
408
+ | Option | Description |
409
+ | ------------------ | ------------------------------ |
410
+ | `-k, --key <name>` | Signing key name or account ID |
411
+
412
+ ```bash
413
+ seed-cli document move hm://z6Mk.../old-path hm://z6Mk.../new-path --key author
414
+ ```
415
+
416
+ **Behavior:**
417
+
418
+ 1. Creates a version ref at the destination (same as `fork`).
419
+ 2. Creates a redirect ref at the source pointing to the destination.
420
+ 3. Clients following the source URL will be transparently redirected.
421
+
422
+ ---
423
+
424
+ ### document redirect
425
+
426
+ Create a redirect from one document to another.
427
+
428
+ ```
429
+ seed-cli document redirect <id> [options]
430
+ ```
431
+
432
+ | Option | Description |
433
+ | ------------------ | ------------------------------------------------- |
434
+ | `--to <targetId>` | **Required.** Target Hypermedia ID to redirect to |
435
+ | `--republish` | Republish target content at this location |
436
+ | `-k, --key <name>` | Signing key name or account ID |
437
+
438
+ ```bash
439
+ # Simple redirect
440
+ seed-cli document redirect hm://z6Mk.../old-page --to hm://z6Mk.../new-page
441
+
442
+ # Redirect with content republishing
443
+ seed-cli document redirect hm://z6Mk.../mirror --to hm://z6Mk.../original --republish
444
+ ```
445
+
446
+ ---
447
+
448
+ ### document changes
449
+
450
+ List document change history (version DAG).
451
+
452
+ ```
453
+ seed-cli document changes <targetId> [options]
454
+ ```
455
+
456
+ | Option | Description |
457
+ | ------------- | -------------------------------- |
458
+ | `-q, --quiet` | Output `CID<tab>author` per line |
459
+
460
+ ```bash
461
+ # Full change history
462
+ seed-cli document changes hm://z6Mk.../my-doc
463
+
464
+ # Compact: CID and author per line
465
+ seed-cli document changes hm://z6Mk.../my-doc -q
466
+ ```
467
+
468
+ **Output includes:**
469
+
470
+ - Change ID (CID)
471
+ - Author account ID
472
+ - Dependencies (parent changes in the DAG)
473
+ - Create time
474
+ - Latest version CID
475
+
476
+ ---
477
+
478
+ ### document stats
479
+
480
+ Get interaction statistics for a document.
481
+
482
+ ```
483
+ seed-cli document stats <id>
484
+ ```
485
+
486
+ ```bash
487
+ seed-cli document stats hm://z6Mk.../my-doc
488
+ ```
489
+
490
+ **Output includes:**
491
+
492
+ - Citation count (incoming links)
493
+ - Comment count
494
+ - Change count (edit history)
495
+ - Child document count
496
+ - Per-block citation and comment counts
497
+
498
+ ---
499
+
500
+ ### document cid
501
+
502
+ Fetch a raw IPFS block by its CID.
503
+
504
+ ```
505
+ seed-cli document cid <cid>
506
+ ```
507
+
508
+ ```bash
509
+ seed-cli document cid bafy2bzace...
510
+ ```
511
+
512
+ Returns the decoded IPLD block data as JSON.
513
+
514
+ ---
515
+
516
+ ## Account Commands
517
+
518
+ All account commands live under `seed-cli account <subcommand>`.
519
+
520
+ ### account get
521
+
522
+ Get account information.
523
+
524
+ ```
525
+ seed-cli account get <uid> [options]
526
+ ```
527
+
528
+ | Option | Description |
529
+ | ------------- | --------------------------------------- |
530
+ | `-q, --quiet` | Print name only (or UID if no name set) |
531
+
532
+ ```bash
533
+ # Full account info
534
+ seed-cli account get z6MkrbYs...
535
+
536
+ # Pretty print
537
+ seed-cli account get z6MkrbYs... --pretty
538
+
539
+ # Just the name
540
+ seed-cli account get z6MkrbYs... -q
541
+ ```
542
+
543
+ ---
544
+
545
+ ### account list
546
+
547
+ List all known accounts on the server.
548
+
549
+ ```
550
+ seed-cli account list [options]
551
+ ```
552
+
553
+ | Option | Description |
554
+ | ------------- | ----------------------------- |
555
+ | `-q, --quiet` | Output `ID<tab>name` per line |
556
+
557
+ ```bash
558
+ # Full JSON
559
+ seed-cli account list
560
+
561
+ # Compact for scripting
562
+ seed-cli account list -q
563
+ ```
564
+
565
+ ---
566
+
567
+ ### account contacts
568
+
569
+ List contacts for an account.
570
+
571
+ ```
572
+ seed-cli account contacts <uid> [options]
573
+ ```
574
+
575
+ | Option | Description |
576
+ | ------------- | ----------------- |
577
+ | `-q, --quiet` | Output names only |
578
+
579
+ ```bash
580
+ seed-cli account contacts z6Mk...
581
+ seed-cli account contacts z6Mk... -q
582
+ ```
583
+
584
+ ---
585
+
586
+ ### account capabilities
587
+
588
+ List access control capabilities for a resource.
589
+
590
+ ```
591
+ seed-cli account capabilities <id>
592
+ ```
593
+
594
+ ```bash
595
+ seed-cli account capabilities hm://z6Mk...
596
+ ```
597
+
598
+ **Output includes:** capability ID, issuer, delegate, role, path restrictions, recursive flag.
599
+
600
+ ---
601
+
602
+ ## Comment Commands
603
+
604
+ All comment commands live under `seed-cli comment <subcommand>`.
605
+
606
+ ### comment get
607
+
608
+ Get a single comment by ID.
609
+
610
+ ```
611
+ seed-cli comment get <id>
612
+ ```
613
+
614
+ ```bash
615
+ seed-cli comment get "hm://z6Mk...?c=bafy..."
616
+ ```
617
+
618
+ ---
619
+
620
+ ### comment list
621
+
622
+ List all comments on a document.
623
+
624
+ ```
625
+ seed-cli comment list <targetId> [options]
626
+ ```
627
+
628
+ | Option | Description |
629
+ | ------------- | ----------------------------------- |
630
+ | `-q, --quiet` | Output `ID<tab>authorName` per line |
631
+
632
+ ```bash
633
+ seed-cli comment list hm://z6Mk.../my-doc
634
+ seed-cli comment list hm://z6Mk.../my-doc -q
635
+ ```
636
+
637
+ ---
638
+
639
+ ### comment create
640
+
641
+ Create a comment on a document.
642
+
643
+ ```
644
+ seed-cli comment create <targetId> [options]
645
+ ```
646
+
647
+ | Option | Description |
648
+ | --------------------- | ---------------------------------------- |
649
+ | `--body <text>` | Comment text (inline) |
650
+ | `--file <path>` | Read comment text from file |
651
+ | `--reply <commentId>` | Reply to an existing comment (threading) |
652
+ | `-k, --key <name>` | Signing key name or account ID |
653
+
654
+ **Examples:**
655
+
656
+ ```bash
657
+ # Top-level comment
658
+ seed-cli comment create hm://z6Mk.../my-doc --body "Great article!" --key reviewer
659
+
660
+ # Reply to a comment (creates a thread)
661
+ seed-cli comment create hm://z6Mk.../my-doc --body "Thanks!" --reply bafy... --key author
662
+
663
+ # Comment on a specific block (block-level annotation)
664
+ seed-cli comment create "hm://z6Mk.../my-doc#blk-abc123" --body "This paragraph needs work" --key editor
665
+
666
+ # Read comment from file
667
+ seed-cli comment create hm://z6Mk.../my-doc --file review.txt --key reviewer
668
+ ```
669
+
670
+ **Inline mentions:**
671
+
672
+ Comment text supports inline mentions using the format `@[DisplayName](hm://accountId)`. Mentions are converted to
673
+ `Embed` annotations with a U+FFFC object replacement character.
674
+
675
+ ```bash
676
+ seed-cli comment create hm://z6Mk.../doc --body "cc @[Alice](hm://z6MkAlice...)" --key bob
677
+ ```
678
+
679
+ **Block-level comments:**
680
+
681
+ When the target ID includes a `#blockId` fragment, the comment body is automatically wrapped in an `Embed` block
682
+ referencing the specific block. This matches the behavior of the desktop and web apps for block-level annotations.
683
+
684
+ **Threading:**
685
+
686
+ When `--reply` is specified, the CLI fetches the parent comment to determine the thread root. If the parent is already a
687
+ reply, the thread root is inherited. Otherwise, the parent comment itself becomes the thread root.
688
+
689
+ ---
690
+
691
+ ### comment delete
692
+
693
+ Delete a comment by publishing a tombstone.
694
+
695
+ ```
696
+ seed-cli comment delete <commentId> [options]
697
+ ```
698
+
699
+ | Option | Description |
700
+ | ------------------ | ------------------------------ |
701
+ | `-k, --key <name>` | Signing key name or account ID |
702
+
703
+ ```bash
704
+ seed-cli comment delete bafy... --key reviewer
705
+ ```
706
+
707
+ ---
708
+
709
+ ### comment discussions
710
+
711
+ List threaded discussions on a document.
712
+
713
+ ```
714
+ seed-cli comment discussions <targetId> [options]
715
+ ```
716
+
717
+ | Option | Description |
718
+ | -------------------- | --------------------------- |
719
+ | `-c, --comment <id>` | Filter to a specific thread |
720
+
721
+ ```bash
722
+ # All discussions
723
+ seed-cli comment discussions hm://z6Mk.../my-doc
724
+
725
+ # A specific thread
726
+ seed-cli comment discussions hm://z6Mk.../my-doc --comment bafy...
727
+ ```
728
+
729
+ ---
730
+
731
+ ## Contact Commands
732
+
733
+ All contact commands live under `seed-cli contact <subcommand>`.
734
+
735
+ ### contact create
736
+
737
+ Create a contact (a named reference to another account).
738
+
739
+ ```
740
+ seed-cli contact create [options]
741
+ ```
742
+
743
+ | Option | Description |
744
+ | ----------------------- | ------------------------------------------ |
745
+ | `--subject <accountId>` | **Required.** Account ID being described |
746
+ | `--name <name>` | **Required.** Display name for the contact |
747
+ | `-k, --key <name>` | Signing key name or account ID |
748
+
749
+ ```bash
750
+ seed-cli contact create --subject z6MkAlice... --name "Alice" --key mykey
751
+ ```
752
+
753
+ **Output:** Contact record ID in `authority/tsid` format.
754
+
755
+ ---
756
+
757
+ ### contact delete
758
+
759
+ Delete a contact by publishing a tombstone.
760
+
761
+ ```
762
+ seed-cli contact delete <contactIdOrCid> [options]
763
+ ```
764
+
765
+ | Option | Description |
766
+ | ------------------ | ------------------------------ |
767
+ | `-k, --key <name>` | Signing key name or account ID |
768
+
769
+ Accepts either a record ID (`authority/tsid`) or a CID. If given a CID, the CLI fetches the blob to compute the record
770
+ ID.
771
+
772
+ ```bash
773
+ seed-cli contact delete z6Mk.../zQ3sh... --key mykey
774
+ seed-cli contact delete bafy... --key mykey
775
+ ```
776
+
777
+ ---
778
+
779
+ ### contact list
780
+
781
+ List contacts for an account.
782
+
783
+ ```
784
+ seed-cli contact list [accountId] [options]
785
+ ```
786
+
787
+ | Option | Description |
788
+ | ----------- | --------------------------------------------------- |
789
+ | `--account` | Only show contacts signed by the account |
790
+ | `--subject` | Only show contacts where the account is the subject |
791
+
792
+ By default, shows contacts in both directions (signed by and about the account).
793
+
794
+ ```bash
795
+ # Both directions
796
+ seed-cli contact list z6Mk...
797
+
798
+ # Only contacts this account created
799
+ seed-cli contact list z6Mk... --account
800
+
801
+ # Only contacts about this account
802
+ seed-cli contact list z6Mk... --subject
803
+ ```
804
+
805
+ ---
806
+
807
+ ## Capability Commands
808
+
809
+ All capability commands live under `seed-cli capability <subcommand>`.
810
+
811
+ ### capability create
812
+
813
+ Create a capability (delegate access to another account).
814
+
815
+ ```
816
+ seed-cli capability create [options]
817
+ ```
818
+
819
+ | Option | Description |
820
+ | ------------------------ | --------------------------------------- |
821
+ | `--delegate <accountId>` | **Required.** Account receiving access |
822
+ | `--role <role>` | **Required.** Role: `WRITER` or `AGENT` |
823
+ | `--path <path>` | Path scope for the capability |
824
+ | `--label <label>` | Human-readable label |
825
+ | `-k, --key <name>` | Signing key name or account ID |
826
+
827
+ ```bash
828
+ # Grant full write access
829
+ seed-cli capability create --delegate z6MkBob... --role WRITER --key alice
830
+
831
+ # Grant write access scoped to a path
832
+ seed-cli capability create --delegate z6MkBot... --role AGENT --path /blog --label "Blog bot" --key alice
833
+ ```
834
+
835
+ ---
836
+
837
+ ## Key Management Commands
838
+
839
+ All key commands live under `seed-cli key <subcommand>`. The `keys` alias also works.
840
+
841
+ Keys are stored in the **OS keyring** (macOS Keychain / Linux libsecret), shared with the Seed desktop app and Go
842
+ daemon. Keys created in the desktop app are immediately available to the CLI, and vice versa.
843
+
844
+ ### key generate
845
+
846
+ Generate a new signing key from a BIP-39 mnemonic.
847
+
848
+ ```
849
+ seed-cli key generate [options]
850
+ ```
851
+
852
+ | Option | Description |
853
+ | --------------------- | ------------------------------------------------- |
854
+ | `-n, --name <name>` | Key name (default: `main`) |
855
+ | `-w, --words <count>` | Mnemonic word count: `12` or `24` (default: `12`) |
856
+ | `--passphrase <pass>` | Optional BIP-39 passphrase |
857
+ | `--show-mnemonic` | Display the mnemonic (save it securely!) |
858
+
859
+ ```bash
860
+ # Generate with default settings
861
+ seed-cli key generate
862
+
863
+ # Generate a named key with 24 words and show the mnemonic
864
+ seed-cli key generate -n secure-key --words 24 --show-mnemonic
865
+
866
+ # Generate with passphrase
867
+ seed-cli key generate -n protected --passphrase "my secret"
868
+ ```
869
+
870
+ **Key name rules:** Only alphanumeric characters, hyphens, and underscores.
871
+
872
+ ---
873
+
874
+ ### key import
875
+
876
+ Import a key from an existing BIP-39 mnemonic.
877
+
878
+ ```
879
+ seed-cli key import <mnemonic> [options]
880
+ ```
881
+
882
+ | Option | Description |
883
+ | --------------------- | ------------------------------ |
884
+ | `-n, --name <name>` | Key name (default: `imported`) |
885
+ | `--passphrase <pass>` | Optional BIP-39 passphrase |
886
+
887
+ ```bash
888
+ seed-cli key import -n restored "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"
889
+
890
+ seed-cli key import -n restored --passphrase "secret" "word1 word2 ... word12"
891
+ ```
892
+
893
+ ---
894
+
895
+ ### key list
896
+
897
+ List all stored signing keys.
898
+
899
+ ```
900
+ seed-cli key list
901
+ ```
902
+
903
+ | Option | Description |
904
+ | ------------- | ------------------------------------ |
905
+ | `-q, --quiet` | Output `name<tab>accountId` per line |
906
+
907
+ ```bash
908
+ seed-cli key list
909
+ seed-cli key list -q
910
+ ```
911
+
912
+ ---
913
+
914
+ ### key show
915
+
916
+ Show information for a specific key, or the default key if none specified.
917
+
918
+ ```
919
+ seed-cli key show [nameOrId]
920
+ ```
921
+
922
+ Accepts a key name or account ID.
923
+
924
+ ```bash
925
+ # Show default key
926
+ seed-cli key show
927
+
928
+ # Show by name
929
+ seed-cli key show main
930
+
931
+ # Show by account ID
932
+ seed-cli key show z6Mk...
933
+ ```
934
+
935
+ ---
936
+
937
+ ### key default
938
+
939
+ Set or show the default signing key.
940
+
941
+ ```
942
+ seed-cli key default [nameOrId]
943
+ ```
944
+
945
+ ```bash
946
+ # Show current default
947
+ seed-cli key default
948
+
949
+ # Set a new default
950
+ seed-cli key default mykey
951
+ ```
952
+
953
+ **Default key resolution order:**
954
+
955
+ 1. Config `defaultAccount` (set by `key default`)
956
+ 2. Key named `main`
957
+ 3. First key in the keyring
958
+
959
+ ---
960
+
961
+ ### key remove
962
+
963
+ Remove a stored key.
964
+
965
+ ```
966
+ seed-cli key remove <nameOrId> [options]
967
+ ```
968
+
969
+ | Option | Description |
970
+ | ------------- | ----------------- |
971
+ | `-f, --force` | Skip confirmation |
972
+
973
+ ```bash
974
+ # Shows warning, requires --force
975
+ seed-cli key remove mykey
976
+
977
+ # Actually remove
978
+ seed-cli key remove mykey --force
979
+ ```
980
+
981
+ ---
982
+
983
+ ### key rename
984
+
985
+ Rename a stored key.
986
+
987
+ ```
988
+ seed-cli key rename <currentName> <newName>
989
+ ```
990
+
991
+ ```bash
992
+ seed-cli key rename old-name new-name
993
+ ```
994
+
995
+ ---
996
+
997
+ ### key derive
998
+
999
+ Derive an account ID from a mnemonic without storing the key.
1000
+
1001
+ ```
1002
+ seed-cli key derive <mnemonic> [options]
1003
+ ```
1004
+
1005
+ | Option | Description |
1006
+ | --------------------- | -------------------------- |
1007
+ | `--passphrase <pass>` | Optional BIP-39 passphrase |
1008
+
1009
+ ```bash
1010
+ seed-cli key derive "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"
1011
+ # Output: z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp
1012
+ ```
1013
+
1014
+ Useful for verifying a mnemonic maps to the expected account without writing it to the keyring.
1015
+
1016
+ ---
1017
+
1018
+ ## Search & Discovery Commands
1019
+
1020
+ These are top-level commands (not subcommands).
1021
+
1022
+ ### search
1023
+
1024
+ Search for documents across the network.
1025
+
1026
+ ```
1027
+ seed-cli search <query> [options]
1028
+ ```
1029
+
1030
+ | Option | Description |
1031
+ | --------------------- | ---------------------------------- |
1032
+ | `-a, --account <uid>` | Limit search to a specific account |
1033
+ | `-q, --quiet` | Output `ID<tab>title` per line |
1034
+
1035
+ ```bash
1036
+ seed-cli search "artificial intelligence"
1037
+ seed-cli search "meeting notes" --account z6Mk...
1038
+ seed-cli search "project" -q
1039
+ ```
1040
+
1041
+ ---
1042
+
1043
+ ### query
1044
+
1045
+ List documents in a space (account).
1046
+
1047
+ ```
1048
+ seed-cli query <space> [options]
1049
+ ```
1050
+
1051
+ | Option | Description |
1052
+ | ------------------- | ------------------------------------------------------------------- |
1053
+ | `-p, --path <path>` | Path prefix to filter |
1054
+ | `-m, --mode <mode>` | `Children` (default) or `AllDescendants` |
1055
+ | `-l, --limit <n>` | Maximum results |
1056
+ | `--sort <term>` | Sort by: `Path`, `Title`, `CreateTime`, `UpdateTime`, `DisplayTime` |
1057
+ | `--reverse` | Reverse sort order |
1058
+ | `-q, --quiet` | Output `ID<tab>name` per line |
1059
+
1060
+ ```bash
1061
+ # List direct children
1062
+ seed-cli query z6Mk...
1063
+
1064
+ # List all descendants recursively
1065
+ seed-cli query z6Mk... --mode AllDescendants
1066
+
1067
+ # List children under a specific path
1068
+ seed-cli query z6Mk... --path projects
1069
+
1070
+ # Sort by update time, newest first
1071
+ seed-cli query z6Mk... --sort UpdateTime --reverse
1072
+
1073
+ # Limit to 5 results
1074
+ seed-cli query z6Mk... --limit 5
1075
+ ```
1076
+
1077
+ ---
1078
+
1079
+ ### children
1080
+
1081
+ Shorthand for `query --mode Children`.
1082
+
1083
+ ```
1084
+ seed-cli children <space> [options]
1085
+ ```
1086
+
1087
+ | Option | Description |
1088
+ | ------------------- | ----------------------------- |
1089
+ | `-p, --path <path>` | Path prefix |
1090
+ | `-l, --limit <n>` | Limit results |
1091
+ | `-q, --quiet` | Output `ID<tab>name` per line |
1092
+
1093
+ ```bash
1094
+ # These are equivalent:
1095
+ seed-cli children z6Mk...
1096
+ seed-cli query z6Mk... --mode Children
1097
+ ```
1098
+
1099
+ ---
1100
+
1101
+ ### citations
1102
+
1103
+ List documents that cite (link to) a given resource.
1104
+
1105
+ ```
1106
+ seed-cli citations <id> [options]
1107
+ ```
1108
+
1109
+ | Option | Description |
1110
+ | ------------- | ---------------------- |
1111
+ | `-q, --quiet` | Output source IDs only |
1112
+
1113
+ ```bash
1114
+ seed-cli citations hm://z6Mk.../my-doc
1115
+ seed-cli citations hm://z6Mk.../my-doc -q
1116
+ ```
1117
+
1118
+ ---
1119
+
1120
+ ### activity
1121
+
1122
+ List recent activity events across the network.
1123
+
1124
+ ```
1125
+ seed-cli activity [options]
1126
+ ```
1127
+
1128
+ | Option | Description |
1129
+ | --------------------- | --------------------------------------- |
1130
+ | `-l, --limit <n>` | Page size |
1131
+ | `-t, --token <token>` | Pagination token (from previous output) |
1132
+ | `--authors <uids>` | Filter by author UIDs (comma-separated) |
1133
+ | `--resource <id>` | Filter by resource |
1134
+ | `-q, --quiet` | Output event count + next token only |
1135
+
1136
+ ```bash
1137
+ # Recent activity
1138
+ seed-cli activity
1139
+
1140
+ # Paginate
1141
+ seed-cli activity --limit 20
1142
+ seed-cli activity --limit 20 --token <nextPageToken>
1143
+
1144
+ # Filter by author
1145
+ seed-cli activity --authors z6Mk...
1146
+
1147
+ # Filter by resource
1148
+ seed-cli activity --resource hm://z6Mk.../my-doc
1149
+ ```
1150
+
1151
+ ---
1152
+
1153
+ ## Hypermedia ID Format
1154
+
1155
+ Seed uses Hypermedia IDs (HM IDs) as universal resource identifiers:
1156
+
1157
+ ```
1158
+ hm://<uid>[/<path>][?v=<version>][?c=<commentCID>][#<blockRef>]
1159
+ ```
1160
+
1161
+ | Component | Description | Example |
1162
+ | ------------ | ------------------------------------- | -------------------- |
1163
+ | `uid` | Account's Ed25519 public key ID | `z6MkrbYsRzKb1VA...` |
1164
+ | `path` | Forward-slash-separated path segments | `/projects/alpha` |
1165
+ | `version` | CID of a specific document version | `?v=bafy2bzace...` |
1166
+ | `commentCID` | CID of a comment | `?c=bafy2bzace...` |
1167
+ | `blockRef` | Specific block ID within the document | `#blk-abc123` |
1168
+
1169
+ **Examples:**
1170
+
1171
+ ```
1172
+ hm://z6MkrbYsRzKb1VABdvhsDSAk6JK8fAszKsyHhcaZigYeWCou
1173
+ hm://z6MkrbYs.../projects/alpha
1174
+ hm://z6MkrbYs.../my-doc?v=bafy2bzacedfvn...
1175
+ hm://z6MkrbYs.../my-doc#blk-abc123
1176
+ hm://z6MkrbYs...?c=bafy2bzace...
1177
+ ```
1178
+
1179
+ The CLI also accepts bare UIDs (without the `hm://` prefix) in most places.
1180
+
1181
+ ---
1182
+
1183
+ ## Output Formats
1184
+
1185
+ ### JSON (default)
1186
+
1187
+ Pretty-printed with 2-space indentation. BigInt values are serialized as strings.
1188
+
1189
+ ```bash
1190
+ seed-cli account list
1191
+ ```
1192
+
1193
+ ```json
1194
+ {
1195
+ "accounts": [
1196
+ {
1197
+ "id": {"id": "hm://z6Mk...", "uid": "z6Mk..."},
1198
+ "metadata": {"name": "Account Name"}
1199
+ }
1200
+ ]
1201
+ }
1202
+ ```
1203
+
1204
+ ### YAML
1205
+
1206
+ ```bash
1207
+ seed-cli account list --yaml
1208
+ ```
1209
+
1210
+ ```yaml
1211
+ accounts:
1212
+ - id:
1213
+ id: hm://z6Mk...
1214
+ uid: z6Mk...
1215
+ metadata:
1216
+ name: Account Name
1217
+ ```
1218
+
1219
+ ### Pretty
1220
+
1221
+ Colorized JSON output:
1222
+
1223
+ - **Green:** strings
1224
+ - **Yellow:** numbers
1225
+ - **Blue:** booleans
1226
+ - **Cyan:** object keys
1227
+ - **Dim gray:** null
1228
+
1229
+ ```bash
1230
+ seed-cli account list --pretty
1231
+ ```
1232
+
1233
+ ### Quiet
1234
+
1235
+ Tab-separated values, one record per line. Ideal for piping to `awk`, `cut`, `grep`, etc.
1236
+
1237
+ ```bash
1238
+ seed-cli account list -q
1239
+ # hm://z6Mk... Account Name
1240
+ # hm://z6Mk... Another Account
1241
+ ```
1242
+
1243
+ ---
1244
+
1245
+ ## Markdown Conversion
1246
+
1247
+ ### Document to Markdown (`--md`)
1248
+
1249
+ When using `document get --md`, the CLI converts the internal block tree to GitHub-flavored Markdown:
1250
+
1251
+ | Block type | Markdown rendering |
1252
+ | ------------- | ----------------------------------------------------------- |
1253
+ | Heading | `#`, `##`, `###`, etc. based on depth |
1254
+ | Paragraph | Plain text with inline formatting |
1255
+ | Code | Fenced code blocks with language tag |
1256
+ | Math | `$$...$$` LaTeX blocks |
1257
+ | Image | `![alt](gateway-url)` (IPFS CIDs converted to gateway URLs) |
1258
+ | Embed | Blockquote with link (or inlined content with `--resolve`) |
1259
+ | Query | Resolved to a list of linked documents (with `--resolve`) |
1260
+ | Button | `[text](url)` link |
1261
+ | Bold | `**text**` |
1262
+ | Italic | `*text*` |
1263
+ | Code (inline) | `` `text` `` |
1264
+ | Link | `[text](url)` |
1265
+
1266
+ **Frontmatter (`--frontmatter`):**
1267
+
1268
+ ```yaml
1269
+ ---
1270
+ title: Document Title
1271
+ summary: A brief description
1272
+ version: bafy2bzace...
1273
+ authors:
1274
+ - z6Mk...
1275
+ ---
1276
+ ```
1277
+
1278
+ **Resolve mode (`--resolve`):**
1279
+
1280
+ Fetches embedded documents and query results from the server and inlines their content directly in the Markdown output,
1281
+ up to a default recursion depth of 2.
1282
+
1283
+ ### Markdown to Blocks (input)
1284
+
1285
+ When creating or updating documents with `--body` or `--body-file`, the CLI parses Markdown into the internal block
1286
+ tree:
1287
+
1288
+ | Markdown element | Block type |
1289
+ | -------------------- | ----------------------------------------------- |
1290
+ | `# Heading` | `Heading` container with children |
1291
+ | Paragraphs | `Paragraph` blocks |
1292
+ | ` ```code``` ` | `Code` block with `language` attribute |
1293
+ | `**bold**` | `Bold` annotation |
1294
+ | `*italic*` | `Italic` annotation |
1295
+ | `` `code` `` | `Code` annotation |
1296
+ | `[text](url)` | `Link` annotation |
1297
+ | `- item` / `1. item` | Children with `childrenType: Unordered/Ordered` |
1298
+
1299
+ ---
1300
+
1301
+ ## Key Storage & Cryptography
1302
+
1303
+ ### Where Keys Live
1304
+
1305
+ Keys are stored in the **OS keyring**, not on disk:
1306
+
1307
+ | Platform | Backend | CLI tool used |
1308
+ | -------- | -------------------------------- | ------------- |
1309
+ | macOS | Keychain | `security` |
1310
+ | Linux | D-Bus Secret Service (libsecret) | `secret-tool` |
1311
+
1312
+ The keyring is shared with the Go daemon and desktop app. Keys registered in any Seed application are available in all
1313
+ others.
1314
+
1315
+ ### Keyring Service Names
1316
+
1317
+ | Environment | Service Name | Selected by |
1318
+ | ----------- | ------------------ | ------------------- |
1319
+ | Production | `seed-daemon-main` | Default |
1320
+ | Development | `seed-daemon-dev` | `--dev` global flag |
1321
+
1322
+ ### Key Encoding Format
1323
+
1324
+ Each key is stored as a 68-byte libp2p protobuf-encoded Ed25519 key pair, base64-encoded:
1325
+
1326
+ ```
1327
+ [08 01 12 40] [32-byte private seed] [32-byte public key]
1328
+ ─── header ─── ─── 64 bytes of key data ───
1329
+ ```
1330
+
1331
+ The 4-byte header is:
1332
+
1333
+ - `08 01` — protobuf field 1 (key type) = 1 (Ed25519)
1334
+ - `12 40` — protobuf field 2 (key data) length = 64 bytes
1335
+
1336
+ ### Account ID Derivation
1337
+
1338
+ ```
1339
+ 32-byte Ed25519 public key
1340
+ ↓ prepend multicodec prefix [0xed, 0x01]
1341
+ 34-byte multicodec key
1342
+ ↓ base58btc encode (multibase prefix 'z')
1343
+ Account ID string (starts with "z6Mk")
1344
+ ```
1345
+
1346
+ ### Key Derivation from Mnemonic
1347
+
1348
+ ```
1349
+ BIP-39 Mnemonic + optional Passphrase
1350
+ ↓ bip39.mnemonicToSeedSync()
1351
+ 64-byte seed
1352
+ ↓ SLIP-10 derivation at path m/44'/104109'/0'
1353
+ 32-byte Ed25519 private key
1354
+ ↓ ed25519.getPublicKey()
1355
+ 32-byte Ed25519 public key
1356
+ ↓ computeAccountId()
1357
+ Account ID (z6Mk...)
1358
+ ```
1359
+
1360
+ The derivation path `104109` is the Unicode codepoint sum for `h` + `m` (104 + 109).
1361
+
1362
+ ### Cross-Format Compatibility
1363
+
1364
+ The keyring JSON payload uses two formats:
1365
+
1366
+ 1. **Plain JSON** — written by the CLI
1367
+ 2. **`go-keyring-base64:<base64>`** — written by the Go daemon
1368
+
1369
+ The CLI reads both formats transparently. When writing, it uses the `go-keyring-base64:` format for compatibility with
1370
+ the daemon.
1371
+
1372
+ ---
1373
+
1374
+ ## Signing & Blob Architecture
1375
+
1376
+ All mutable data in Seed is stored as signed CBOR blobs. The CLI creates and signs these blobs client-side before
1377
+ publishing them to the server.
1378
+
1379
+ ### Signing Process
1380
+
1381
+ 1. Create the unsigned object with `sig: new Uint8Array(64)` (zeroed) and `ts: 0n`.
1382
+ 2. CBOR-encode the unsigned object.
1383
+ 3. Sign the CBOR bytes with Ed25519.
1384
+ 4. Fill in the actual `sig` and `ts` values.
1385
+ 5. CBOR-encode the final signed object.
1386
+ 6. Compute the SHA-256 CID of the encoded bytes.
1387
+ 7. Publish with the explicit CID.
1388
+
1389
+ ### Blob Types
1390
+
1391
+ **Genesis Change:** The root of every document's change DAG.
1392
+
1393
+ ```
1394
+ {type: "Change", signer, sig, ts: 0n}
1395
+ ```
1396
+
1397
+ **Document Change:** Mutations to document content and metadata.
1398
+
1399
+ ```
1400
+ {type: "Change", signer, sig, ts, genesis: CID, deps: CID[], depth, body: {ops, opCount}}
1401
+ ```
1402
+
1403
+ **Version Ref:** Points clients to the current document head.
1404
+
1405
+ ```
1406
+ {type: "Ref", signer, sig, ts, space, path, genesis, version, generation}
1407
+ ```
1408
+
1409
+ **Tombstone Ref:** Marks a document as deleted.
1410
+
1411
+ **Redirect Ref:** Points one document to another.
1412
+
1413
+ **Comment:** A signed comment blob attached to a document version.
1414
+
1415
+ **Contact:** A named reference from one account to another.
1416
+
1417
+ **Capability:** A delegation of write or agent access.
1418
+
1419
+ ### Document Operations
1420
+
1421
+ Changes contain arrays of operations:
1422
+
1423
+ | Operation | Description |
1424
+ | --------------- | ------------------------------ |
1425
+ | `SetAttributes` | Set metadata key-value pairs |
1426
+ | `ReplaceBlock` | Insert or replace a block |
1427
+ | `MoveBlocks` | Move blocks under a new parent |
1428
+ | `DeleteBlocks` | Remove blocks by ID |
1429
+
1430
+ ---
1431
+
1432
+ ## Environment Variables
1433
+
1434
+ | Variable | Description |
1435
+ | ------------- | ---------------------------------------------------- |
1436
+ | `SEED_SERVER` | Default server URL (overrides `https://hyper.media`) |
1437
+
1438
+ ---
1439
+
1440
+ ## Error Handling
1441
+
1442
+ **Exit codes:**
1443
+
1444
+ | Code | Meaning |
1445
+ | ---- | ----------------------------------------------------- |
1446
+ | `0` | Success |
1447
+ | `1` | Error (invalid input, network error, not found, etc.) |
1448
+
1449
+ **Error output:** Errors are printed to stderr with a red `✗` prefix.
1450
+
1451
+ **Common errors:**
1452
+
1453
+ | Error | Cause |
1454
+ | --------------------------------------------------------------- | -------------------------------------------------- |
1455
+ | `Invalid Hypermedia ID` | Malformed `hm://` URL |
1456
+ | `API error (500): ...` | Server-side error or resource not found |
1457
+ | `Key "name" not found` | No key with that name or account ID in the keyring |
1458
+ | `No signing keys found` | Must run `key generate` or `key import` first |
1459
+ | `Cannot combine --body/--body-file with --blocks/--blocks-file` | Mutually exclusive options |
1460
+
1461
+ ---
1462
+
1463
+ ## Scripting Examples
1464
+
1465
+ ### Export all documents as Markdown
1466
+
1467
+ ```bash
1468
+ #!/bin/bash
1469
+ ACCOUNT="z6MkrbYsRzKb1VABdvhsDSAk6JK8fAszKsyHhcaZigYeWCou"
1470
+
1471
+ seed-cli query "$ACCOUNT" --mode AllDescendants -q | while IFS=$'\t' read -r id name; do
1472
+ filename=$(echo "$name" | tr ' /' '_' | tr -cd '[:alnum:]_-')
1473
+ [ -z "$filename" ] && filename="unnamed_$(echo "$id" | md5sum | head -c 8)"
1474
+ seed-cli document get "$id" --md --resolve > "${filename}.md"
1475
+ echo "Exported: ${filename}.md"
1476
+ done
1477
+ ```
1478
+
1479
+ ### Create a document from a Markdown file
1480
+
1481
+ ```bash
1482
+ #!/bin/bash
1483
+ ACCOUNT="z6Mk..."
1484
+ TITLE="$(head -1 "$1" | sed 's/^# //')"
1485
+
1486
+ seed-cli document create "$ACCOUNT" \
1487
+ --title "$TITLE" \
1488
+ --body-file "$1" \
1489
+ --key main
1490
+ ```
1491
+
1492
+ ### Batch update documents from local files
1493
+
1494
+ ```bash
1495
+ #!/bin/bash
1496
+ for file in docs/*.md; do
1497
+ DOC_PATH=$(basename "$file" .md)
1498
+ ID="hm://z6Mk.../$DOC_PATH"
1499
+ echo "Updating $ID from $file"
1500
+ seed-cli document update "$ID" -f "$file" --key main
1501
+ done
1502
+ ```
1503
+
1504
+ ### Monitor activity feed
1505
+
1506
+ ```bash
1507
+ #!/bin/bash
1508
+ TOKEN=""
1509
+ while true; do
1510
+ if [ -n "$TOKEN" ]; then
1511
+ OUTPUT=$(seed-cli activity --limit 10 --token "$TOKEN")
1512
+ else
1513
+ OUTPUT=$(seed-cli activity --limit 10)
1514
+ fi
1515
+ echo "$OUTPUT" | jq '.events[] | "\(.eventType) by \(.author)"'
1516
+ TOKEN=$(echo "$OUTPUT" | jq -r '.nextPageToken // empty')
1517
+ sleep 60
1518
+ done
1519
+ ```
1520
+
1521
+ ### Find all documents by a specific author
1522
+
1523
+ ```bash
1524
+ #!/bin/bash
1525
+ AUTHOR="z6Mk..."
1526
+ seed-cli activity --authors "$AUTHOR" --limit 100 | jq -r '.events[].resource' | sort -u
1527
+ ```
1528
+
1529
+ ### Delegate write access
1530
+
1531
+ ```bash
1532
+ #!/bin/bash
1533
+ seed-cli capability create \
1534
+ --delegate z6MkBob... \
1535
+ --role WRITER \
1536
+ --key alice
1537
+
1538
+ seed-cli contact create \
1539
+ --subject z6MkBob... \
1540
+ --name "Bob" \
1541
+ --key alice
1542
+ ```
1543
+
1544
+ ### Backup all keys (show mnemonics)
1545
+
1546
+ ```bash
1547
+ #!/bin/bash
1548
+ seed-cli key list -q | while IFS=$'\t' read -r name id; do
1549
+ echo "=== Key: $name ($id) ==="
1550
+ seed-cli key show "$name"
1551
+ echo ""
1552
+ done
1553
+ ```
1554
+
1555
+ ---
1556
+
1557
+ ## Development
1558
+
1559
+ ```bash
1560
+ cd frontend/apps/cli
1561
+
1562
+ # Run directly
1563
+ bun run src/index.ts [command]
1564
+
1565
+ # Build for distribution
1566
+ npm run build
1567
+
1568
+ # Type check
1569
+ npm run typecheck
1570
+
1571
+ # Run fixture-based tests (starts a local daemon)
1572
+ bun test src/test/cli-fixture.test.ts
1573
+
1574
+ # Run daemon integration tests
1575
+ bun test src/test/cli.test.ts
1576
+
1577
+ # Run live server tests
1578
+ bun test src/test/cli-live.test.ts
1579
+ ```
1580
+
1581
+ ### Project Structure
1582
+
1583
+ ```
1584
+ frontend/apps/cli/
1585
+ ├── src/
1586
+ │ ├── index.ts # Entry point, global options, command registration
1587
+ │ ├── client.ts # HTTP API client
1588
+ │ ├── config.ts # ~/.seed/config.json management
1589
+ │ ├── output.ts # Output formatting (JSON, YAML, pretty, table)
1590
+ │ ├── markdown.ts # Document → Markdown conversion
1591
+ │ ├── commands/
1592
+ │ │ ├── document.ts # document get/create/update/delete/fork/move/redirect/changes/stats/cid
1593
+ │ │ ├── comment.ts # comment get/list/create/delete/discussions
1594
+ │ │ ├── capability.ts # capability create
1595
+ │ │ ├── contact.ts # contact create/delete/list
1596
+ │ │ ├── account.ts # account get/list/contacts/capabilities
1597
+ │ │ ├── key.ts # key generate/import/list/show/default/remove/rename/derive
1598
+ │ │ ├── search.ts # search
1599
+ │ │ └── query.ts # query/children/citations/activity
1600
+ │ ├── utils/
1601
+ │ │ ├── keyring.ts # Cross-platform OS keyring access
1602
+ │ │ ├── key-derivation.ts # BIP-39/SLIP-10 key derivation
1603
+ │ │ ├── signing.ts # CBOR blob signing (genesis, changes)
1604
+ │ │ ├── markdown.ts # Markdown → blocks parser
1605
+ │ │ ├── blocks-json.ts # HMBlockNodes JSON parser
1606
+ │ │ ├── block-diff.ts # Smart block diffing for document update
1607
+ │ │ ├── depth.ts # Change DAG depth resolution
1608
+ │ │ └── hm-id.ts # Hypermedia ID pack/unpack
1609
+ │ └── test/
1610
+ │ ├── cli-fixture.test.ts # Fixture-based integration tests
1611
+ │ ├── cli.test.ts # Daemon integration tests
1612
+ │ └── cli-live.test.ts # Live server tests
1613
+ ├── docs/
1614
+ │ ├── API.md # HTTP API reference
1615
+ │ ├── KEYS.md # Key management internals
1616
+ │ ├── SIGNING.md # Signing and blob creation reference
1617
+ │ └── TYPES.md # Type definitions reference
1618
+ └── package.json
1619
+ ```
1620
+
1621
+ ### Dependencies
1622
+
1623
+ | Package | Purpose |
1624
+ | ------------------------- | --------------------------- |
1625
+ | `commander` | CLI framework |
1626
+ | `multiformats` | CID/IPLD handling |
1627
+ | `@ipld/dag-cbor` | CBOR encoding |
1628
+ | `@noble/ed25519` | Ed25519 signatures |
1629
+ | `@noble/hashes` | Cryptographic hashing |
1630
+ | `@exodus/slip10` | SLIP-10 key derivation |
1631
+ | `bip39` | BIP-39 mnemonics |
1632
+ | `chalk` | Terminal colors |
1633
+ | `yaml` | YAML formatting |
1634
+ | `@seed-hypermedia/client` | SDK for document operations |
1635
+
1636
+ ---
1637
+
1638
+ ## Further Reading
1639
+
1640
+ - [API Reference](docs/API.md) — HTTP API endpoints
1641
+ - [Key Management](docs/KEYS.md) — Keyring internals and cross-platform storage
1642
+ - [Signing Reference](docs/SIGNING.md) — Blob signing and creation details
1643
+ - [Types Reference](docs/TYPES.md) — Complete type definitions
1644
+ - [Seed Hypermedia](https://seed.hyper.media) — Project website
1645
+ - [GitHub Repository](https://github.com/seed-hypermedia/seed) — Source code