# HarborForge CLI (hf) Plan ## Goal Build a **Go-based HarborForge CLI binary** named: ```bash hf ``` This CLI should work well in two environments: 1. **With padded-cell / `pass_mgr` available** - agents can execute commands directly - secrets and generated credentials are resolved automatically 2. **Without padded-cell installed** - humans can still use the CLI manually by explicitly passing tokens or account-manager credentials > Important: do **not** directly migrate the old Python CLI from `HarborForge.Backend/cli.py` as-is. > That old CLI is only a reference for command inventory. The new CLI must be a standalone **Go binary**. --- ## High-Level Direction - Language: **Go** - Delivery: **single binary** - Config file: `.hf-config.json` - Config location: **same directory as the CLI binary** - Secret integration: `pass_mgr` - Command style: grouped subcommands (`hf user ...`, `hf task ...`, `hf monitor ...`) - Identifiers: prefer **codes/names** instead of internal numeric ids whenever possible - `project-code` - `milestone-code` - `task-code` - `meeting-code` - `support-code` - `role-name` - `username` --- ## OpenClaw Plugin / Monitor Integration Requirements This CLI plan now also carries **cross-project integration constraints** for: - `HarborForge.OpenclawPlugin` - `HarborForge.Monitor` - `HarborForge.Cli` These requirements should be treated as part of the same roadmap because the CLI, plugin installation flow, and monitor data path are now coupled. ### 1. OpenClaw plugin registration name The plugin currently known as HarborForge.OpenclawPlugin should register under the plugin name: ```text harbor-forge ``` This should replace the old plugin registration name used previously. ### 2. Remove plugin sidecar server The plugin should no longer keep a separate `server/` sidecar process for telemetry collection. That means: - remove the plugin-side `server` component - remove the architecture where plugin telemetry is uploaded by a dedicated sidecar process - any OpenClaw-specific monitor data should instead be served directly by the plugin via the plugin/runtime communication path described below ### 3. Plugin install script: `--install-cli` The OpenClaw plugin install script should support: ```bash --install-cli ``` If present, the installer should: 1. build `HarborForge.Cli` 2. produce the `hf` binary 3. copy the binary into the OpenClaw profile `bin` directory 4. `chmod +x` the installed binary Default target location: ```text ~/.openclaw/bin/hf ``` The implementation should allow profile-aware resolution, but default to: ```text ~/.openclaw/bin ``` ### 4. Plugin config: add `monitor_port` The OpenClaw plugin configuration should add a new field: ```text monitor_port ``` This port is used for **local communication between HarborForge.Monitor and the plugin**. ### 5. HarborForge.Monitor Docker env: `MONITOR_PORT` `HarborForge.Monitor` should add a Docker environment variable: ```text MONITOR_PORT ``` Behavior: - Monitor listens on `127.0.0.1:` - docker-compose should expose this port to the host on `127.0.0.1` - the OpenClaw plugin communicates with Monitor through this local port This communication channel is specifically for supplementing OpenClaw-related telemetry, such as: - OpenClaw version - plugin version - agent information - other OpenClaw runtime metadata that used to come from the plugin-side sidecar telemetry path ### 6. Monitor heartbeat behavior stays independent `HarborForge.Monitor` startup / heartbeat / telemetry upload must **not depend** on successful communication with the plugin over `MONITOR_PORT`. Required behavior: - if no plugin communication happens, Monitor should behave exactly like it does now - if plugin communication succeeds, Monitor should enrich uploaded telemetry with: - OpenClaw version - plugin version - agent list / agent metadata - related OpenClaw-side monitor fields In other words: - hardware/host telemetry path remains primary and independent - OpenClaw-side metadata becomes optional enrichment ### 7. Plugin `skills/` folder deployment `HarborForge.OpenclawPlugin` should include a `skills/` directory. During plugin installation, installer logic should copy everything under that directory into the OpenClaw profile skills directory. Default target location: ```text ~/.openclaw/skills ``` The implementation should be profile-aware, but default to the standard OpenClaw profile path above. ### 8. Implication for implementation planning This means the CLI plan is no longer only about `hf` command syntax. It also implies follow-up implementation work in: - `HarborForge.Cli` - `HarborForge.OpenclawPlugin` - `HarborForge.Monitor` - Docker / install scripts / plugin packaging --- ## Binary / Config Model ## CLI name ```bash hf ``` ## Config file location `hf` must resolve its config file relative to the **binary directory**, not cwd and not home directory. The command: ```bash hf config --url ``` must write: ```json { "base-url": "" } ``` into: ```text /.hf-config.json ``` ## Initial config structure ```json { "base-url": "http://127.0.0.1:8000" } ``` The config file should remain intentionally minimal at first. --- ## Runtime Mode Detection At startup, the CLI must check whether `pass_mgr` exists: ```bash which pass_mgr ``` This determines the CLI mode. ## Mode A — padded-cell / `pass_mgr` installed If `which pass_mgr` succeeds: - the CLI runs in **automatic secret mode** - users/agents should **not** explicitly provide `--token` or `--acc-mgr-token` - help output should **not** show those flags - if a caller explicitly provides such flags, terminate with: ```text padded-cell installed, --token flag disabled, use command directly ``` This message is also used for other manual credential flags that should be suppressed in padded-cell mode. ### Token sources in padded-cell mode For normal authenticated commands: ```bash pass_mgr get-secret --key hf-token ``` For account-manager flow: ```bash pass_mgr get-secret --public --key hf-acc-mgr-token ``` For password generation during user creation: ```bash pass_mgr generate --key hf --username ``` --- ## Mode B — no padded-cell / no `pass_mgr` If `which pass_mgr` fails: - assume padded-cell is not installed - manual auth flags become required where needed - help output must explicitly show the required flags - commands that require token/account-manager credentials must state that clearly in `--help` --- ## Help System Rules ## 1. `hf --help` - does **not** require `--token` - does **not** require `pcexec` - shows all top-level command groups ## 2. `hf --help-brief` - does **not** require `--token` - does **not** require `pcexec` - shows only currently **permitted** top-level command groups ## 3. `hf --help` Show **all** subcommands in the group. - If permitted: show subcommand name + description - If not permitted: show subcommand name + `(not permitted)` - For not-permitted subcommands, do **not** show detailed usage or flag descriptions Example: ```text hf user --help list List users get Show a user by username or id create Create a user account (uses account-manager token flow) update (not permitted) activate (not permitted) deactivate (not permitted) delete (not permitted) ``` ## 4. `hf --help-brief` Show only currently **permitted** subcommands. Example: ```text hf user --help-brief list List users get Show a user by username or id create Create a user account (uses account-manager token flow) ``` ## 5. `hf --help` - If permitted: show full help - If not permitted: show only a short message such as: ```text hf user update: not permitted ``` No detailed usage, no flags, no examples. ## 6. `hf --help-brief` For leaf commands, this behaves the same as `--help`: - permitted → full help - not permitted → short `not permitted` message only ## 7. Mode-sensitive help ### padded-cell mode - hide `--token` - hide `--acc-mgr-token` - hide other manual credential flags that should not be used directly ### manual mode - show required credential flags where needed - clearly indicate commands that require `--token` - clearly indicate `user create` special requirements --- ## Credential / Auth Rules ## Normal authenticated commands For most resource commands, auth behaves like this: ### padded-cell mode - do not accept `--token` - auto-read token using: ```bash pass_mgr get-secret --key hf-token ``` ### manual mode - `--token ` becomes required - if missing, terminate with: ```text --token required or execute this with pcexec ``` --- ## Special command: `hf user create` `hf user create` is **special**. It does **not** use the normal user token flow. It uses **account-manager token** flow. Command shape: ```bash hf user create --user [--pass ] [--email ] [--full-name ] [--acc-mgr-token ] ``` ### Rules - no `--token` - no `--role` - default role is always `guest` ### padded-cell mode - do not show `--acc-mgr-token` - do not allow callers to pass `--acc-mgr-token` - password fallback: ```bash pass_mgr generate --key hf --username ``` - account-manager token fallback: ```bash pass_mgr get-secret --public --key hf-acc-mgr-token ``` If password generation fails: ```text --pass required or execute with pcexec ``` If account-manager token lookup fails: ```text --acc-mgr-token required or execute with pcexec ``` ### manual mode - `--acc-mgr-token` must be shown in help - `--pass` may be omitted only if running with pcexec / pass_mgr-compatible flow - otherwise use the same exact failure messages above ### Special help behavior Even if the current user token lacks normal user-write permission, `hf user create` may still appear as available because it is a distinct **account-manager token flow**. --- ## Config Commands ## 1. Configure HarborForge URL ```bash hf config --url ``` Behavior: - write/update `base-url` in `/.hf-config.json` ## 2. Configure account-manager token ```bash hf config --acc-mgr-token ``` Behavior: - execute: ```bash pass_mgr set --public --key hf-acc-mgr-token --secret ``` If this fails: ```text --acc-mgr-token can only be set with padded-cell plugin ``` --- ## Supported Command Tree This section defines the intended command surface. --- ## A. Base Commands ### `hf version` ```bash hf version ``` ### `hf health` ```bash hf health ``` > No separate auth/login command group is planned. > Authentication is entirely handled through padded-cell/pass_mgr mode or explicit manual flags. --- ## B. User Commands ### `hf user create` ```bash hf user create --user [--pass ] [--email ] [--full-name ] [--acc-mgr-token ] ``` ### `hf user list` ```bash hf user list [--token ] ``` ### `hf user get` ```bash hf user get [--token ] ``` ### `hf user update` ```bash hf user update [--email ] [--full-name ] [--pass ] [--active ] [--token ] ``` ### `hf user activate` ```bash hf user activate [--token ] ``` ### `hf user deactivate` ```bash hf user deactivate [--token ] ``` ### `hf user delete` ```bash hf user delete [--token ] ``` > `hf user worklogs` is not planned. --- ## C. Role / Permission Commands ### `hf role list` ```bash hf role list [--token ] ``` ### `hf role get` ```bash hf role get [--token ] ``` ### `hf role create` ```bash hf role create --name [--desc ] [--global ] [--token ] ``` ### `hf role update` ```bash hf role update [--desc ] [--token ] ``` ### `hf role delete` ```bash hf role delete [--token ] ``` ### `hf permission list` ```bash hf permission list [--token ] ``` ### `hf role set-permissions` ```bash hf role set-permissions --permission [--permission ...] [--token ] ``` ### `hf role add-permissions` ```bash hf role add-permissions --permission [--permission ...] [--token ] ``` ### `hf role remove-permissions` ```bash hf role remove-permissions --permission [--permission ...] [--token ] ``` --- ## D. Project Commands ### `hf project list` ```bash hf project list [--owner ] [--order-by ] [--order-by <...>] [--token ] ``` ### `hf project get` ```bash hf project get [--token ] ``` ### `hf project create` ```bash hf project create --name [--desc ] [--repo ] [--token ] ``` ### `hf project update` ```bash hf project update [--name ] [--desc ] [--repo ] [--token ] ``` ### `hf project delete` ```bash hf project delete [--token ] ``` ### `hf project members` ```bash hf project members [--token ] ``` ### `hf project add-member` ```bash hf project add-member --user --role [--token ] ``` ### `hf project remove-member` ```bash hf project remove-member --user [--token ] ``` --- ## E. Milestone Commands ### `hf milestone list` ```bash hf milestone list --project [--status ] [--order-by ] [--order-by <...>] [--token ] ``` ### `hf milestone get` ```bash hf milestone get [--token ] ``` ### `hf milestone create` ```bash hf milestone create --project --title [--desc <desc>] [--due <date>] [--token <token>] ``` ### `hf milestone update` ```bash hf milestone update <milestone-code> [--title <title>] [--desc <desc>] [--status <status>] [--due <date>] [--token <token>] ``` ### `hf milestone delete` ```bash hf milestone delete <milestone-code> [--token <token>] ``` ### `hf milestone progress` ```bash hf milestone progress <milestone-code> [--token <token>] ``` --- ## F. Task Commands ### `hf task list` ```bash hf task list [--project <project-code>] [--milestone <milestone-code>] [--status <status>] [--taken-by <me|null|username>] [--due-today <true|false>] [--order-by <due-date|priority|created|name>] [--order-by <...>] [--token <token>] ``` Defaults: - `--taken-by me` - `--due-today false` - `--order-by due-date` ### `hf task get` ```bash hf task get <task-code> [--token <token>] ``` ### `hf task create` ```bash hf task create --project <project-code> --title <title> [--milestone <milestone-code>] [--type <type>] [--priority <priority>] [--desc <desc>] [--token <token>] ``` ### `hf task update` ```bash hf task update <task-code> [--title <title>] [--desc <desc>] [--status <status>] [--priority <priority>] [--assignee <username|null>] [--token <token>] ``` ### `hf task transition` ```bash hf task transition <task-code> <status> [--token <token>] ``` ### `hf task take` ```bash hf task take <task-code> [--token <token>] ``` Behavior: - assign the task to the current user - if already taken by another user or permission rules block the change, return a clear error ### `hf task delete` ```bash hf task delete <task-code> [--token <token>] ``` ### `hf task search` ```bash hf task search --query <text> [--project <project-code>] [--status <status>] [--token <token>] ``` --- ## G. Meeting Commands Meeting logic is task-like, but the special action is **attend**, not take. ### `hf meeting list` ```bash hf meeting list [--project <project-code>] [--status <status>] [--order-by <created|due-date|name>] [--order-by <...>] [--token <token>] ``` ### `hf meeting get` ```bash hf meeting get <meeting-code> [--token <token>] ``` ### `hf meeting create` ```bash hf meeting create --project <project-code> --title <title> [--milestone <milestone-code>] [--desc <desc>] [--time <datetime>] [--token <token>] ``` ### `hf meeting update` ```bash hf meeting update <meeting-code> [--title <title>] [--desc <desc>] [--status <status>] [--time <datetime>] [--token <token>] ``` ### `hf meeting attend` ```bash hf meeting attend <meeting-code> [--token <token>] ``` Behavior: - add the current user to the meeting participant list ### `hf meeting delete` ```bash hf meeting delete <meeting-code> [--token <token>] ``` --- ## H. Support Commands Support logic is also task-like. ### `hf support list` ```bash hf support list [--taken-by <me|null|username>] [--status <status>] [--order-by <due-date|priority|created|name>] [--order-by <...>] [--token <token>] ``` ### `hf support get` ```bash hf support get <support-code> [--token <token>] ``` ### `hf support create` ```bash hf support create --title <title> [--project <project-code>] [--desc <desc>] [--priority <priority>] [--token <token>] ``` ### `hf support update` ```bash hf support update <support-code> [--title <title>] [--desc <desc>] [--status <status>] [--priority <priority>] [--token <token>] ``` ### `hf support take` ```bash hf support take <support-code> [--token <token>] ``` ### `hf support transition` ```bash hf support transition <support-code> <status> [--token <token>] ``` ### `hf support delete` ```bash hf support delete <support-code> [--token <token>] ``` --- ## I. Comment / Worklog Commands ### `hf comment add` ```bash hf comment add --task <task-code> --content <text> [--token <token>] ``` ### `hf comment list` ```bash hf comment list --task <task-code> [--token <token>] ``` ### `hf worklog add` ```bash hf worklog add --task <task-code> --hours <n> [--desc <text>] [--date <yyyy-mm-dd>] [--token <token>] ``` ### `hf worklog list` ```bash hf worklog list [--task <task-code>] [--user <username>] [--token <token>] ``` --- ## J. Propose Commands ### `hf propose list` ```bash hf propose list --project <project-code> [--status <status>] [--order-by <created|name>] [--order-by <...>] [--token <token>] ``` ### `hf propose get` ```bash hf propose get <propose-code|propose-id> [--token <token>] ``` > If propose code does not exist yet in backend, the CLI may temporarily accept ids, but code-based lookup is the target direction. ### `hf propose create` ```bash hf propose create --project <project-code> --title <title> --desc <desc> [--token <token>] ``` ### `hf propose update` ```bash hf propose update <propose-code|propose-id> [--title <title>] [--desc <desc>] [--token <token>] ``` ### `hf propose accept` ```bash hf propose accept <propose-code|propose-id> --milestone <milestone-code> [--token <token>] ``` ### `hf propose reject` ```bash hf propose reject <propose-code|propose-id> [--reason <reason>] [--token <token>] ``` ### `hf propose reopen` ```bash hf propose reopen <propose-code|propose-id> [--token <token>] ``` --- ## K. Monitor Commands ### `hf monitor overview` ```bash hf monitor overview [--token <token>] ``` ### `hf monitor server list` ```bash hf monitor server list [--token <token>] ``` ### `hf monitor server get` ```bash hf monitor server get <server-identifier|server-id> [--token <token>] ``` ### `hf monitor server create` ```bash hf monitor server create --identifier <identifier> [--name <display-name>] [--token <token>] ``` ### `hf monitor server delete` ```bash hf monitor server delete <identifier|server-id> [--token <token>] ``` ### `hf monitor api-key generate` ```bash hf monitor api-key generate <identifier|server-id> [--token <token>] ``` ### `hf monitor api-key revoke` ```bash hf monitor api-key revoke <identifier|server-id> [--token <token>] ``` --- ## Backend / Permission Requirements The CLI design depends on backend support for a narrow **account-manager** capability. ## Required protected roles In addition to: - `admin` - `guest` also protect: - `account-manager` ## account-manager semantics - default seeded role - cannot be deleted - should only have the permission: - `account.create` - should not inherit general admin powers ## Current alignment The backend should support: - single global role per account - default `guest` assignment for normal account creation - admin role protected from normal user-management reassignment - account-manager flow for creating accounts --- ## Planned Implementation Phases ## Phase 1 — Foundation - create Go module - add binary entrypoint for `hf` - implement config file resolution relative to binary directory - add `.hf-config.json` load/save - implement runtime mode detection via `which pass_mgr` - implement help renderer (`--help` and `--help-brief`) - add HTTP client wrapper ## Phase 2 — Secrets / Mode Behavior - implement padded-cell mode flag suppression - implement manual mode required credential flags - implement normal token resolution rules - implement account-manager token resolution rules - enforce exact failure messages ## Phase 3 — Config + Core Commands - `hf version` - `hf health` - `hf config --url` - `hf config --acc-mgr-token` ## Phase 4 — User / Role / Project Baseline - `hf user create` - `hf user list` - `hf user get` - `hf user update` - `hf user activate` - `hf user deactivate` - `hf user delete` - `hf role list` - `hf role get` - `hf project list` - `hf project get` ## Phase 5 — Task / Milestone / Propose / Monitor - task commands - milestone commands - propose commands - monitor commands - meeting commands - support commands ## Phase 6 — Plugin / Install Integration - rename OpenClaw plugin registration to `harbor-forge` - remove plugin-side telemetry `server/` sidecar architecture - add plugin config field `monitor_port` - add plugin installer flag `--install-cli` - build and install `hf` into OpenClaw profile `bin/` - copy plugin `skills/` into OpenClaw profile `skills/` ## Phase 7 — Monitor / Plugin Local Bridge - add `MONITOR_PORT` to HarborForge.Monitor Docker runtime - expose `127.0.0.1:<MONITOR_PORT>` to host in compose - let Monitor query plugin over this local port for OpenClaw metadata - keep hardware heartbeat / telemetry upload independent of plugin communication - enrich Monitor uploads with OpenClaw version / plugin version / agent metadata when available ## Phase 8 — Hardening - tests for config-path behavior - tests for mode switching (`pass_mgr` present / absent) - tests for exact stderr messages - tests for help and help-brief rendering - tests for permission-aware help visibility - tests for plugin installer behavior (`--install-cli`, skills copy) - tests for monitor local bridge behavior with and without plugin connectivity - binary packaging / release pipeline --- ## Non-Goals (for now) - do not directly port the old Python CLI architecture - do not add a separate `auth` command group - do not store normal auth token in `.hf-config.json` - do not expose admin role assignment through `hf user create` - do not broaden account-manager beyond account creation in the first design