feat: pos tree — print the CLI command tree

pos tree derives the hierarchy live from bin/pos-* filenames + # POS:
/# POS_SUBCMDS: headers, so it always matches what the dispatcher can
run. Category-less tool (like pos-config); --depth N limits nesting.

Also sharpen the agent-facing docs that the work exposed:
- AGENTS.md: drop the stale "one category-less exception" claim; document
  the category-less pattern (pos-config, pos-tree) and that gen only reads
  the text after the first em-dash in # POS: headers
- DEV.md: category-less vs categorized rule + header extraction note
- AGENT_Context "Adding a New Tool": new step 0 — pin the exact CLI verb
  and runtime context (dev/repo-only vs installed) before writing code
- POS.md: new config + tree sections; category-less tools get their own
  sections
- README: pos tree bullet following the pos X convention
This commit is contained in:
Your Name
2026-08-09 12:50:52 +00:00
parent 4d8f70d770
commit 52413a6a68
9 changed files with 162 additions and 18 deletions
+20 -16
View File
@@ -10,19 +10,19 @@
<!-- GEN:START docmap -->
| ## 1. Project Overview | 2843 |
| ## 2. Directory Structure | 44180 |
| ## 3. Installation Flow | 181233 |
| ## 4. The `pos` CLI System | 234295 |
| ## 5. Shared Library — `lib/common.sh` | 296327 |
| ## 6. Docker Compose / ScaleTail | 328370 |
| ## 7. Optional Apps (`apps/`) | 371400 |
| ## 8. Entertainment Module | 401414 |
| ## 9. Systemd Services | 415427 |
| ## 10. Configuration Files | 428453 |
| ## 11. Coding Conventions | 454486 |
| ## 12. Development Workflow | 487538 |
| ## 13. Key File Quick Reference | 539586 |
| ## 14. Common Tasks for Agents | 587611 |
| ## 2. Directory Structure | 44181 |
| ## 3. Installation Flow | 182234 |
| ## 4. The `pos` CLI System | 235297 |
| ## 5. Shared Library — `lib/common.sh` | 298329 |
| ## 6. Docker Compose / ScaleTail | 330372 |
| ## 7. Optional Apps (`apps/`) | 373402 |
| ## 8. Entertainment Module | 403416 |
| ## 9. Systemd Services | 417429 |
| ## 10. Configuration Files | 430455 |
| ## 11. Coding Conventions | 456488 |
| ## 12. Development Workflow | 489541 |
| ## 13. Key File Quick Reference | 542590 |
| ## 14. Common Tasks for Agents | 591615 |
<!-- GEN:END docmap -->
## 1. Project Overview
@@ -82,6 +82,7 @@ Linux_post_install/
│ ├── pos-system-health # Host health dashboard (disk, RAM, services, backup age, fail2ban, docker); exit 1 if any FAIL
│ ├── pos-system-nfs-client # Mount NFS shares (ephemeral or persistent systemd mount units)
│ ├── pos-system-nfs-server # Manage the NFS kernel server (status, share/unshare exports, enable/disable)
│ ├── pos-tree # Show the pos CLI command tree: categories, commands, and subcommands
│ ├── pos-usb-server # USB Redirector server control (--ls, --share; prompts when args omitted)
<!-- GEN:END tree -->
│ ├── flag-reader # Inspect feature flags (list/status/--raw)
@@ -274,6 +275,7 @@ All non-interactive `pos` commands log output to `~/.local/share/linux_post_inst
| system | health | `pos-system-health` | Host health dashboard (disk, RAM, services, backup age, fail2ban, docker); exit 1 if any FAIL |
| system | nfs-client | `pos-system-nfs-client` | Mount NFS shares (ephemeral or persistent systemd mount units) |
| system | nfs-server | `pos-system-nfs-server` | Manage the NFS kernel server (status, share/unshare exports, enable/disable) |
| | tree | `pos-tree` | Show the pos CLI command tree: categories, commands, and subcommands |
| usb | server | `pos-usb-server` | USB Redirector server control (--ls, --share; prompts when args omitted) |
<!-- GEN:END dispatch -->
@@ -502,7 +504,8 @@ System-wide flag store at `/usr/local/share/linux_post_install/flags/`:
### Adding a New Tool
1. Create `bin/pos-<category>-<command>` from `templates/pos-tool.sh` — must be executable (`100755`); it auto-appears in `pos <category> --help` (filename-derived, no registration)
0. Define the exact CLI verb (`pos <category> <command> [<subcommand>]`) and its runtime context before writing code: a **dev/repo-only** tool (e.g. reads repo files, like `pos tree`) or a **runtime** tool that must work from `/usr/local/bin` after the repo is deleted. Category-less `bin/pos-<cmd>` is for dispatcher/dev-level commands that fit no category (`pos-config`, `pos-tree`); everything else goes in a category.
1. Create `bin/pos-<category>-<command>` (or `bin/pos-<cmd>` for category-less) from `templates/pos-tool.sh` — must be executable (`100755`); it auto-appears in `pos <category> --help` (filename-derived, no registration)
2. Add the `# POS: <cat> <cmd> — <one-line description>` header right after the shebang (plus `# POS_FLAGS: ...` for flag-style tools and `# POS_SUBCMDS: ...` for multi-command tools) — this is the single source of truth for the generated docs; nested tools (`pos-<cat>-<a>-<b>`) auto-list under their parent tool
3. Add to `INTERACTIVE_CMDS` in `bin/pos` if it reads stdin
4. Add system deps to `PACKAGES` array in `preinstall.sh` (if needed); non-apt/manual installers → `command -v` guard in the tool instead
@@ -552,7 +555,7 @@ Use conventional prefixes: `feat:`, `fix:`, `docs:`, `refactor:`, `chore:`
| `bin/flag-clear` | 21 | Unset a flag |
| `features/autostart.sh` | 14 | Boot-time feature (moved from `bin/`, flag-gated service) |
<!-- GEN:START filetable -->
| `bin/pos` | 270 | CLI dispatcher with smart arg matching + logging + category help |
| `bin/pos` | 272 | CLI dispatcher with smart arg matching + logging + category help |
| `bin/pos-communication-telegram-listener` | 509 | Telegram bot listener: map /command → bash, run them on chat messages |
| `bin/pos-communication-telegram-sender` | 220 | Send Telegram messages/files/links/stickers via Bot API (send, test) |
| `bin/pos-config` | 80 | Interactive editor for the tools' runtime config (reads # POS_CONFIG: registry) |
@@ -577,8 +580,9 @@ Use conventional prefixes: `feat:`, `fix:`, `docs:`, `refactor:`, `chore:`
| `bin/pos-system-health` | 209 | Host health dashboard (disk, RAM, services, backup age, fail2ban, docker); exit 1 if any FAIL |
| `bin/pos-system-nfs-client` | 138 | Mount NFS shares (ephemeral or persistent systemd mount units) |
| `bin/pos-system-nfs-server` | 134 | Manage the NFS kernel server (status, share/unshare exports, enable/disable) |
| `bin/pos-tree` | 110 | Show the pos CLI command tree: categories, commands, and subcommands |
| `bin/pos-usb-server` | 218 | USB Redirector server control (--ls, --share; prompts when args omitted) |
| `completions/pos.bash` | 279 | Dynamic bash completion |
| `completions/pos.bash` | 280 | Dynamic bash completion |
<!-- GEN:END filetable -->
| `apps/install.sh` | 171 | App install/uninstall picker/orchestrator |
+2 -1
View File
@@ -127,7 +127,8 @@ esac
# POS_FLAGS: --flag1 --flag2 # ONLY for flag-style tools
# POS_SUBCMDS: sub1 sub2 # ONLY for multi-command tools
```
The description feeds the dispatch table, bin tree and file table in `DOC/AGENT_Context_Project.md`; `POS_FLAGS` feeds flag completion and `POS_SUBCMDS` feeds subcommand completion in `completions/pos.bash` (both update via `make gen`).
The description feeds the dispatch table, bin tree and file table in `DOC/AGENT_Context_Project.md`; `POS_FLAGS` feeds flag completion and `POS_SUBCMDS` feeds subcommand completion in `completions/pos.bash` (both update via `make gen`). `make gen` only reads the text after the first `` — the `<category> <command>` words before it are convention-only (for nested tools, keep the full path there, e.g. `# POS: communication telegram-listener — …`).
- **Category-less vs categorized:** most tools are `bin/pos-<category>-<command>`. Use category-less `bin/pos-<cmd>` (e.g. `pos-config`, `pos-tree`) only for dispatcher/dev-level commands that fit no category — they dispatch and document like any tool but show with an empty category in the generated tables.
- Nested tools (e.g. `bin/pos-communication-telegram-listener`) are auto-detected from filenames: the trailing segment (`listener`) is offered as a subcommand of the parent tool (`communication-telegram`) in `pos <category> --help` and tab-completion, instead of appearing as a flat sibling (`telegram-listener`). The flat dash-form (`pos communication telegram-listener`) still dispatches.
- Optionally add an EXAMPLES line in `bin/pos` `usage()` to showcase the tool in `pos --help`.
- If the command **reads stdin** (prompts/selection), add it to `INTERACTIVE_CMDS` in `bin/pos` — see [The `pos` CLI](#the-pos-cli).
+23
View File
@@ -14,6 +14,8 @@
- [communication](#communication)
- [entertainment](#entertainment)
- [flags](#flags)
- [config](#config)
- [tree](#tree)
- [Legacy wrappers](#legacy-wrappers)
---
@@ -48,6 +50,8 @@ Every non-interactive `pos` invocation logs to `~/.local/share/linux_post_instal
## Commands
Category-less tools (`config`, `tree`) live outside any category and are documented in their own `###` sections below.
### network
| Command | File | Purpose | Configuration |
@@ -301,6 +305,25 @@ Feature-flag management CLIs (see [SCRIPTS.md → lib/flags.sh](SCRIPTS.md#libfl
| `flag-set <name> [value]` | Set a flag, optionally with a value (requires sudo) |
| `flag-clear <name>` | Unset a flag (requires sudo) |
### config
`pos config` is the interactive editor for the tools' runtime config (see [DEV.md](DEV.md#config-files) and §10 of AGENT_Context). Every tool exposes its configuration by declaring a `# POS_CONFIG:` header; `pos config` reads those at runtime — it knows nothing about the variables themselves. Values live in `~/.config/linux_post_install/<scope>.env` (chmod 600).
| Command | Purpose |
|---------|---------|
| `pos config` | Scope picker (on a TTY), otherwise the scope list |
| `pos config <scope>` | Edit that scope's variables (masked secrets, validation, `-` to clear) |
| `pos config <scope> set KEY=VALUE` | Set a value non-interactively (each tool's `config set` form) |
### tree
`pos tree` prints the `pos` command tree — every category, command, and subcommand the dispatcher can reach, annotated with each tool's `# POS:` description. Data is derived live from the `bin/pos-*` filenames and their `# POS_SUBCMDS:` headers, so it always matches what `pos` can actually run.
| Command | Purpose |
|---------|---------|
| `pos tree` | Full command tree |
| `pos tree --depth N` | Limit nesting depth (1 = root only) |
---
## Legacy wrappers