# NousResearch/hermes-agent · Dashboard backup CLI argument flag bug

## Open now

- Nothing open on GitHub.

The dashboard backup feature was passing the output path as a positional argument rather than using the correct -o/--output flag, causing backup failures. Multiple issue reports and fix attempts address this CLI argument syntax mismatch.

## TL;DR

- 7 member(s): 0 open issue(s), 4 closed issue(s), 0 open PR(s), 1 merged PR(s), 2 PR(s) closed without merging.
- A fix was merged to main in PR #64561. Verify it addresses your case.
- **Recommended:** read PR #64561 (and any competing PRs below) before filing. Confirm the merged change covers your symptom.

## Maintainer resolution verdict

- Internal-tracker verdict over this cluster's issue members: `partially_resolved` · deciding PR(s): `pr-64561`. This is distinct from the fix status above. Weigh it yourself.

## How this cluster was grouped

- Link evidence (`STRUCTURAL_PARTIAL`): some members are connected by structural evidence (shared changed files, or a closing/superseded reference); the rest are joined by an automated relevance judgement over their text.
- Members outside that structural core may belong to a different underlying problem.
- Pairwise link density `0.25`: the share of member pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36. `1.00` means every pair is linked.

## Closed / duplicate issues

- #54801: Dashboard backup button passes archive path as positional argument instead of --output flag
- #59078: Dashboard backup passes output path as bare arg instead of -o
- #62489: Backup error in macos App
- #65034: Dashboard Full Backup fails silently in v0.18.2 — CLI argument syntax mismatch

## Prior & competing PRs

- **#64561: fix(dashboard): pass backup output path with -o instead of positional arg**. merged to main · fix tier `verified`
  - maintainer direction: category `merged`; implication `superseded`
  - files: `hermes_cli/web_server.py`, `tests/hermes_cli/test_dashboard_admin_endpoints.py`, `tests/hermes_cli/test_web_server.py`
  - fix hunks:
  - `hermes_cli/web_server.py`

    ```diff
    @@ -11915,8 +11915,9 @@ def _new_dashboard_backup_path() -> Path:
     async def run_backup(body: BackupRequest):
         args = ["backup"]
         archive: Optional[Path] = None
    -    if body.output:
    -        args.append(body.output.strip())
    +    output = (body.output or "").strip()
    +    if output:
    +        args.extend(["-o", output])
         else:
             archive = _new_dashboard_backup_path()
             try:
    ```

    ```diff
    @@ -11926,7 +11927,7 @@ async def run_backup(body: BackupRequest):
                     status_code=500,
                     detail=f"Could not create backup directory: {exc}",
                 )
    -        args.append(str(archive))
    +        args.extend(["-o", str(archive)])
         try:
             proc = _spawn_hermes_action(args, "backup")
         except Exception as exc:
    ```
  - `tests/hermes_cli/test_dashboard_admin_endpoints.py`

    ```diff
    @@ -338,6 +338,60 @@ class TestOpsEndpoints:
         def _setup(self, _isolate_hermes_home):
             self.client, _ = _client()
     
    +    def test_backup_output_uses_output_flag(self, monkeypatch):
    +        import hermes_cli.web_server as ws
    +
    +        captured = {}
    +
    +        class FakeProc:
    +            pid = 12345
    +
    +        def fake_spawn_action(subcommand, name):
    +            captured["subcommand"] = subcommand
    +            captured["name"] = name
    +            return FakeProc()
    +
    +        monkeypatch.setattr(ws, "_spawn_hermes_action", fake_spawn_action)
    +
    +        r = self.client.post(
    +            "/api/ops/backup",
    +            json={"output": "  /tmp/hermes-test.zip  "},
    +        )
    +
    +        assert r.status_code == 200
    +        assert captured == {
    +            "subcommand": ["backup", "-o", "/tmp/hermes-test.zip"],
    +            "name": "backup",
    +        }
    +
    +    def test_backup_blank_output_uses_default_archive(self, monkeypatch):
    +        from pathlib import Path
    +
    +        import hermes_cli.web_server as ws
    +        from hermes_cli.config import get_hermes_home
    +
    +        captured = {}
    +
    +        class FakeProc:
    +            pid = 12345
    +
    +        def fake_spawn_action(subcommand, name):
    +            captured["subcommand"] = subcommand
    +            captured["name"] = name
    +            return FakeProc()
    +
    +        monkeypatch.setattr(ws, "_spawn_hermes_action", fake_spawn_action)
    +
    +        r = self.client.post("/api/ops/backup", json={"output": "   "})
    +
    +        assert r.status_code == 200
    +        archive = Path(r.json()["archive"])
    +        assert captured == {
    +            "subcommand": ["backup", "-o", str(archive)],
    +            "name": "backup",
    +        }
    +        assert archive.parent == get_hermes_home() / "backups"
    +
         def test_hooks_list_reads_config(self):
             from hermes_cli.config import load_config, save_config
     
    ```
  - `tests/hermes_cli/test_web_server.py`

    ```diff
    @@ -2385,7 +2385,7 @@ def fake_spawn(subcommand, name):
     
             assert data["name"] == "backup"
             assert captured["name"] == "backup"
    -        assert captured["args"] == ["backup", str(archive)]
    +        assert captured["args"] == ["backup", "-o", str(archive)]
             assert archive.parent == get_hermes_home() / "backups"
             assert archive.name.startswith("hermes-backup-")
             assert archive.suffix == ".zip"
    ```

    ```diff
    @@ -2412,7 +2412,7 @@ def fake_spawn(subcommand, name):
             archive = Path(resp.json()["archive"])
     
             assert archive.parent == hosted_home / "backups"
    -        assert captured["args"] == ["backup", str(archive)]
    +        assert captured["args"] == ["backup", "-o", str(archive)]
             assert archive.parent.is_dir()
     
         def test_ops_backup_download_streams_dashboard_backup(self, tmp_path):
    ```
- **#55043: fix(dashboard): pass backup output with -o**. closed without merge
  - maintainer direction: category `merged_via`; implication `superseded`; refs `#64561`
- **#62631: fix(dashboard): pass --output to backup command**. closed without merge
  - maintainer direction: category `duplicate_of`; implication `duplicate`; refs `#55043`, `#54801`, `#62489`

## Fix status

- Merged to main in PR #64561 (cited above). No release data is tracked. Verify downstream.
- Fix last verified (merged) `2026-07-14`.
- Subsystem: `dashboard`
