@gmickel/gno 1.37.1 → 1.39.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.
Files changed (47) hide show
  1. package/assets/skill/README.md +2 -0
  2. package/browser-extension/artifacts/{gno-browser-clipper-v1.37.1.zip → gno-browser-clipper-v1.39.0.zip} +0 -0
  3. package/browser-extension/artifacts/gno-browser-clipper-v1.39.0.zip.sha256 +1 -0
  4. package/browser-extension/dist/manifest.json +1 -1
  5. package/package.json +1 -1
  6. package/spec/cli.md +243 -26
  7. package/spec/output-schemas/agents-mutation.schema.json +108 -0
  8. package/spec/output-schemas/agents-verify.schema.json +89 -0
  9. package/src/cli/commands/agents/block.ts +164 -0
  10. package/src/cli/commands/agents/commands.ts +413 -0
  11. package/src/cli/commands/agents/engine.ts +417 -0
  12. package/src/cli/commands/agents/harnesses.ts +298 -0
  13. package/src/cli/commands/agents/index.ts +35 -0
  14. package/src/cli/commands/cleanup.ts +8 -2
  15. package/src/cli/commands/collection/clear-embeddings.ts +6 -1
  16. package/src/cli/commands/completion/scripts.ts +5 -0
  17. package/src/cli/commands/doctor-activation.ts +5 -1
  18. package/src/cli/commands/doctor.ts +72 -2
  19. package/src/cli/commands/embed.ts +227 -194
  20. package/src/cli/commands/index-cmd.ts +74 -50
  21. package/src/cli/commands/init.ts +5 -1
  22. package/src/cli/commands/profile-apply.ts +5 -1
  23. package/src/cli/commands/setup-activation.ts +2 -1
  24. package/src/cli/commands/setup.ts +2 -1
  25. package/src/cli/commands/shared.ts +5 -1
  26. package/src/cli/commands/status.ts +5 -1
  27. package/src/cli/commands/tags.ts +18 -3
  28. package/src/cli/commands/update.ts +34 -27
  29. package/src/cli/commands/vec.ts +13 -4
  30. package/src/cli/errors.ts +3 -2
  31. package/src/cli/program.ts +449 -194
  32. package/src/config/defaults.ts +2 -0
  33. package/src/config/index.ts +3 -0
  34. package/src/config/types.ts +32 -1
  35. package/src/core/file-lock.ts +16 -4
  36. package/src/core/write-lease.ts +354 -0
  37. package/src/embed/backlog.ts +9 -1
  38. package/src/embed/retry.ts +116 -3
  39. package/src/sdk/client.ts +3 -1
  40. package/src/sdk/embed.ts +8 -3
  41. package/src/sdk/types.ts +2 -0
  42. package/src/serve/embed-scheduler.ts +8 -0
  43. package/src/serve/resident-runtime.ts +5 -1
  44. package/src/store/sqlite/adapter.ts +28 -4
  45. package/src/store/sqlite/scoped-index.ts +5 -1
  46. package/src/store/vector/sqlite-vec.ts +2 -1
  47. package/browser-extension/artifacts/gno-browser-clipper-v1.37.1.zip.sha256 +0 -1
@@ -42,6 +42,8 @@ gno skill install --target hermes # Hermes
42
42
  gno skill install --target all # All supported agents
43
43
  ```
44
44
 
45
+ As of their current releases, `--target claude` also serves Grok Build and Cursor via automatic `.claude/skills` discovery, `--target codex` is also read by Cursor, and other skill-capable clients can copy the files listed by `gno skill paths`.
46
+
45
47
  Scope is configurable:
46
48
 
47
49
  ```bash
@@ -0,0 +1 @@
1
+ b3b2f2609cfe5c821eb9d22d76832b6ad329afa7496c0792e0dd4f5bd0f74fbc gno-browser-clipper-v1.39.0.zip
@@ -21,5 +21,5 @@
21
21
  "content_security_policy": {
22
22
  "extension_pages": "script-src 'self'; object-src 'none'; connect-src http://127.0.0.1:*"
23
23
  },
24
- "version": "1.37.1"
24
+ "version": "1.39.0"
25
25
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gmickel/gno",
3
- "version": "1.37.1",
3
+ "version": "1.39.0",
4
4
  "description": "Local semantic search for your documents. Index Markdown, PDF, and Office files with hybrid BM25 + vector search.",
5
5
  "keywords": [
6
6
  "embeddings",
package/spec/cli.md CHANGED
@@ -15,6 +15,7 @@ This document specifies the command-line interface for GNO, a local knowledge in
15
15
  | 1 | VALIDATION | Validation or usage error (bad args, missing required params) |
16
16
  | 2 | RUNTIME | Runtime failure (IO, DB, conversion, model, network) |
17
17
  | 3 | NOT_RUNNING | `--status`/`--stop` found no live matching process |
18
+ | 4 | BUSY | Write-lease contention on `index` / `update` / `embed` |
18
19
 
19
20
  ### Global Flags
20
21
 
@@ -112,6 +113,10 @@ equivalent files fail closed as ambiguous.
112
113
  | skill uninstall | yes | no | no | no | no | terminal |
113
114
  | skill show | no | no | no | no | no | terminal |
114
115
  | skill paths | yes | no | no | no | no | terminal |
116
+ | agents install | yes | no | no | no | no | terminal |
117
+ | agents update | yes | no | no | no | no | terminal |
118
+ | agents verify | yes | no | no | no | no | terminal |
119
+ | agents uninstall | yes | no | no | no | no | terminal |
115
120
  | tags list | yes | no | no | yes | no | terminal |
116
121
  | tags add | yes | no | no | no | no | terminal |
117
122
  | tags rm | yes | no | no | no | no | terminal |
@@ -957,7 +962,7 @@ Sync files from disk into the index (ingestion without embedding).
957
962
  **Synopsis:**
958
963
 
959
964
  ```bash
960
- gno update [--git-pull] [--json]
965
+ gno update [--git-pull] [--json] [--lock-wait <duration>] [--no-wait]
961
966
  ```
962
967
 
963
968
  **Options:**
@@ -965,6 +970,10 @@ gno update [--git-pull] [--json]
965
970
  |--------|------|-------------|
966
971
  | `--git-pull` | boolean | Run `git pull` in git repositories before scanning |
967
972
  | `--json` | boolean | Emit the complete deterministic sync result on stdout |
973
+ | `--lock-wait <duration>` | duration | How long to wait for the index write lease (default: `120s`). Accepts `120`, `120s`, or `2m`. |
974
+ | `--no-wait` | boolean | Do not wait; fail immediately if another writer holds the lease |
975
+
976
+ **Concurrency:** One writer at a time on the shared index database. `update` waits up to `--lock-wait` for the lease (the same `.mcp-write.lock` MCP write tools use); `index`, `embed`, `cleanup`, `vec sync`, `vec rebuild`, `collection clear-embeddings`, `tags add`, and `tags rm` follow the same contract; `capture` takes the same lock internally, and single-row writes such as `collection policy set` are absorbed by `busy_timeout`. `--no-wait` opts out. Reads (`search`, `query`, `get`) never take the lease. External serialising wrappers are no longer required for CLI-vs-CLI and CLI-vs-MCP overlap. Residual window: a resident (`gno serve`/`gno daemon`) watch or embed flush writes without the lease; those short transactions are absorbed by the raised `busy_timeout` and the SQLITE_BUSY retry, and a deferred chunk is reported as contention, never as an embedding failure.
968
977
 
969
978
  **Behavior:**
970
979
 
@@ -986,6 +995,7 @@ record failure was reported. Human progress and diagnostics remain on stderr.
986
995
 
987
996
  - 0: Success (conversion warnings do not affect exit code)
988
997
  - 2: DB failure or critical IO error
998
+ - 4: Write lease busy (contention after `--lock-wait`, or immediately with `--no-wait`)
989
999
 
990
1000
  ---
991
1001
 
@@ -996,7 +1006,7 @@ Build or update the index end-to-end (update + embed).
996
1006
  **Synopsis:**
997
1007
 
998
1008
  ```bash
999
- gno index [collection] [--no-embed] [--models-pull] [--git-pull] [--json] [--yes]
1009
+ gno index [collection] [--no-embed] [--models-pull] [--git-pull] [--json] [--yes] [--lock-wait <duration>] [--no-wait]
1000
1010
  ```
1001
1011
 
1002
1012
  **Options:**
@@ -1008,24 +1018,29 @@ gno index [collection] [--no-embed] [--models-pull] [--git-pull] [--json] [--yes
1008
1018
  | `--git-pull` | boolean | Run `git pull` in git repositories |
1009
1019
  | `--json` | boolean | Emit the complete deterministic sync and embedding result on stdout |
1010
1020
  | `--yes` | boolean | Accept defaults, no prompts |
1021
+ | `--lock-wait <duration>` | duration | How long to wait for the index write lease (default: `120s`). Accepts `120`, `120s`, or `2m`. |
1022
+ | `--no-wait` | boolean | Do not wait; fail immediately if another writer holds the lease |
1011
1023
 
1012
1024
  **Behavior:**
1013
1025
 
1014
1026
  - Runs `update` then `embed` by default
1015
1027
  - With `--no-embed`, runs `update` only
1028
+ - Waits by default for the shared write lease; `--no-wait` fails immediately with exit 4
1016
1029
 
1017
1030
  **JSON output:** Emits `{ syncResult, embedSkipped, embedResult? }`.
1018
1031
  `syncResult.collections[].files[].recordImport`, when present, conforms to
1019
1032
  [`record-import@1.0`](./output-schemas/record-import.schema.json) with the same
1020
1033
  deterministic ordering, bounds, truncation disclosure, and partial-snapshot
1021
1034
  warnings as `gno update --json`. Human progress and diagnostics remain on
1022
- stderr.
1035
+ stderr. On lease timeout, stdout is one object `{ success: false, error, contention }`
1036
+ and the process exits 4.
1023
1037
 
1024
1038
  **Exit Codes:**
1025
1039
 
1026
1040
  - 0: Success
1027
- - 1: Invalid collection name
1041
+ - 1: Invalid collection name or invalid `--lock-wait`
1028
1042
  - 2: DB or model failure
1043
+ - 4: Write lease busy (contention, not corruption)
1029
1044
 
1030
1045
  **Examples:**
1031
1046
 
@@ -1060,25 +1075,30 @@ memory pressure prevents creating the full pool.
1060
1075
  **Synopsis:**
1061
1076
 
1062
1077
  ```bash
1063
- gno embed [--force] [--model <uri>] [--batch-size <n>] [--dry-run] [--yes] [--json]
1078
+ gno embed [--force] [--model <uri>] [--batch-size <n>] [--dry-run] [--yes] [--json] [--lock-wait <duration>] [--no-wait]
1064
1079
  ```
1065
1080
 
1066
1081
  **Options:**
1067
1082
 
1068
- | Option | Type | Default | Description |
1069
- | -------------- | ------- | ------- | --------------------------------------------- |
1070
- | `--force` | boolean | false | Re-embed all chunks (ignore existing vectors) |
1071
- | `--model` | string | config | Override embedding model URI |
1072
- | `--batch-size` | integer | 32 | Chunks per batch |
1073
- | `--dry-run` | boolean | false | Show what would be embedded without doing it |
1074
- | `--yes`, `-y` | boolean | false | Skip confirmation prompts |
1075
- | `--json` | boolean | false | Output result as JSON |
1083
+ | Option | Type | Default | Description |
1084
+ | ------------------------ | -------- | ------- | --------------------------------------------------------------------------- |
1085
+ | `--force` | boolean | false | Re-embed all chunks (ignore existing vectors) |
1086
+ | `--model` | string | config | Override embedding model URI |
1087
+ | `--batch-size` | integer | 32 | Chunks per batch |
1088
+ | `--dry-run` | boolean | false | Show what would be embedded without doing it |
1089
+ | `--yes`, `-y` | boolean | false | Skip confirmation prompts |
1090
+ | `--json` | boolean | false | Output result as JSON |
1091
+ | `--lock-wait <duration>` | duration | `120s` | How long to wait for the index write lease. Accepts `120`, `120s`, or `2m`. |
1092
+ | `--no-wait` | boolean | false | Do not wait; fail immediately if another writer holds the lease |
1093
+
1094
+ Waits by default for the same write lease as `index` / `update` / MCP writers. `--no-wait` opts out.
1076
1095
 
1077
1096
  **Exit Codes:**
1078
1097
 
1079
1098
  - 0: Success
1080
- - 1: User cancelled
1099
+ - 1: User cancelled or invalid `--lock-wait`
1081
1100
  - 2: Model not available or embedding failure
1101
+ - 4: Write lease busy (contention, not corruption)
1082
1102
 
1083
1103
  **JSON Output:**
1084
1104
 
@@ -2566,6 +2586,8 @@ gno skill install [--scope <project|user>] [--target <claude|codex|opencode|open
2566
2586
  3. Atomically installs skill directory (temp + rename)
2567
2587
  4. Copies SKILL.md, reference files, and nested recipe files
2568
2588
 
2589
+ **Compatibility:** As of their current releases, Grok Build (the xAI grok CLI) automatically reads Claude skill directories (`.claude/skills/` and `~/.claude/skills/`) with no extra configuration, and Cursor loads agent skills from `.claude/skills/` and `.codex/skills/` (project and user scope) in addition to its own `.cursor/skills/`. `--target claude` therefore covers Grok Build and Cursor; `--target codex` is also read by Cursor. Other skill-capable clients can copy the installed files; `gno skill paths` prints their locations. Dedicated `grok` and `cursor` installer targets are not shipped: they would duplicate the claude/codex paths those tools already read. Revisit only if users keep `~/.grok/skills` or `~/.cursor/skills` separate and ask for first-class targets.
2590
+
2569
2591
  **Output (JSON):**
2570
2592
 
2571
2593
  ```json
@@ -2607,7 +2629,7 @@ Remove GNO agent skill.
2607
2629
  gno skill uninstall [--scope <project|user>] [--target <claude|codex|opencode|openclaw|hermes|all>] [--json]
2608
2630
  ```
2609
2631
 
2610
- **Options:** Same as `skill install` (except `--force`)
2632
+ **Options:** Same as `skill install` (except `--force`).
2611
2633
 
2612
2634
  **Safety Checks:**
2613
2635
 
@@ -2712,6 +2734,195 @@ gno skill paths [--scope <project|user>] [--target <claude|codex|opencode|opencl
2712
2734
 
2713
2735
  ---
2714
2736
 
2737
+ ### gno agents install
2738
+
2739
+ Install the compact, versioned GNO protocol block into the global (user-scope)
2740
+ instruction files of every detected harness. The block is bounded by stable
2741
+ markers (`<!-- gno:agents:begin -->` / `<!-- gno:agents:end -->`); install and
2742
+ update touch ONLY the owned block — content outside the markers stays
2743
+ byte-identical. The block content is static (identical on every machine), so
2744
+ a block is current exactly when its stamp version and hash match the installed
2745
+ release.
2746
+
2747
+ **Synopsis:**
2748
+
2749
+ ```bash
2750
+ gno agents install [--target <claude|codex|cursor|opencode|grok|hermes|openclaw|all>] [--extra-dir <path>]... [--dry-run] [--json]
2751
+ ```
2752
+
2753
+ **Options:**
2754
+
2755
+ | Option | Type | Default | Description |
2756
+ | ------------- | ------- | ------- | ----------------------------------------------------------------------------------------------- |
2757
+ | `--target` | string | all | Harness to install for; `all` = every harness detected on this machine |
2758
+ | `--extra-dir` | string | — | Additional instruction dir (repeatable, for nonstandard/multi-instance layouts). Never guessed. |
2759
+ | `--dry-run` | boolean | false | Print per-target unified diffs; write nothing |
2760
+
2761
+ **Harness matrix (standard documented locations):**
2762
+
2763
+ | Target | Instruction file | Detection root | Notes |
2764
+ | ---------- | ------------------------------------------------------- | ----------------------- | ----------------------------------------------------------------------------------- |
2765
+ | `claude` | `$CLAUDE_CONFIG_DIR/CLAUDE.md` or `~/.claude/CLAUDE.md` | `~/.claude` | Honors `CLAUDE_CONFIG_DIR` |
2766
+ | `codex` | `$CODEX_HOME/AGENTS.md` or `~/.codex/AGENTS.md` | `~/.codex` | Honors `CODEX_HOME` |
2767
+ | `cursor` | `~/AGENTS.md` | `~/.cursor` | Cursor Agent walks cwd → home for AGENTS.md |
2768
+ | `opencode` | `~/.config/opencode/AGENTS.md` | `~/.config/opencode` | |
2769
+ | `grok` | — (import chain) | `~/.grok` | Reads the Claude global file; reported `covered via claude`, never double-installed |
2770
+ | `hermes` | `~/.hermes/SOUL.md` | `~/.hermes` | |
2771
+ | `openclaw` | `~/.openclaw/workspace/AGENTS.md` | `~/.openclaw/workspace` | |
2772
+
2773
+ **Behavior:**
2774
+
2775
+ 1. Detects harnesses (config dir exists); undetected targets are reported
2776
+ `not-detected` and skipped — the installer never fabricates harness dirs
2777
+ (creating the instruction FILE inside a detected dir is fine). An explicit
2778
+ detected covered target (e.g. `--target grok`) also resolves its covering
2779
+ target so the file it actually reads converges; when the explicit target is
2780
+ absent, the covering chain never activates.
2781
+ 2. Backup-first, atomic: an existing file is copied to
2782
+ `<file>.gno-agents.bak.<timestamp>` (same permission mode as the source),
2783
+ then the new content is written to a sibling temp file and renamed over the
2784
+ destination, so a failed write leaves the live file unchanged. A fresh
2785
+ install appends the block after one blank line (a file without a final
2786
+ newline gets that newline first).
2787
+ 3. Idempotent: a current block is a `current` no-op (no write, no backup).
2788
+ 4. Fail-closed: malformed or duplicate markers, a file that is not valid
2789
+ UTF-8, or any read/write failure produce a per-target `error` row, nothing
2790
+ is written to that file, and — for install/update — the command prints the
2791
+ complete block (`manualBlock` in JSON) so the operator can apply it by
2792
+ hand. Other targets in the same run still proceed. A leading UTF-8 BOM is
2793
+ preserved across every operation.
2794
+ 5. Symlink-aware: writes go through the resolved real file (an operator's
2795
+ canonical-file-linked-everywhere scheme survives); targets resolving to the
2796
+ same real file are written once (`covered via <target> (same file)`).
2797
+ 6. `GNO_AGENTS_HOME_OVERRIDE` overrides the home directory (testing/sandboxed
2798
+ verification); any home override suppresses harness config-dir env vars.
2799
+
2800
+ **Output (JSON):**
2801
+
2802
+ ```json
2803
+ {
2804
+ "command": "install",
2805
+ "blockVersion": 2,
2806
+ "dryRun": false,
2807
+ "results": [
2808
+ {
2809
+ "target": "claude",
2810
+ "label": "Claude Code",
2811
+ "path": "/home/user/.claude/CLAUDE.md",
2812
+ "action": "install",
2813
+ "detected": true,
2814
+ "backup": null
2815
+ },
2816
+ {
2817
+ "target": "grok",
2818
+ "label": "Grok Build",
2819
+ "path": "/home/user/.claude/CLAUDE.md",
2820
+ "action": "covered",
2821
+ "detected": true,
2822
+ "via": "claude",
2823
+ "detail": "covered via claude"
2824
+ }
2825
+ ]
2826
+ }
2827
+ ```
2828
+
2829
+ `action` is one of `install`, `update`, `current`, `covered`, `not-detected`,
2830
+ `error` (and `remove`, `absent` for uninstall). A covered row's `path` is the
2831
+ file the harness actually reads (its covering target's file). With
2832
+ `--dry-run`, a `diffs` array of unified diffs is included. When
2833
+ any target failed on install/update, `manualBlock` carries the complete block
2834
+ text to paste. Schema: `spec/output-schemas/agents-mutation.schema.json`
2835
+ (shared by install, update, and uninstall).
2836
+
2837
+ **Exit Codes:**
2838
+
2839
+ - 0: Success (including no-op)
2840
+ - 1: Validation failure (unknown target, missing `--extra-dir`, malformed
2841
+ markers, non-UTF-8 file)
2842
+ - 2: Runtime failure — every failing target hit an I/O error (unreadable file,
2843
+ backup or write failed); the receipt still lists every target's outcome
2844
+
2845
+ ---
2846
+
2847
+ ### gno agents update
2848
+
2849
+ Refresh an installed block in place (block-version migration). Same options,
2850
+ output, and exit codes as `agents install`; both verbs converge the block to
2851
+ the current release — `update` exists for operator intent clarity.
2852
+
2853
+ ```bash
2854
+ gno agents update [--target <...>] [--extra-dir <path>]... [--dry-run] [--json]
2855
+ ```
2856
+
2857
+ ---
2858
+
2859
+ ### gno agents verify
2860
+
2861
+ Deterministic per-target verification of installed blocks. Fresh-session
2862
+ behavioral canaries are an operator practice, not automated here.
2863
+
2864
+ **Synopsis:**
2865
+
2866
+ ```bash
2867
+ gno agents verify [--target <...>] [--extra-dir <path>]... [--json]
2868
+ ```
2869
+
2870
+ **Checks per target:**
2871
+
2872
+ - Exactly one marker block (`malformed` otherwise)
2873
+ - Block stamp hash matches the block body (tamper detection)
2874
+ - Block version and content match the installed release (`outdated` otherwise)
2875
+ - The block carries no filesystem references by construction, so the spec's
2876
+ link-resolution check is vacuously satisfied
2877
+ - Targets resolving to the same real file are verified once, using install's
2878
+ ownership order; the rest report `covered via <target> (same file)`
2879
+
2880
+ **Output (JSON):**
2881
+
2882
+ ```json
2883
+ {
2884
+ "command": "verify",
2885
+ "blockVersion": 2,
2886
+ "ok": true,
2887
+ "results": [
2888
+ {
2889
+ "target": "claude",
2890
+ "label": "Claude Code",
2891
+ "path": "/home/user/.claude/CLAUDE.md",
2892
+ "status": "ok",
2893
+ "detected": true,
2894
+ "blockVersion": 2,
2895
+ "hashOk": true
2896
+ }
2897
+ ]
2898
+ }
2899
+ ```
2900
+
2901
+ `status` is one of `ok`, `outdated`, `missing`, `malformed`, `error`,
2902
+ `covered`, `not-detected`. `error` means the file exists but could not be read
2903
+ — a "could not check", never a content verdict. Schema:
2904
+ `spec/output-schemas/agents-verify.schema.json`.
2905
+
2906
+ **Exit Codes:**
2907
+
2908
+ - 0: All verified targets ok (covered / not-detected do not fail)
2909
+ - 1: One or more targets `outdated`, `missing`, or `malformed`
2910
+ - 2: Every failing target is an `error` (I/O) row
2911
+
2912
+ ---
2913
+
2914
+ ### gno agents uninstall
2915
+
2916
+ Remove the block, its markers, and the blank line install added above it;
2917
+ everything else stays byte-identical. Same options, output shape
2918
+ (`action: remove|absent|...`), and exit codes as `agents install`.
2919
+
2920
+ ```bash
2921
+ gno agents uninstall [--target <...>] [--extra-dir <path>]... [--dry-run] [--json]
2922
+ ```
2923
+
2924
+ ---
2925
+
2715
2926
  ### gno tags list
2716
2927
 
2717
2928
  List all tags with document counts.
@@ -3615,7 +3826,11 @@ Errors are written to stderr. With `--json` flag, errors are also returned as:
3615
3826
  }
3616
3827
  ```
3617
3828
 
3618
- Error codes match exit codes: `VALIDATION` (exit 1), `RUNTIME` (exit 2), `NOT_RUNNING` (exit 3).
3829
+ Error codes match exit codes: `VALIDATION` (exit 1), `RUNTIME` (exit 2), `NOT_RUNNING` (exit 3), `BUSY` (exit 4).
3830
+
3831
+ Write-lease contention on `index` / `update` / `embed` does not use the generic envelope. Text mode writes the dedicated "index is busy" message to stderr; `--json` writes `{ success: false, error, contention }` to stdout. Both exit 4. `gno audit` also uses exit 4 for findings.
3832
+
3833
+ **`NOT_RUNNING` is not an error envelope.**
3619
3834
 
3620
3835
  **`NOT_RUNNING` is not an error envelope.** `gno serve|daemon --status --json` returns a `process-status`-shaped payload on stdout with exit 3 when no live matching process is found (it reports observable state, not failure). `--stop` exits 3 silently when there is nothing to stop and does not accept `--json`. The error envelope above is reserved for `VALIDATION` and `RUNTIME` failures where the command could not produce its structured output at all.
3621
3836
 
@@ -3623,16 +3838,18 @@ Error codes match exit codes: `VALIDATION` (exit 1), `RUNTIME` (exit 2), `NOT_RU
3623
3838
 
3624
3839
  ## Environment Variables
3625
3840
 
3626
- | Variable | Description |
3627
- | -------------------------- | --------------------------------------------------------------------- |
3628
- | `GNO_CONFIG_DIR` | Override config directory |
3629
- | `GNO_DATA_DIR` | Override data directory (DB location) |
3630
- | `GNO_CACHE_DIR` | Override cache directory (models) |
3631
- | `NO_COLOR` | Disable colored output (standard) |
3632
- | `PAGER` | Pager for long output (default: less -R on Unix, built-in on Windows) |
3633
- | `GNO_SKILLS_HOME_OVERRIDE` | Override home dir for skill user scope (testing) |
3634
- | `CLAUDE_SKILLS_DIR` | Override Claude skills directory |
3635
- | `CODEX_SKILLS_DIR` | Override Codex skills directory |
3841
+ | Variable | Description |
3842
+ | -------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
3843
+ | `GNO_CONFIG_DIR` | Override config directory |
3844
+ | `GNO_DATA_DIR` | Override data directory (DB location) |
3845
+ | `GNO_CACHE_DIR` | Override cache directory (models) |
3846
+ | `NO_COLOR` | Disable colored output (standard) |
3847
+ | `PAGER` | Pager for long output (default: less -R on Unix, built-in on Windows) |
3848
+ | `GNO_SKILLS_HOME_OVERRIDE` | Override home dir for skill user scope (testing) |
3849
+ | `CLAUDE_SKILLS_DIR` | Override Claude skills directory |
3850
+ | `CODEX_SKILLS_DIR` | Override Codex skills directory |
3851
+ | `CLAUDE_CONFIG_DIR` | Claude Code config dir; `gno agents` resolves Claude's instruction file under it (suppressed by an explicit home override) |
3852
+ | `CODEX_HOME` | Codex config dir; same rule as `CLAUDE_CONFIG_DIR` |
3636
3853
 
3637
3854
  ---
3638
3855
 
@@ -0,0 +1,108 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "gno://schemas/agents-mutation@1.0",
4
+ "title": "GNO Agents Mutation Receipt",
5
+ "description": "JSON receipt for `gno agents install|update|uninstall --json`",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": ["command", "blockVersion", "dryRun", "results"],
9
+ "allOf": [
10
+ {
11
+ "if": {
12
+ "properties": { "dryRun": { "const": false } },
13
+ "required": ["dryRun"]
14
+ },
15
+ "then": {
16
+ "not": { "properties": { "diffs": true }, "required": ["diffs"] }
17
+ }
18
+ }
19
+ ],
20
+ "properties": {
21
+ "command": {
22
+ "enum": ["install", "update", "uninstall"],
23
+ "description": "The mutation verb that produced this receipt"
24
+ },
25
+ "blockVersion": {
26
+ "type": "integer",
27
+ "minimum": 1,
28
+ "description": "Protocol block version of the installed release"
29
+ },
30
+ "dryRun": {
31
+ "type": "boolean",
32
+ "description": "True when nothing was written; diffs carries the planned changes"
33
+ },
34
+ "results": {
35
+ "type": "array",
36
+ "description": "One row per resolved target",
37
+ "items": {
38
+ "type": "object",
39
+ "additionalProperties": false,
40
+ "required": ["target", "label", "path", "action", "detected"],
41
+ "allOf": [
42
+ {
43
+ "if": {
44
+ "properties": { "action": { "const": "covered" } },
45
+ "required": ["action"]
46
+ },
47
+ "then": {
48
+ "properties": { "via": true, "detail": true },
49
+ "required": ["via", "detail"]
50
+ }
51
+ }
52
+ ],
53
+ "properties": {
54
+ "target": {
55
+ "type": "string",
56
+ "description": "Harness id (claude, codex, cursor, ...) or extra-dir id"
57
+ },
58
+ "label": {
59
+ "type": "string",
60
+ "description": "Human-readable harness label"
61
+ },
62
+ "path": {
63
+ "type": "string",
64
+ "description": "Instruction file path for this target"
65
+ },
66
+ "action": {
67
+ "enum": [
68
+ "install",
69
+ "update",
70
+ "current",
71
+ "remove",
72
+ "absent",
73
+ "covered",
74
+ "not-detected",
75
+ "error"
76
+ ],
77
+ "description": "What the run did (or would do) for this target"
78
+ },
79
+ "detected": {
80
+ "type": "boolean",
81
+ "description": "Whether the harness config dir exists on this machine"
82
+ },
83
+ "via": {
84
+ "type": "string",
85
+ "description": "Target id that covers this one (import chain or shared real file)"
86
+ },
87
+ "detail": {
88
+ "type": "string",
89
+ "description": "Human-readable detail (coverage reason, error guidance)"
90
+ },
91
+ "backup": {
92
+ "type": ["string", "null"],
93
+ "description": "Backup file path for a written target; null when no backup was made (new file or dry run). Omitted for no-op rows."
94
+ }
95
+ }
96
+ }
97
+ },
98
+ "diffs": {
99
+ "type": "array",
100
+ "description": "Unified diffs of planned writes; present only with dryRun",
101
+ "items": { "type": "string" }
102
+ },
103
+ "manualBlock": {
104
+ "type": "string",
105
+ "description": "The complete block to paste by hand; present on install/update when at least one target reported an error"
106
+ }
107
+ }
108
+ }
@@ -0,0 +1,89 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "gno://schemas/agents-verify@1.0",
4
+ "title": "GNO Agents Verify Receipt",
5
+ "description": "JSON receipt for `gno agents verify --json`",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": ["command", "blockVersion", "ok", "results"],
9
+ "properties": {
10
+ "command": { "const": "verify" },
11
+ "blockVersion": {
12
+ "type": "integer",
13
+ "minimum": 1,
14
+ "description": "Protocol block version of the installed release"
15
+ },
16
+ "ok": {
17
+ "type": "boolean",
18
+ "description": "True when no target is outdated, missing, or malformed (covered / not-detected do not fail)"
19
+ },
20
+ "results": {
21
+ "type": "array",
22
+ "description": "One row per resolved target",
23
+ "items": {
24
+ "type": "object",
25
+ "additionalProperties": false,
26
+ "required": ["target", "label", "path", "status", "detected"],
27
+ "allOf": [
28
+ {
29
+ "if": {
30
+ "properties": { "status": { "const": "covered" } },
31
+ "required": ["status"]
32
+ },
33
+ "then": {
34
+ "properties": { "via": true, "detail": true },
35
+ "required": ["via", "detail"]
36
+ }
37
+ }
38
+ ],
39
+ "properties": {
40
+ "target": {
41
+ "type": "string",
42
+ "description": "Harness id (claude, codex, cursor, ...) or extra-dir id"
43
+ },
44
+ "label": {
45
+ "type": "string",
46
+ "description": "Human-readable harness label"
47
+ },
48
+ "path": {
49
+ "type": "string",
50
+ "description": "Instruction file path for this target"
51
+ },
52
+ "status": {
53
+ "enum": [
54
+ "ok",
55
+ "outdated",
56
+ "missing",
57
+ "malformed",
58
+ "error",
59
+ "covered",
60
+ "not-detected"
61
+ ],
62
+ "description": "Verification outcome for this target (`error` = the file exists but could not be read)"
63
+ },
64
+ "detected": {
65
+ "type": "boolean",
66
+ "description": "Whether the harness config dir exists on this machine"
67
+ },
68
+ "via": {
69
+ "type": "string",
70
+ "description": "Target id whose row carries the actual block status (import chain or shared real file)"
71
+ },
72
+ "detail": {
73
+ "type": "string",
74
+ "description": "Human-readable detail (coverage reason, failure guidance)"
75
+ },
76
+ "blockVersion": {
77
+ "type": "integer",
78
+ "minimum": 0,
79
+ "description": "Version stamped on the found block (a legacy/pre-release stamp may read 0 — the `outdated` migration case); omitted when the stamp is unparseable"
80
+ },
81
+ "hashOk": {
82
+ "type": "boolean",
83
+ "description": "Block body matches its stamp hash (tamper detection)"
84
+ }
85
+ }
86
+ }
87
+ }
88
+ }
89
+ }