# 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 [options] gemcms create capsule [options] gemcms create site [options] gemcms create page [options] gemcms create article [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.