@geml/geml 1.7.1 → 1.7.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/package.json CHANGED
@@ -1,67 +1,67 @@
1
- {
2
- "name": "@geml/geml",
3
- "version": "1.7.1",
4
- "mcpName": "io.github.geml-spec/geml",
5
- "publishConfig": {
6
- "access": "public"
7
- },
8
- "description": "CLI and parser for GEML, a plain-text document format where every block has an id — so an AI patches one block instead of rewriting the file; edits, reference checks and rollbacks are all per block. Ships an MCP server.",
9
- "type": "module",
10
- "bin": {
11
- "geml": "dist/geml.js"
12
- },
13
- "main": "dist/geml.js",
14
- "types": "dist/geml.d.ts",
15
- "files": [
16
- "dist",
17
- "codemap",
18
- "skill",
19
- "README.md",
20
- "LICENSE"
21
- ],
22
- "engines": {
23
- "node": ">=22"
24
- },
25
- "keywords": [
26
- "geml",
27
- "general expressive markup language",
28
- "mcp",
29
- "mcp-server",
30
- "markup",
31
- "markdown",
32
- "parser",
33
- "cli",
34
- "document",
35
- "typed-block",
36
- "ai",
37
- "agent",
38
- "llm",
39
- "addressable",
40
- "versioning",
41
- "docs",
42
- "code-graph"
43
- ],
44
- "repository": {
45
- "type": "git",
46
- "url": "git+https://github.com/geml-spec/geml.git",
47
- "directory": "geml-parser"
48
- },
49
- "homepage": "https://github.com/geml-spec/geml#readme",
50
- "bugs": {
51
- "url": "https://github.com/geml-spec/geml/issues"
52
- },
53
- "scripts": {
54
- "build": "tsc",
55
- "test": "tsc && node test/all.mjs",
56
- "parse": "node dist/geml.js",
57
- "coverage": "tsc && c8 --all --include=dist/**/*.js --include=codemap/**/*.mjs --reporter=text --reporter=text-summary node test/all.mjs",
58
- "coverage:check": "tsc && c8 --all --include=dist/**/*.js --include=codemap/**/*.mjs --check-coverage --lines 95 --statements 95 --functions 95 --branches 95 node test/all.mjs",
59
- "prepublishOnly": "npm run build"
60
- },
61
- "license": "MIT",
62
- "devDependencies": {
63
- "@types/node": "^22.19.21",
64
- "c8": "^10.1.3",
65
- "typescript": "^5.9.3"
66
- }
67
- }
1
+ {
2
+ "name": "@geml/geml",
3
+ "version": "1.7.3",
4
+ "mcpName": "io.github.geml-spec/geml",
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
8
+ "description": "CLI and parser for GEML, a plain-text document format where every block has an id — so an AI patches one block instead of rewriting the file; edits, reference checks and rollbacks are all per block. Ships an MCP server.",
9
+ "type": "module",
10
+ "bin": {
11
+ "geml": "dist/cli.js"
12
+ },
13
+ "main": "dist/geml.js",
14
+ "types": "dist/geml.d.ts",
15
+ "files": [
16
+ "dist",
17
+ "codemap",
18
+ "skill",
19
+ "README.md",
20
+ "LICENSE"
21
+ ],
22
+ "engines": {
23
+ "node": ">=22"
24
+ },
25
+ "keywords": [
26
+ "geml",
27
+ "general expressive markup language",
28
+ "mcp",
29
+ "mcp-server",
30
+ "markup",
31
+ "markdown",
32
+ "parser",
33
+ "cli",
34
+ "document",
35
+ "typed-block",
36
+ "ai",
37
+ "agent",
38
+ "llm",
39
+ "addressable",
40
+ "versioning",
41
+ "docs",
42
+ "code-graph"
43
+ ],
44
+ "repository": {
45
+ "type": "git",
46
+ "url": "git+https://github.com/geml-spec/geml.git",
47
+ "directory": "geml-parser"
48
+ },
49
+ "homepage": "https://github.com/geml-spec/geml#readme",
50
+ "bugs": {
51
+ "url": "https://github.com/geml-spec/geml/issues"
52
+ },
53
+ "scripts": {
54
+ "build": "tsc",
55
+ "test": "tsc && node test/all.mjs",
56
+ "parse": "node dist/geml.js",
57
+ "coverage": "tsc && c8 --all --include=dist/**/*.js --include=codemap/**/*.mjs --reporter=text --reporter=text-summary node test/all.mjs",
58
+ "coverage:check": "tsc && c8 --all --include=dist/**/*.js --include=codemap/**/*.mjs --check-coverage --lines 95 --statements 95 --functions 95 --branches 95 node test/all.mjs",
59
+ "prepublishOnly": "npm run build"
60
+ },
61
+ "license": "MIT",
62
+ "devDependencies": {
63
+ "@types/node": "^22.19.21",
64
+ "c8": "^10.1.3",
65
+ "typescript": "^5.9.3"
66
+ }
67
+ }
package/skill/SKILL.md CHANGED
@@ -50,15 +50,50 @@ Inside the geml-spec repo prefer the local build:
50
50
  `node geml-parser/dist/geml.js <args>`. If no parser is reachable, follow the
51
51
  golden rules and validate once it is.
52
52
 
53
+ `geml skill install` sets all of this up user-global, and installs this text
54
+ into whatever other agent tools it detects — a tool's directory has to be there
55
+ already; none is ever created for you. `--dry-run` shows what it would do.
56
+
53
57
  ## Work blockwise (agent editing)
54
58
 
55
59
  ```sh
60
+ geml list file.geml # CALL THIS FIRST — every block, its address, kind, lines
61
+ geml find "text" file.geml|dir # search block CONTENT -> file<TAB>address (exit 1 = no hit)
56
62
  geml get file.geml '#id' # read ONE block (a heading id = its whole section)
57
63
  geml set file.geml '#id' --in f # replace ONE block (re-parsed; never writes a broken doc)
64
+ geml replace file.geml OLD NEW # EXPERIMENTAL literal swap; --within '#id' to narrow
58
65
  geml history save file.geml -m "…" # snapshot to .gemlhistory after each meaningful edit
59
66
  geml revert file.geml '#id' # roll ONE block back (--rev -2 | changed | <rev-id>)
60
67
  ```
61
68
 
69
+ Address a block, never a line range: `#id` · `'## Heading'` (its whole section)
70
+ · `'=== type'` · `@<hex>` (no id) · `L27` or `L27-58` (the smallest block holding
71
+ those lines — how a line number from an editor, a linter or a diff hunk becomes
72
+ an address). `list` and `find` print addresses that paste straight into the
73
+ others, so neither `grep` nor a line count is needed to locate anything.
74
+
75
+ Any section can be cut three ways, on `get` and `set` alike: `--head` (the
76
+ heading line), `--intro` (what it says before its first subheading — empty when
77
+ one follows immediately, the whole body when none does), `--body` (everything
78
+ under it, so it always contains the intro). `--intro` is how you edit a
79
+ section's opening without pulling its subsections into context, and setting an
80
+ empty one writes an opening where the section had none.
81
+
82
+ When the exact old text is already known and nothing needs reading — a version
83
+ string in six places, a renamed term — `geml replace` is the cheap path, and the
84
+ one to prefer over dropping to `sed`: same two short strings, but the result is
85
+ re-parsed before it lands, the blocks it touched are named back to you, and it
86
+ is in `.gemlhistory` to revert. It swaps a LITERAL, never a pattern, and refuses
87
+ a swap that would rename an id (use `geml rename`, which fixes the references
88
+ too). **It is EXPERIMENTAL and may be withdrawn** — reach for it, but do not
89
+ build anything on it that cannot change.
90
+
91
+ A write is refused when it would break the document, never merely because it
92
+ removes something: a replacement that drops blocks is carried out and NAMED on
93
+ stderr — unnamed blocks included — with `geml revert` as the way back. Read,
94
+ edit, write back, and nothing is dropped, because `get` handed those blocks to
95
+ you. Send content that omits them only when removing them is the point.
96
+
62
97
  ## Full reference — pull ONE section, not the whole file
63
98
 
64
99
  `references/authoring.geml` (under this skill's base directory) holds the
@@ -214,10 +214,17 @@ All commands accept `-` to read from stdin.
214
214
 
215
215
  === code {#cli-verbs lang=sh}
216
216
  geml file.geml # document-model JSON (default --to json)
217
- geml get file.geml # list every addressable block + address (--json = array)
217
+ geml list file.geml # CALL FIRST: every block, its address, kind, line range
218
+ geml find "text" file.geml|dir # search block CONTENT -> file<TAB>address; exit 1 = no hit
219
+ geml get file.geml # same listing as `list` (the no-selector default)
218
220
  geml get file.geml '#id' # print ONE block (raw span; --json = model node)
219
221
  geml get file.geml '=== note' # every block of a type; '@a3f9c1d2' = a block with no #id
222
+ geml get file.geml 'L27-58' # position: the smallest block holding those lines
223
+ geml get file.geml '#sec' --intro # a section cut three ways: --head | --intro | --body
220
224
  geml set file.geml '#id' --in f # replace ONE block (guarded: re-parsed, never writes broken)
225
+ geml set file.geml '#sec' --intro # replace just the opening; the subsections stay put
226
+ geml replace file.geml OLD NEW # EXPERIMENTAL, may be withdrawn: literal swap, checked and
227
+ # reported; --within '#id' or '=== type' narrows the scope
221
228
  geml add file.geml --after '#id' --in f # insert a fragment (keeps its own ids)
222
229
  geml delete file.geml '#id' ['#id2'] # remove one or more blocks
223
230
  geml rename file.geml '#old' '#new' # rename an id AND every reference to it