1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
|
# gemcms Help
`gemcms` is a file-based CLI CMS for Gemini capsules. Most commands are run
inside a capsule directory, or one of its subdirectories. A capsule is detected
by the presence of `capsule.toml`.
## Global Usage
```text
gemcms
gemcms help
gemcms -h
gemcms --help
```
With no arguments, or with `help`, `-h`, or `--help`, `gemcms` prints the short
usage summary.
Command flags can be placed before or after positional arguments:
```bash
gemcms add ~/article.md --section journal
gemcms add --section journal ~/article.md
```
## Commands Overview
```text
gemcms add <file-or-directory> [options]
gemcms create capsule <name> [options]
gemcms create site <name> [options]
gemcms create page <slug> [options]
gemcms create article <title> [options]
gemcms create section <name> [options]
gemcms create menu <name>
gemcms create widget <type> [options]
gemcms menu add <menu> <kind> [target] [options]
gemcms list <pages|articles|menus|widgets>
gemcms status
gemcms health
gemcms build
gemcms check
```
`create capsule` and `create site` are aliases.
## `gemcms add`
Import an existing Markdown or Gemtext file, or a directory containing importable
files.
```text
gemcms add <file-or-directory> [--type article|page] [--title title] [--slug slug] [--section name] [--tags a,b] [--draft] [--menu name]
```
Options:
| Option | Default | Description |
| --- | --- | --- |
| `--type article|page` | `article` | Imported content type. Frontmatter `type` is used when present and this option is omitted. |
| `--title title` | inferred | Content title. Only valid when importing one file. |
| `--slug slug` | inferred | Content slug. Only valid when importing one file. |
| `--section name` | `articles` | Article section. Ignored for pages. |
| `--tags a,b` | none | Comma-separated tags. |
| `--draft` | `false` | Mark imported content as draft. Drafts are not built and are not added to menus. |
| `--menu name` | none | Add imported non-draft content to the named menu. |
Accepted input extensions:
```text
.md
.markdown
.gmi
.gemini
```
Directory imports recursively import supported files, skip hidden directories,
and sort files deterministically. `--title` and `--slug` cannot be used with
directory imports.
Title inference order:
1. Frontmatter `title`
2. First `# Heading`
3. File name converted to title case
Examples:
```bash
gemcms add ~/article.md --section journal --tags gemini --draft --menu top
gemcms add ~/notes/ --section journal --tags gemini
gemcms add ~/about.gmi --type page --slug about --menu top
```
## `gemcms create capsule`
Create a new capsule project. This command also creates the default top menu,
home page, recent-articles widget, content directories, asset directory, and
`public/`.
```text
gemcms create capsule <name> [--title title] [--host host] [--author name] [--language code] [--import path] [--type article|page] [--section name] [--tags a,b] [--draft] [--menu name] [--build]
```
Options:
| Option | Default | Description |
| --- | --- | --- |
| `--title title` | title-cased name | Capsule title written to `capsule.toml`. |
| `--host host` | empty | Gemini host name. |
| `--author name` | empty | Default author metadata. |
| `--language code` | `en` | Content language metadata. |
| `--import path` | none | Import one file or a directory after capsule creation. |
| `--type article|page` | inferred or `article` | Type for imported content. |
| `--section name` | `articles` | Section for imported articles. |
| `--tags a,b` | none | Tags for imported content. |
| `--draft` | `false` | Mark imported content as draft. |
| `--menu name` | none | Add imported non-draft content to a menu. |
| `--build` | `false` | Build `public/` after creation and optional import. |
Example:
```bash
gemcms create capsule my-capsule --title "My Capsule" --host gemini.example.org --import ~/articles --section journal --tags gemini --build
```
## `gemcms create site`
Alias of `create capsule`.
```text
gemcms create site <name> [same options as create capsule]
```
## `gemcms create page`
Create a new page in `content/pages/`.
```text
gemcms create page <slug> [--title title] [--menu name]
```
Options:
| Option | Default | Description |
| --- | --- | --- |
| `--title title` | title-cased slug | Page title. |
| `--menu name` | none | Add the page to the named menu. |
Example:
```bash
gemcms create page about --title "About" --menu top
```
## `gemcms create article`
Create a new article in `content/articles/`.
```text
gemcms create article <title> [--section name] [--tags a,b] [--draft] [--menu name]
```
Options:
| Option | Default | Description |
| --- | --- | --- |
| `--section name` | `articles` | Article section. |
| `--tags a,b` | none | Comma-separated tags. |
| `--draft` | `false` | Mark article as draft. Drafts are not built and are not added to menus. |
| `--menu name` | none | Add the non-draft article to the named menu. |
Example:
```bash
gemcms create article "Hello Gemini" --section journal --tags gemini,capsule --menu top
```
## `gemcms create section`
Create a section config in `site/sections/`.
```text
gemcms create section <name> [--title title]
```
Options:
| Option | Default | Description |
| --- | --- | --- |
| `--title title` | title-cased name | Section display title. |
Example:
```bash
gemcms create section journal --title "Journal"
```
## `gemcms create menu`
Create an empty menu config in `site/menus/`.
```text
gemcms create menu <name>
```
Example:
```bash
gemcms create menu footer
```
## `gemcms create widget`
Create a build-time widget config in `site/widgets/`.
```text
gemcms create widget <type> [--name name] [--section name] [--limit n]
```
Options:
| Option | Default | Description |
| --- | --- | --- |
| `--name name` | widget type | Widget config name. |
| `--section name` | `articles` | Section used by recent article widgets. |
| `--limit n` | `5` | Maximum number of items. Values below `1` become `5`. |
Currently supported widget type:
| Type | Description |
| --- | --- |
| `recent` | Render recent non-draft articles from one section. |
Example:
```bash
gemcms create widget recent --name recent-journal --section journal --limit 10
```
Use the widget in content:
```text
{{ widget recent-journal }}
```
## `gemcms menu add`
Add an item to a menu. Missing menus are created automatically.
```text
gemcms menu add <menu> <home|page|section|article|custom> [target] [--label label] [--url url]
```
Kinds:
| Kind | Target required | Default URL | Notes |
| --- | --- | --- | --- |
| `home` | no | `/` | Default label: `Home`. |
| `page` | yes | `/<target>.gmi` | `index` maps to `/`. |
| `section` | yes | `/<target>/` | Links to a generated section index. |
| `article` | yes | `/articles/<target>.gmi` | Uses the default `articles` section path. |
| `custom` | yes | none | Requires `--url`. |
Options:
| Option | Default | Description |
| --- | --- | --- |
| `--label label` | inferred | Link label. |
| `--url url` | inferred | Link URL. Required for `custom`. |
Examples:
```bash
gemcms menu add top home
gemcms menu add top page about --label "About"
gemcms menu add top section journal --label "Journal"
gemcms menu add top custom external --label "Project" --url "gemini://example.org/"
```
Use the menu in content:
```text
{{ menu top }}
```
## `gemcms list`
List project objects.
```text
gemcms list <pages|articles|menus|widgets>
```
Output:
| Target | Output format |
| --- | --- |
| `pages` | `slug<TAB>title` |
| `articles` | `date<TAB>section<TAB>slug<TAB>title` |
| `menus` | `name<TAB>N items` |
| `widgets` | `name<TAB>type` |
Examples:
```bash
gemcms list pages
gemcms list articles
gemcms list menus
gemcms list widgets
```
## `gemcms status`
Print a project summary.
```text
gemcms status
```
Includes:
- capsule root
- title
- host
- page, article, and draft counts
- menu, section, and widget counts
- number of generated public files
- health summary
## `gemcms health`
Print only health status and issues.
```text
gemcms health
```
Returns an error exit when errors are present. Warnings are printed but do not
fail the command.
## `gemcms build`
Generate Gemtext output into `public/`.
```text
gemcms build
```
Build behavior:
- Deletes and recreates `public/`.
- Copies files from `assets/` into `public/`.
- Skips draft documents.
- Writes pages as `/<slug>.gmi`, with `index` mapped to `/index.gmi`.
- Writes articles as `/<section>/<slug>.gmi`.
- Generates `/index.gmi` if no `index` page exists.
- Generates section indexes as `/<section>/index.gmi`.
- Expands build-time blocks:
- `{{ menu name }}`
- `{{ widget name }}`
## `gemcms check`
Validate common capsule problems.
```text
gemcms check
```
Checks include:
- missing capsule title
- missing content documents
- missing index page warning
- missing slugs
- duplicate output paths
- broken or suspicious local Gemtext links
- empty menu labels or URLs
- missing widget type
- invalid recent widget section
The command prints `OK` when no issues are found. It returns an error exit when
errors are present.
## Capsule Layout
```text
capsule.toml
content/
pages/
articles/
assets/
site/
menus/
sections/
widgets/
public/
```
## Content Frontmatter
Gemtext files use TOML-like frontmatter:
```text
+++
title = "Hello Gemini"
type = "article"
slug = "hello-gemini"
date = "2026-07-07"
section = "articles"
tags = ["gemini", "capsule"]
draft = true
+++
# Hello Gemini
```
Imported Markdown can also use simple YAML-style frontmatter:
```text
---
title: Hello Gemini
tags: gemini, capsule
---
# Hello Gemini
```
Markdown imports are converted to Gemtext before being stored.
|