Files
HarborForge/plans/harborforge-cli-go-plan.md

1041 lines
24 KiB
Markdown

# 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:<MONITOR_PORT>`
- 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.
#### Special rule for `skills/hf/`
The plugin `skills/` directory should include an `hf/` subfolder.
However:
- if installer is run **without** `--install-cli`, do **not** copy `skills/hf/` into the OpenClaw profile skills directory
- if installer is run **with** `--install-cli`, then `skills/hf/` should be copied together with the CLI installation flow
In other words:
- normal plugin install copies regular plugin skills
- `hf` skill content is gated behind `--install-cli`
#### `skills/hf/SKILL.md` content requirement
`skills/hf/` should contain a `SKILL.md` file.
That skill file should:
- introduce the basic usage of `hf`
- explain that `hf` is the HarborForge CLI
- encourage agents to use:
```bash
hf --help-brief
```
when they want a concise view of the currently permitted command surface
- point agents to normal `--help` when they need the full command tree including `(not permitted)` entries
### 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 <hf-url>
```
must write:
```json
{
"base-url": "<hf-url>"
}
```
into:
```text
<binary-dir>/.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 <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 <group> --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 <group> --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 <group> <subcommand> --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 <group> <subcommand> --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 <token>` becomes required
- if missing, terminate with:
```text
--token <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 <username> [--pass <password>] [--email <email>] [--full-name <name>] [--acc-mgr-token <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 <username>
```
- account-manager token fallback:
```bash
pass_mgr get-secret --public --key hf-acc-mgr-token
```
If password generation fails:
```text
--pass <password> required or execute with pcexec
```
If account-manager token lookup fails:
```text
--acc-mgr-token <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 <hf-url>
```
Behavior:
- write/update `base-url` in `<binary-dir>/.hf-config.json`
## 2. Configure account-manager token
```bash
hf config --acc-mgr-token <token>
```
Behavior:
- execute:
```bash
pass_mgr set --public --key hf-acc-mgr-token --secret <token>
```
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 <username> [--pass <password>] [--email <email>] [--full-name <name>] [--acc-mgr-token <token>]
```
### `hf user list`
```bash
hf user list [--token <token>]
```
### `hf user get`
```bash
hf user get <username|user-id> [--token <token>]
```
### `hf user update`
```bash
hf user update <username|user-id> [--email <email>] [--full-name <name>] [--pass <password>] [--active <true|false>] [--token <token>]
```
### `hf user activate`
```bash
hf user activate <username|user-id> [--token <token>]
```
### `hf user deactivate`
```bash
hf user deactivate <username|user-id> [--token <token>]
```
### `hf user delete`
```bash
hf user delete <username|user-id> [--token <token>]
```
> `hf user worklogs` is not planned.
---
## C. Role / Permission Commands
### `hf role list`
```bash
hf role list [--token <token>]
```
### `hf role get`
```bash
hf role get <role-name> [--token <token>]
```
### `hf role create`
```bash
hf role create --name <role-name> [--desc <desc>] [--global <true|false>] [--token <token>]
```
### `hf role update`
```bash
hf role update <role-name> [--desc <desc>] [--token <token>]
```
### `hf role delete`
```bash
hf role delete <role-name> [--token <token>]
```
### `hf permission list`
```bash
hf permission list [--token <token>]
```
### `hf role set-permissions`
```bash
hf role set-permissions <role-name> --permission <perm> [--permission <perm> ...] [--token <token>]
```
### `hf role add-permissions`
```bash
hf role add-permissions <role-name> --permission <perm> [--permission <perm> ...] [--token <token>]
```
### `hf role remove-permissions`
```bash
hf role remove-permissions <role-name> --permission <perm> [--permission <perm> ...] [--token <token>]
```
---
## D. Project Commands
### `hf project list`
```bash
hf project list [--owner <username>] [--order-by <created|name>] [--order-by <...>] [--token <token>]
```
### `hf project get`
```bash
hf project get <project-code> [--token <token>]
```
### `hf project create`
```bash
hf project create --name <name> [--desc <desc>] [--repo <repo>] [--token <token>]
```
### `hf project update`
```bash
hf project update <project-code> [--name <name>] [--desc <desc>] [--repo <repo>] [--token <token>]
```
### `hf project delete`
```bash
hf project delete <project-code> [--token <token>]
```
### `hf project members`
```bash
hf project members <project-code> [--token <token>]
```
### `hf project add-member`
```bash
hf project add-member <project-code> --user <username> --role <role-name> [--token <token>]
```
### `hf project remove-member`
```bash
hf project remove-member <project-code> --user <username> [--token <token>]
```
---
## E. Milestone Commands
### `hf milestone list`
```bash
hf milestone list --project <project-code> [--status <status>] [--order-by <due-date|created|name>] [--order-by <...>] [--token <token>]
```
### `hf milestone get`
```bash
hf milestone get <milestone-code> [--token <token>]
```
### `hf milestone create`
```bash
hf milestone create --project <project-code> --title <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