oacp-cli 0.2.2__tar.gz → 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/CHANGELOG.md +23 -0
  2. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/PKG-INFO +6 -6
  3. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/README.md +5 -5
  4. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/SPEC.md +62 -3
  5. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/docs/guides/runtime_capability_matrix.md +28 -16
  6. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/oacp/cli.py +2 -1
  7. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/pyproject.toml +2 -1
  8. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/scripts/memory_cli.py +91 -7
  9. oacp_cli-0.3.0/scripts/memory_sync.py +547 -0
  10. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/scripts/oacp_doctor.py +427 -0
  11. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/scripts/oacp_watch.py +95 -16
  12. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/scripts/setup_runtime.py +159 -2
  13. oacp_cli-0.3.0/tests/test_memory_archive.py +443 -0
  14. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/tests/test_oacp_doctor.py +106 -0
  15. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/tests/test_oacp_watch.py +217 -6
  16. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/tests/test_setup_runtime.py +57 -0
  17. oacp_cli-0.2.2/tests/test_memory_archive.py +0 -222
  18. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/.github/workflows/ci.yml +0 -0
  19. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/.github/workflows/release.yml +0 -0
  20. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/.gitignore +0 -0
  21. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/CONTRIBUTING.md +0 -0
  22. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/LICENSE +0 -0
  23. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/Makefile +0 -0
  24. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/QUICKSTART.md +0 -0
  25. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/SECURITY.md +0 -0
  26. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/docs/guides/adoption.md +0 -0
  27. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/docs/guides/doctor.md +0 -0
  28. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/docs/guides/prompt_caching.md +0 -0
  29. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/docs/guides/setup.md +0 -0
  30. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/docs/guides/unified_skill_spec.md +0 -0
  31. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/docs/guides/versioning.md +0 -0
  32. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/docs/protocol/agent_profiles.md +0 -0
  33. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/docs/protocol/agent_safety_defaults.md +0 -0
  34. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/docs/protocol/credential_scoping.md +0 -0
  35. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/docs/protocol/cross_runtime_sync.md +0 -0
  36. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/docs/protocol/dispatch_states.yaml +0 -0
  37. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/docs/protocol/inbox_outbox.md +0 -0
  38. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/docs/protocol/mcp_integration.md +0 -0
  39. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/docs/protocol/multi_agent_shared_workspace.md +0 -0
  40. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/docs/protocol/org_memory.md +0 -0
  41. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/docs/protocol/packet_states.yaml +0 -0
  42. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/docs/protocol/review_loop.md +0 -0
  43. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/docs/protocol/runtime_capabilities.md +0 -0
  44. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/docs/protocol/session_init.md +0 -0
  45. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/docs/protocol/skills_manifest.yaml +0 -0
  46. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/docs/protocol/task_negotiation.md +0 -0
  47. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/examples/quickstart/README.md +0 -0
  48. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/mcp_servers/oacp_coordinator.py +0 -0
  49. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/oacp/__init__.py +0 -0
  50. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/scripts/_oacp_constants.py +0 -0
  51. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/scripts/_oacp_env.py +0 -0
  52. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/scripts/add_agent.py +0 -0
  53. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/scripts/agent_profile.py +0 -0
  54. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/scripts/check_quality_gate.py +0 -0
  55. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/scripts/codex_session_init.py +0 -0
  56. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/scripts/create_handoff_packet.py +0 -0
  57. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/scripts/handoff_schema.py +0 -0
  58. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/scripts/init_org_memory.py +0 -0
  59. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/scripts/init_packet.sh +0 -0
  60. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/scripts/init_project_workspace.py +0 -0
  61. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/scripts/init_project_workspace.sh +0 -0
  62. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/scripts/memory_archive_common.py +0 -0
  63. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/scripts/normalize_findings.py +0 -0
  64. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/scripts/oacp_inbox.py +0 -0
  65. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/scripts/preflight.py +0 -0
  66. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/scripts/promote_to_archive.py +0 -0
  67. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/scripts/restore_from_archive.py +0 -0
  68. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/scripts/send_inbox_message.py +0 -0
  69. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/scripts/session_lifecycle_hooks.py +0 -0
  70. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/scripts/update_workspace.sh +0 -0
  71. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/scripts/validate_agent_card.py +0 -0
  72. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/scripts/validate_message.py +0 -0
  73. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/scripts/write_event.py +0 -0
  74. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/templates/agent_card.template.yaml +0 -0
  75. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/templates/agent_profile.template.yaml +0 -0
  76. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/templates/agent_status.template.yaml +0 -0
  77. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/templates/checkpoint.template.md +0 -0
  78. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/templates/claude/agents/role_agent.template.md +0 -0
  79. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/templates/claude/rules/guardrail.template.md +0 -0
  80. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/templates/findings_packet.template.yaml +0 -0
  81. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/templates/github_actions_quality_gate.yaml +0 -0
  82. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/templates/guardrails/coding_standards.template.md +0 -0
  83. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/templates/guardrails/safe_commands.template.md +0 -0
  84. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/templates/guardrails/secrets_rules.template.md +0 -0
  85. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/templates/handoff_packet.template.yaml +0 -0
  86. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/templates/inbox_message.template.yaml +0 -0
  87. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/templates/manual_validation.template.md +0 -0
  88. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/templates/merge_decision.template.md +0 -0
  89. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/templates/org-memory/decisions.md +0 -0
  90. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/templates/org-memory/events/.gitkeep +0 -0
  91. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/templates/org-memory/events/20260317-170120-example-api-convention.md +0 -0
  92. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/templates/org-memory/recent.md +0 -0
  93. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/templates/org-memory/rules.md +0 -0
  94. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/templates/review_packet.template.md +0 -0
  95. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/templates/roles/role_baseline.template.md +0 -0
  96. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/templates/roles/role_definition.template.yaml +0 -0
  97. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/templates/runtime_capabilities.yaml +0 -0
  98. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/templates/skills_manifest.template.yaml +0 -0
  99. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/templates/test_packet.template.md +0 -0
  100. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/tests/test_add_agent.py +0 -0
  101. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/tests/test_agent_profile.py +0 -0
  102. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/tests/test_codex_session_init.py +0 -0
  103. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/tests/test_create_handoff_packet.py +0 -0
  104. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/tests/test_github_workflows.py +0 -0
  105. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/tests/test_handoff_schema.py +0 -0
  106. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/tests/test_init_project_workspace.py +0 -0
  107. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/tests/test_oacp_cli.py +0 -0
  108. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/tests/test_oacp_constants.py +0 -0
  109. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/tests/test_oacp_coordinator.py +0 -0
  110. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/tests/test_oacp_env.py +0 -0
  111. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/tests/test_oacp_inbox.py +0 -0
  112. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/tests/test_preflight.py +0 -0
  113. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/tests/test_review_loop.py +0 -0
  114. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/tests/test_send_inbox_message.py +0 -0
  115. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/tests/test_session_lifecycle_hooks.py +0 -0
  116. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/tests/test_update_workspace.py +0 -0
  117. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/tests/test_validate_agent_card.py +0 -0
  118. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/tests/test_validate_message.py +0 -0
  119. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/tests/test_workspace_discovery.py +0 -0
  120. {oacp_cli-0.2.2 → oacp_cli-0.3.0}/tests/test_write_event.py +0 -0
@@ -5,6 +5,27 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [Unreleased]
9
+
10
+ ## [0.3.0] - 2026-04-29
11
+
12
+ ### Added
13
+
14
+ - `oacp memory init|clone|pull|push|disable` subcommands for opt-in cross-machine sync of `$OACP_HOME/org-memory/**` and `$OACP_HOME/projects/*/memory/**` via a plain git repo rooted at `$OACP_HOME`. Three-state activation model: Disabled (no marker), Local-only (`init` without `--remote`), and Synced (`init --remote <url>` or `clone <url>`).
15
+ - `oacp doctor --memory` advisory checks (10 checks covering marker presence, allowlist coverage, remote configuration, fetch/divergence state, and signing setup).
16
+ - `oacp setup claude` now installs memory pull/push hook scripts and registers them in `.claude/settings.json` for Claude SessionStart and SessionEnd lifecycle events. Hooks are marker-gated and no-op silently unless `$OACP_HOME/.oacp-memory-repo` is present, so existing workflows are unaffected on machines that have not opted in.
17
+
18
+ ## [0.2.3] - 2026-04-26
19
+
20
+ ### Changed
21
+
22
+ - `oacp watch` defaults are now notification-friendly: existing inbox messages are no longer replayed on the first scan for a target, and `message_archived` events are suppressed by default. Pass `--since=epoch` to restore replay and `--show-archived` to re-enable archive events. Reduces noise for `Monitor` and `oacp watch` consumers.
23
+
24
+ ### Added
25
+
26
+ - `oacp watch --since=<spec>` — controls the first-run baseline cutoff. Accepts `now` (default), `epoch`, relative durations (`30s`, `5m`, `2h`, `7d`), or ISO 8601 timestamps. Only applies on first run for a target (no state file yet).
27
+ - `oacp watch --show-archived` — opt-in flag to emit `message_archived` events. Useful for observer agents tracking another agent's inbox; disabled by default because the watching agent's own deletes are self-loops.
28
+
8
29
  ## [0.2.2] - 2026-04-17
9
30
 
10
31
  ### Added
@@ -110,6 +131,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
110
131
  - Checkout step in github-release workflow job (#19)
111
132
  - Pre-release audit fixes: SHA-pinned actions, dangling doc refs (#15, #16)
112
133
 
134
+ [0.3.0]: https://github.com/kiloloop/oacp/compare/v0.2.3...v0.3.0
135
+ [0.2.3]: https://github.com/kiloloop/oacp/compare/v0.2.2...v0.2.3
113
136
  [0.2.2]: https://github.com/kiloloop/oacp/compare/v0.2.1...v0.2.2
114
137
  [0.2.1]: https://github.com/kiloloop/oacp/compare/v0.2.0...v0.2.1
115
138
  [0.2.0]: https://github.com/kiloloop/oacp/compare/v0.1.9...v0.2.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: oacp-cli
3
- Version: 0.2.2
3
+ Version: 0.3.0
4
4
  Summary: Open Agent Coordination Protocol CLI for file-based multi-agent workflows
5
5
  Project-URL: Homepage, https://github.com/kiloloop/oacp
6
6
  Project-URL: Repository, https://github.com/kiloloop/oacp
@@ -152,7 +152,7 @@ uv tool install .
152
152
  | `oacp send` | Send a protocol-compliant inbox message (`--from` auto-inferred) |
153
153
  | `oacp inbox` | List pending messages across agents (table or `--json`) |
154
154
  | `oacp watch` | Emit inbox delta events for one agent across selected projects |
155
- | `oacp memory` | Archive or restore project memory files |
155
+ | `oacp memory` | Archive, restore, or git-sync project/org memory files |
156
156
  | `oacp agent` | Manage global agent profiles (`init`, `show`, `list`) |
157
157
  | `oacp org-memory` | Initialize org-level memory at `$OACP_HOME/org-memory/` |
158
158
  | `oacp write-event` | Write an event to `org-memory/events/` |
@@ -165,11 +165,11 @@ uv tool install .
165
165
 
166
166
  **`oacp send`**: `--in-reply-to`, `--expires`, `--body-file`, `--channel`, `--dry-run`, `--json`, `--quiet`
167
167
 
168
- **`oacp watch`**: `--agent`, repeatable `--project`, `--all-projects`, `--json`
168
+ **`oacp watch`**: `--agent`, repeatable `--project`, `--all-projects`, `--json`, `--since` (default `now`), `--show-archived`
169
169
 
170
- **`oacp doctor`**: `--fix` (auto-fix safe issues), `--json`, `-o/--output`
170
+ **`oacp doctor`**: `--fix` (auto-fix safe issues), `--memory`, `--json`, `-o/--output`
171
171
 
172
- **`oacp memory`**: `oacp memory archive <project> <file>`, `oacp memory restore <project> <file>`
172
+ **`oacp memory`**: `init [--remote URL]`, `clone <URL> [--force]`, `pull`, `push`, `disable`, `archive <project> <file>`, `restore <project> <file>`
173
173
 
174
174
  </details>
175
175
 
@@ -182,7 +182,7 @@ If `OACP_HOME` is unset, workspace commands default to `~/oacp`.
182
182
  | **Inbox/Outbox** | Async messaging between agents via YAML files in `agents/<name>/inbox/` |
183
183
  | **Review Loop** | Structured code review: `review_request` → `review_feedback` → `review_addressed` → `review_lgtm` |
184
184
  | **Quality Gate** | Merge-readiness criteria: no unresolved P0/P1 findings, deferred nits tracked |
185
- | **Durable Memory** | Shared `memory/` directory with an active working set plus `memory/archive/` for historical memory |
185
+ | **Durable Memory** | Shared `memory/` directory with an active working set plus `memory/archive/` for historical memory; optional `$OACP_HOME` git sync tracks only `org-memory/**` and `projects/*/memory/**` |
186
186
  | **Dispatch States** | Task lifecycle: `received` → `accepted` → `working` → `pr_opened` → `in_review` → `done` |
187
187
  | **Safety Defaults** | Baseline rules all agents follow: no force push, no secrets in commits, stage hygiene |
188
188
 
@@ -126,7 +126,7 @@ uv tool install .
126
126
  | `oacp send` | Send a protocol-compliant inbox message (`--from` auto-inferred) |
127
127
  | `oacp inbox` | List pending messages across agents (table or `--json`) |
128
128
  | `oacp watch` | Emit inbox delta events for one agent across selected projects |
129
- | `oacp memory` | Archive or restore project memory files |
129
+ | `oacp memory` | Archive, restore, or git-sync project/org memory files |
130
130
  | `oacp agent` | Manage global agent profiles (`init`, `show`, `list`) |
131
131
  | `oacp org-memory` | Initialize org-level memory at `$OACP_HOME/org-memory/` |
132
132
  | `oacp write-event` | Write an event to `org-memory/events/` |
@@ -139,11 +139,11 @@ uv tool install .
139
139
 
140
140
  **`oacp send`**: `--in-reply-to`, `--expires`, `--body-file`, `--channel`, `--dry-run`, `--json`, `--quiet`
141
141
 
142
- **`oacp watch`**: `--agent`, repeatable `--project`, `--all-projects`, `--json`
142
+ **`oacp watch`**: `--agent`, repeatable `--project`, `--all-projects`, `--json`, `--since` (default `now`), `--show-archived`
143
143
 
144
- **`oacp doctor`**: `--fix` (auto-fix safe issues), `--json`, `-o/--output`
144
+ **`oacp doctor`**: `--fix` (auto-fix safe issues), `--memory`, `--json`, `-o/--output`
145
145
 
146
- **`oacp memory`**: `oacp memory archive <project> <file>`, `oacp memory restore <project> <file>`
146
+ **`oacp memory`**: `init [--remote URL]`, `clone <URL> [--force]`, `pull`, `push`, `disable`, `archive <project> <file>`, `restore <project> <file>`
147
147
 
148
148
  </details>
149
149
 
@@ -156,7 +156,7 @@ If `OACP_HOME` is unset, workspace commands default to `~/oacp`.
156
156
  | **Inbox/Outbox** | Async messaging between agents via YAML files in `agents/<name>/inbox/` |
157
157
  | **Review Loop** | Structured code review: `review_request` → `review_feedback` → `review_addressed` → `review_lgtm` |
158
158
  | **Quality Gate** | Merge-readiness criteria: no unresolved P0/P1 findings, deferred nits tracked |
159
- | **Durable Memory** | Shared `memory/` directory with an active working set plus `memory/archive/` for historical memory |
159
+ | **Durable Memory** | Shared `memory/` directory with an active working set plus `memory/archive/` for historical memory; optional `$OACP_HOME` git sync tracks only `org-memory/**` and `projects/*/memory/**` |
160
160
  | **Dispatch States** | Task lifecycle: `received` → `accepted` → `working` → `pr_opened` → `in_review` → `done` |
161
161
  | **Safety Defaults** | Baseline rules all agents follow: no force push, no secrets in commits, stage hygiene |
162
162
 
@@ -16,7 +16,7 @@ OACP is not a framework or SDK. It is a set of conventions, YAML schemas, and sh
16
16
  3. [Review Loop Protocol](#3-review-loop-protocol)
17
17
  4. [Cross-Runtime Sync](#4-cross-runtime-sync)
18
18
  5. [Agent Safety Defaults](#5-agent-safety-defaults)
19
- 6. [Org-Level Memory](#6-org-level-memory)
19
+ 6. [Org-Level Memory and Sync](#6-org-level-memory-and-sync)
20
20
  7. [Kernel Script Inventory](#7-kernel-script-inventory)
21
21
 
22
22
  ---
@@ -451,7 +451,7 @@ Agents operate under least-privilege credentials:
451
451
 
452
452
  ---
453
453
 
454
- ## 6. Org-Level Memory
454
+ ## 6. Org-Level Memory and Sync
455
455
 
456
456
  Full specification: [`docs/protocol/org_memory.md`](docs/protocol/org_memory.md)
457
457
 
@@ -459,6 +459,16 @@ Full specification: [`docs/protocol/org_memory.md`](docs/protocol/org_memory.md)
459
459
 
460
460
  Shared, cross-project memory for multi-agent organizations. Agents across projects read org-wide decisions, conventions, and events from a single location. Complements per-project memory — does not replace it.
461
461
 
462
+ OACP can optionally sync curated memory across machines using one plain git
463
+ repository rooted at `$OACP_HOME`. This feature is opt-in and tracks only:
464
+
465
+ - `$OACP_HOME/org-memory/**`
466
+ - `$OACP_HOME/projects/<project>/memory/**`
467
+
468
+ Cross-machine inbox delivery, `agents/` runtime state, `status.yaml`, concurrent
469
+ writer protocols, encrypted transport, and runtime-specific memory outside
470
+ `$OACP_HOME` are out of scope.
471
+
462
472
  ### Directory Structure
463
473
 
464
474
  ```
@@ -470,6 +480,28 @@ $OACP_HOME/org-memory/
470
480
  └── YYYYMMDD-HHMMSS-short-slug.md
471
481
  ```
472
482
 
483
+ When memory sync is enabled, `$OACP_HOME` also contains:
484
+
485
+ ```text
486
+ $OACP_HOME/
487
+ ├── .gitignore # positive allowlist
488
+ ├── .oacp-memory-repo # tracked marker; activates hooks
489
+ ├── org-memory/ # tracked
490
+ └── projects/*/memory/ # tracked
491
+ ```
492
+
493
+ Canonical root `.gitignore`:
494
+
495
+ ```gitignore
496
+ *
497
+ !*/
498
+ !.gitignore
499
+ !.oacp-memory-repo
500
+ !org-memory/**
501
+ !projects/*/memory/**
502
+ projects/*/memory/.cache/
503
+ ```
504
+
473
505
  ### Key Concepts
474
506
 
475
507
  - **`recent.md`** is the always-loaded cross-project context. Agents read it at session start via session-init hooks. Kept concise (~150 lines) as a rolling summary of current state, not full history.
@@ -506,11 +538,37 @@ Agents write events only (append-only). The coordinator curates topical files an
506
538
 
507
539
  - **`oacp org-memory init`** — scaffold `$OACP_HOME/org-memory/` with default files
508
540
  - **`oacp write-event`** — create an event file with proper frontmatter
541
+ - **`oacp memory init [--remote URL]`** — initialize the `$OACP_HOME` memory git repo, marker, canonical allowlist, optional remote, and initial commit
542
+ - **`oacp memory clone <URL> [--force]`** — clone a memory repo into `$OACP_HOME`; refuses non-empty targets unless `--force` moves the existing directory aside
543
+ - **`oacp memory pull`** — advisory fetch plus fast-forward-only pull; warns loudly on dirty, ahead, behind, diverged, or fetch-failed states and never auto-merges
544
+ - **`oacp memory push`** — stages only the memory allowlist, commits as `memory: <agent>@<host> <date> (N files)`, then pushes when a remote is configured
545
+ - **`oacp memory disable`** — removes `.oacp-memory-repo` locally while leaving `.git/` intact
546
+ - **`oacp doctor --memory`** — runs advisory memory sync checks for marker state, allowlist drift, tracked/untracked leakage, clean/ahead/behind/diverged state, remote reachability, commit staleness, `agents/` leakage, and per-project memory overlay safety
509
547
 
510
548
  ### Integration with Session Init
511
549
 
512
550
  Agents can read `org-memory/recent.md` at session start for cross-project context. This integration is runtime-specific — for example, Claude Code loads it via a session-init hook, while other runtimes may read it explicitly. Topical files and `events/` are available for on-demand reading when agents need deeper org context.
513
551
 
552
+ Memory sync has three activation states:
553
+
554
+ | State | Trigger | Behavior |
555
+ |-------|---------|----------|
556
+ | Disabled | No `.oacp-memory-repo` marker | Hooks no-op silently; `oacp doctor --memory` reports not configured |
557
+ | Local-only | `oacp memory init` | Wrap-up commits memory locally for audit history; no push |
558
+ | Synced | `oacp memory init --remote URL` or `oacp memory clone <URL>` | Session start pulls fast-forward updates; wrap-up commits and pushes |
559
+
560
+ Lifecycle hooks must check for `$OACP_HOME/.oacp-memory-repo` first and exit
561
+ without output when it is absent. Claude runtime setup installs hook scripts for
562
+ `SessionStart` pull and wrap-up/session-end push:
563
+
564
+ 1. Session start runs `oacp memory pull`. It exits advisory-successfully, pulls
565
+ only clean behind states with `--ff-only`, and warns loudly when memory is
566
+ dirty, ahead, diverged, behind, or remote fetch fails.
567
+ 2. Wrap-up runs `oacp memory push`. It stages only `.gitignore`,
568
+ `.oacp-memory-repo`, `org-memory/**`, and `projects/*/memory/**`; commits
569
+ with the fixed terse message format; pushes when a remote exists; and warns
570
+ loudly when memory is dirty, behind, diverged, or push fails.
571
+
514
572
  ---
515
573
 
516
574
  ## 7. Kernel Script Inventory
@@ -532,7 +590,8 @@ Scripts marked **CLI** are exposed as `oacp` subcommands. Scripts marked **scrip
532
590
  | `agent_profile.py` | Two-tier agent profile management | CLI: `oacp agent` |
533
591
  | `send_inbox_message.py` | Compose and send inbox messages | CLI: `oacp send` |
534
592
  | `oacp_inbox.py` | List pending inbox messages | CLI: `oacp inbox` |
535
- | `memory_cli.py` | Archive or restore project memory files | CLI: `oacp memory` |
593
+ | `memory_cli.py` | Archive, restore, or git-sync project/org memory files | CLI: `oacp memory` |
594
+ | `memory_sync.py` | Shared git allowlist and memory sync helpers | imported by CLI/doctor |
536
595
  | `setup_runtime.py` | Generate runtime-specific config files | CLI: `oacp setup` |
537
596
  | `init_org_memory.py` | Scaffold org-level memory directory | CLI: `oacp org-memory` |
538
597
  | `write_event.py` | Write timestamped events to org-memory | CLI: `oacp write-event` |
@@ -1,10 +1,12 @@
1
1
  # Cross-Runtime Parity Matrix
2
2
 
3
- **Date**: 2026-04-17
3
+ **Date**: 2026-04-29
4
4
 
5
5
  This is a capability comparison across 3 agent runtimes (Claude Code, Codex, Gemini), compiled from each runtime's self-report and current runtime changelogs. Use this as a reference when deciding which agent to assign for a given task.
6
6
 
7
- Codex was last checked against the official Codex changelog entries for app update `26.415` (2026-04-16) and `Codex CLI 0.121.0` (2026-04-15).
7
+ Claude was last checked against Claude Code `v2.1.123`.
8
+
9
+ Codex was last checked against app update `26.415`, CLI `0.123.0`, and OpenAI's GPT-5.5 launch note from 2026-04-23.
8
10
 
9
11
  ---
10
12
 
@@ -15,31 +17,32 @@ Codex was last checked against the official Codex changelog entries for app upda
15
17
  | Spawn background tasks | Yes — Task tool + Bash `run_in_background` | Yes — shell background processes | Yes — `run_command` async mode |
16
18
  | Spawn subagents | Yes — typed agents (Explore, Plan, general-purpose, code-reviewer, etc.) | Yes — native `spawn_agent` lifecycle with `default`, `explorer`, and `worker` agents | Partial — `browser_subagent` only |
17
19
  | Parallel agent teams | Yes — TeamCreate, task lists, SendMessage, broadcast | Partial — parallel spawned agents are supported, but there is no team/task-list primitive | No — parallel tool calls but no independent agent instances |
18
- | MCP tools | Yes — extensible via MCP servers | Yes — MCP/plugin support depends on configured servers and marketplaces | Yes — MCP server support |
20
+ | MCP tools | Yes — extensible via MCP servers | Yes — MCP/plugin support with `/mcp verbose` diagnostics; configuration-dependent | Yes — MCP server support |
19
21
  | Web search | Yes — native WebSearch tool | Yes — web search/fetch tools | Yes — native `search_web` tool |
20
22
  | Browser interaction | Partial — WebFetch (read-only, HTML→markdown) | Partial — web tools plus early in-app browser for local/public pages without sign-in | Yes — full browser control (click, type, navigate, screenshot, video) |
21
- | File system access | Sandboxed — configurable read/write allowlists | Policy-dependent per session | Full — unrestricted |
23
+ | File system access | Sandboxed — configurable read/write allowlists | Policy-dependent per session; sandbox profiles can include deny-read rules | Full — unrestricted |
22
24
  | Git operations | Yes — via Bash (may need sandbox configuration) | Yes — native | Yes — via shell |
23
25
  | GitHub CLI (gh) | Yes — via Bash (may need sandbox configuration) | Yes — authenticated | Yes — native |
24
26
  | Session memory | Strong — auto-loaded MEMORY.md + optional MCP memory | Partial — app memories where available plus OACP file memory; app memories are not protocol SSOT | Partial — Knowledge Items (not directly writable), conversation logs |
25
- | Interactive mode | Yes — CLI chat with permissions, plan mode | Yes — desktop app | Yes — chat with task UI, artifacts |
26
- | Context window | ~1M with Opus 4.7 (auto-compaction extends indefinitely) | Not directly exposed; practically finite | ~1M tokens |
27
- | Cost model | Token-based, visible in statusline | Not surfaced in runtime | Token-based |
28
- | Sandbox restrictions | Yes — configurable allowlists | Session-dependent | None — full system access |
27
+ | Interactive mode | Yes — CLI chat with permissions, plan mode | Yes — desktop app and CLI/TUI, including Plan Mode and side conversations | Yes — chat with task UI, artifacts |
28
+ | Context window | ~1M with Opus 4.7 (auto-compaction extends indefinitely) | Model-dependent; GPT-5.5 in Codex is documented at 400K, with no auto-compaction guarantee | ~1M tokens |
29
+ | Cost model | Token-based, visible in statusline | Not surfaced per session; GPT-5.5 Fast mode trades 2.5x cost for 1.5x token generation speed | Token-based |
30
+ | Sandbox restrictions | Yes — configurable allowlists | Session-dependent; supports deny-read policies, isolated `codex exec`, and remote sandbox requirements | None — full system access |
29
31
 
30
32
  ---
31
33
 
32
- ## 2. Unique Capabilities (Only One Runtime Has)
34
+ ## 2. Distinctive Capabilities
33
35
 
34
36
  | Capability | Runtime | Details |
35
37
  | -------------------------------- | ------------- | ---------------------------------------------------------------------------- |
36
38
  | Typed subagent orchestration | Claude | Multiple agent types with scoped tools and model selection |
37
39
  | Team coordination primitive | Claude | TeamCreate + task lists + assignment + broadcast + shutdown |
38
- | Plan mode | Claude | Structured explore → plan → approve → implement workflow |
40
+ | Plan mode | Claude, Codex | Claude has structured explore → plan → approve → implement; Codex CLI can move from planning into fresh-context implementation |
39
41
  | Auto-compaction | Claude | Context auto-compresses, enabling unlimited session length |
40
42
  | Cross-session semantic search | Claude | MCP-based searchable memory (optional) |
41
43
  | Browser automation (full) | Gemini | Click, type, navigate, screenshot, WebP video recording |
42
- | Image generation | Gemini | Native `generate_image` tool |
44
+ | GPT-5.5 model availability | Codex | Available in Codex for Plus, Pro, Business, Enterprise, Edu, and Go plans with a 400K context window |
45
+ | Image generation | Codex, Gemini | Codex CLI image generation is enabled by default; Gemini has native `generate_image` |
43
46
  | URL content reading (no browser) | Gemini | `read_url_content` fetches HTML→markdown or PDF directly |
44
47
  | Code outline navigation | Gemini | `view_file_outline`, `view_code_item` for structured exploration |
45
48
  | PTY / terminal stdin | Codex, Gemini | Codex: native PTY; Gemini: `send_command_input` (Claude lacks stdin support) |
@@ -68,9 +71,9 @@ Scope: skills shipped in [`kiloloop/oacp-skills`](https://github.com/kiloloop/oa
68
71
 
69
72
  | Dimension | Claude | Codex | Gemini |
70
73
  | --------------- | ---------------------------------------------------------------------- | ----------------------------------------------------------------------- | -------------------------------------------------------------------- |
71
- | Best at | Orchestration, multi-agent teams, persistent memory, plan-then-execute | Terminal-native execution, fast iterative patching, app-assisted PR/artifact review, protocol discipline | Web research, browser automation, visual verification, large context |
72
- | Ideal task type | Team coordination, complex multi-file refactors, long-running sessions | Shell-heavy workflows, targeted file edits, deterministic scripts, PR follow-up, artifact review | External research, UI testing, document review, MCP integrations |
73
- | Cost profile | Flexible (haiku subagents for cheap tasks, opus for complex) | Not directly visible | Token-based, web search has additional costs |
74
+ | Best at | Orchestration, multi-agent teams, persistent memory, plan-then-execute | Terminal-native execution, GPT-5.5 agentic coding, fast iterative patching, plan-to-implementation handoff, app-assisted PR/artifact review, protocol discipline | Web research, browser automation, visual verification, large context |
75
+ | Ideal task type | Team coordination, complex multi-file refactors, long-running sessions | Shell-heavy workflows, long-horizon coding, targeted file edits, deterministic scripts, PR follow-up, artifact review, CLI planning passes | External research, UI testing, document review, MCP integrations |
76
+ | Cost profile | Flexible (haiku subagents for cheap tasks, opus for complex) | Per-session cost not visible; GPT-5.5 is described as more token-efficient than GPT-5.4 for Codex tasks | Token-based, web search has additional costs |
74
77
 
75
78
  ---
76
79
 
@@ -80,11 +83,11 @@ Scope: skills shipped in [`kiloloop/oacp-skills`](https://github.com/kiloloop/oa
80
83
  | ----------------------------- | ----------------------------- | -------------------------------------------------------------- | ---------------------- |
81
84
  | No subagents | — | Yes | Partial (browser only) |
82
85
  | No browser automation | Yes (read-only) | Partial (in-app browser is not full automation and excludes sign-in flows) | — |
83
- | No image generation | Yes | Yes | — |
86
+ | No image generation | Yes | — | — |
84
87
  | No persistent writable memory | — | Partial (app memories are not a replacement for OACP durable memory) | Yes |
85
88
  | Sandbox friction | Yes (configurable) | Session-dependent | — |
86
89
  | No team primitive | — | Yes | Yes |
87
- | Context limits | Auto-compaction mitigates | Yes (no compaction) | Large but finite |
90
+ | Context limits | Auto-compaction mitigates | Model-dependent; GPT-5.5 in Codex is 400K, but there is no documented auto-compaction behavior | Large but finite |
88
91
  | No terminal stdin | Yes | — | — |
89
92
  | Cost not surfaced | — | Yes | — |
90
93
 
@@ -110,6 +113,7 @@ These are the highest-impact gaps where one runtime's limitation blocks effectiv
110
113
  | Dimension | Claude | Codex | Gemini |
111
114
  | ---------------------------- | -------------------------------- | ------------------------------------------ | --------------------------------------------- |
112
115
  | Max parallel tool calls | ~10+ | Yes (parallel independent calls) | ~10 (practical) |
116
+ | Side conversations | No | Yes (`/side` in CLI/TUI) | No |
113
117
  | Hooks system | Yes (pre/post tool call hooks) | No | No |
114
118
  | Automation scheduling | Yes (`CronCreate`, `ScheduleWakeup`, `/loop`, `/schedule` skills) | Yes (desktop app thread automations wake a thread on a schedule, with user request) | No |
115
119
  | Notebook editing | Yes (NotebookEdit tool) | No | No |
@@ -117,6 +121,8 @@ These are the highest-impact gaps where one runtime's limitation blocks effectiv
117
121
  | Image reading (multimodal) | Yes | Yes (desktop app local image/view support) | Yes |
118
122
  | Artifact system | No | Yes (sidebar preview for generated files) | Yes (task.md, implementation plans) |
119
123
  | Video recording | No | No | Yes (WebP via browser) |
124
+ | Image generation | No | Yes (enabled by default in CLI) | Yes |
125
+ | MCP diagnostics | Partial | Yes (`/mcp verbose`) | Partial |
120
126
  | Multi-file editing primitive | Edit tool (one file at a time) | `apply_patch` (one file) | `multi_replace_file_content` (non-contiguous) |
121
127
  | Workflow file format | SKILL.md with YAML frontmatter | SKILL.md with YAML frontmatter | Markdown with YAML frontmatter |
122
128
  | Policy visibility at runtime | Partial (sandbox config visible) | Yes (session policy in system context) | Yes (`SafeToAutoRun` flags) |
@@ -124,4 +130,10 @@ These are the highest-impact gaps where one runtime's limitation blocks effectiv
124
130
 
125
131
  ---
126
132
 
133
+ ## 8. Source Notes
134
+
135
+ - GPT-5.5 Codex availability, 400K context, Fast mode, token-efficiency, and API timing come from OpenAI's 2026-04-23 release note: <https://openai.com/index/introducing-gpt-5-5/>.
136
+
137
+ ---
138
+
127
139
  *Each runtime should update only its own column. Discrepancies should be resolved by the runtime owner.*
@@ -24,7 +24,7 @@ Commands:
24
24
  agent Manage global agent profiles (init, show, list)
25
25
  inbox List pending inbox messages
26
26
  watch Emit inbox delta events for Monitor-friendly polling
27
- memory Archive or restore project memory files
27
+ memory Archive, restore, or sync memory files
28
28
  setup Generate runtime-specific config files in a repo
29
29
  send Send a protocol-compliant inbox message
30
30
  org-memory Initialize org-level memory at $OACP_HOME/org-memory/
@@ -38,6 +38,7 @@ Examples:
38
38
  oacp add-agent my-project alice --runtime claude
39
39
  oacp inbox my-project --agent claude
40
40
  oacp watch --agent claude --project my-project --json
41
+ oacp memory init --remote git@github.com:<YOUR_ORG>/oacp-memory.git
41
42
  oacp memory archive my-project research_notes.md
42
43
  oacp setup claude --project my-project
43
44
  oacp send my-project --to iris --type notification --subject "Done" --body "Completed"
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "oacp-cli"
7
- version = "0.2.2"
7
+ version = "0.3.0"
8
8
  description = "Open Agent Coordination Protocol CLI for file-based multi-agent workflows"
9
9
  readme = "README.md"
10
10
  license = "Apache-2.0"
@@ -63,6 +63,7 @@ packages = ["oacp"]
63
63
  "scripts/oacp_inbox.py" = "oacp/_scripts/oacp_inbox.py"
64
64
  "scripts/oacp_watch.py" = "oacp/_scripts/oacp_watch.py"
65
65
  "scripts/memory_cli.py" = "oacp/_scripts/memory_cli.py"
66
+ "scripts/memory_sync.py" = "oacp/_scripts/memory_sync.py"
66
67
  "scripts/memory_archive_common.py" = "oacp/_scripts/memory_archive_common.py"
67
68
  "scripts/promote_to_archive.py" = "oacp/_scripts/promote_to_archive.py"
68
69
  "scripts/restore_from_archive.py" = "oacp/_scripts/restore_from_archive.py"
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env python3
2
2
  # SPDX-FileCopyrightText: 2026 Kiloloop
3
3
  # SPDX-License-Identifier: Apache-2.0
4
- """Namespace CLI for project memory archive/restore operations."""
4
+ """Namespace CLI for project memory archive/restore and sync operations."""
5
5
 
6
6
  from __future__ import annotations
7
7
 
@@ -14,10 +14,56 @@ from typing import Optional, Sequence
14
14
  def _build_parser() -> argparse.ArgumentParser:
15
15
  parser = argparse.ArgumentParser(
16
16
  prog="oacp memory",
17
- description="Archive or restore project memory files.",
17
+ description="Archive, restore, or sync OACP memory files.",
18
18
  )
19
19
  sub = parser.add_subparsers(dest="command")
20
20
 
21
+ init_parser = sub.add_parser("init", help="Initialize git sync at $OACP_HOME")
22
+ init_parser.add_argument(
23
+ "--remote",
24
+ default=None,
25
+ help="Optional git remote URL for cross-machine sync",
26
+ )
27
+ init_parser.add_argument(
28
+ "--oacp-dir",
29
+ default=None,
30
+ help="Override OACP home directory (default: $OACP_HOME or ~/oacp)",
31
+ )
32
+
33
+ clone_parser = sub.add_parser("clone", help="Clone a memory repo into $OACP_HOME")
34
+ clone_parser.add_argument("url", help="Git remote URL to clone")
35
+ clone_parser.add_argument(
36
+ "--force",
37
+ action="store_true",
38
+ help="Move a non-empty OACP_HOME aside before cloning",
39
+ )
40
+ clone_parser.add_argument(
41
+ "--oacp-dir",
42
+ default=None,
43
+ help="Override OACP home directory (default: $OACP_HOME or ~/oacp)",
44
+ )
45
+
46
+ pull_parser = sub.add_parser("pull", help="Fetch and fast-forward memory sync")
47
+ pull_parser.add_argument(
48
+ "--oacp-dir",
49
+ default=None,
50
+ help="Override OACP home directory (default: $OACP_HOME or ~/oacp)",
51
+ )
52
+
53
+ push_parser = sub.add_parser("push", help="Commit allowlisted memory and push")
54
+ push_parser.add_argument(
55
+ "--oacp-dir",
56
+ default=None,
57
+ help="Override OACP home directory (default: $OACP_HOME or ~/oacp)",
58
+ )
59
+
60
+ disable_parser = sub.add_parser("disable", help="Disable memory sync hooks locally")
61
+ disable_parser.add_argument(
62
+ "--oacp-dir",
63
+ default=None,
64
+ help="Override OACP home directory (default: $OACP_HOME or ~/oacp)",
65
+ )
66
+
21
67
  archive_parser = sub.add_parser(
22
68
  "archive", help="Move a non-standard memory file into memory/archive/"
23
69
  )
@@ -57,6 +103,14 @@ def _build_parser() -> argparse.ArgumentParser:
57
103
 
58
104
  def main(argv: Optional[Sequence[str]] = None) -> int:
59
105
  from _oacp_env import resolve_oacp_home
106
+ from memory_sync import (
107
+ MemorySyncError,
108
+ clone_memory_repo,
109
+ disable_memory_repo,
110
+ init_memory_repo,
111
+ pull_memory,
112
+ push_memory,
113
+ )
60
114
  from promote_to_archive import archive_memory_file
61
115
  from restore_from_archive import restore_memory_file
62
116
 
@@ -67,10 +121,37 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
67
121
  parser.print_help()
68
122
  return 2
69
123
 
124
+ json_output = bool(getattr(args, "json_output", False))
70
125
  oacp_root = resolve_oacp_home(explicit=args.oacp_dir)
71
126
 
72
127
  try:
73
- if args.command == "archive":
128
+ if args.command == "init":
129
+ result = {"action": "init"}
130
+ lines = init_memory_repo(oacp_root, remote=args.remote)
131
+ human = "\n".join(lines)
132
+ elif args.command == "clone":
133
+ result = {"action": "clone", "url": args.url, "oacp_root": str(oacp_root)}
134
+ lines = clone_memory_repo(oacp_root, args.url, force=args.force)
135
+ human = "\n".join(lines)
136
+ elif args.command == "pull":
137
+ result = {"action": "pull"}
138
+ lines = pull_memory(oacp_root)
139
+ human = "\n".join(lines)
140
+ elif args.command == "push":
141
+ result = {"action": "push"}
142
+ lines, code = push_memory(oacp_root)
143
+ human = "\n".join(lines)
144
+ if json_output:
145
+ result["exit_code"] = code
146
+ if not json_output and human:
147
+ print(human)
148
+ elif json_output:
149
+ print(json.dumps(result, indent=2, sort_keys=True))
150
+ return code
151
+ elif args.command == "disable":
152
+ result = {"action": "disable"}
153
+ human = "\n".join(disable_memory_repo(oacp_root))
154
+ elif args.command == "archive":
74
155
  result = archive_memory_file(
75
156
  args.project_name,
76
157
  args.memory_file,
@@ -82,7 +163,7 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
82
163
  f"memory/{result['memory_file']} -> "
83
164
  f"memory/archive/{result['archived_file']}"
84
165
  )
85
- else:
166
+ elif args.command == "restore":
86
167
  result = restore_memory_file(
87
168
  args.project_name,
88
169
  args.archived_file,
@@ -94,13 +175,16 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
94
175
  f"memory/archive/{result['archived_file']} -> "
95
176
  f"memory/{result['restored_file']}"
96
177
  )
97
- except ValueError as exc:
178
+ else:
179
+ parser.print_help()
180
+ return 2
181
+ except (MemorySyncError, ValueError) as exc:
98
182
  print(f"Error: {exc}", file=sys.stderr)
99
183
  return 1
100
184
 
101
- if args.json_output:
185
+ if json_output:
102
186
  print(json.dumps(result, indent=2, sort_keys=True))
103
- else:
187
+ elif human:
104
188
  print(human)
105
189
  return 0
106
190