agent-notes 2.24.0__tar.gz → 2.25.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 (268) hide show
  1. {agent_notes-2.24.0 → agent_notes-2.25.0}/PKG-INFO +1 -1
  2. agent_notes-2.25.0/agent_notes/VERSION +1 -0
  3. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/cli.py +28 -6
  4. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/config.py +23 -2
  5. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/doctor.py +51 -17
  6. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/hook.py +27 -0
  7. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/info.py +25 -2
  8. agent_notes-2.25.0/agent_notes/commands/install.py +225 -0
  9. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/regenerate.py +46 -19
  10. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/wizard/__init__.py +42 -3
  11. agent_notes-2.25.0/agent_notes/commands/wizard/cost_report.py +41 -0
  12. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/wizard/execute.py +44 -15
  13. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/wizard/orchestrator.py +20 -7
  14. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/cli/claude.yaml +1 -0
  15. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/models/claude-opus-4-7.yaml +2 -1
  16. agent_notes-2.25.0/agent_notes/data/models/claude-opus-4-8.yaml +15 -0
  17. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/roles/reasoner.yaml +1 -1
  18. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/domain/cli_backend.py +9 -2
  19. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/domain/state.py +4 -0
  20. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/registries/cli_registry.py +2 -1
  21. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/scripts/_claude_backend.py +46 -10
  22. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/scripts/cost_report.py +16 -5
  23. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/diagnostics/_checks.py +17 -12
  24. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/install_state_builder.py +36 -15
  25. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/installer.py +46 -15
  26. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/rendering.py +26 -18
  27. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/state_store.py +87 -24
  28. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/user_config.py +7 -0
  29. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes.egg-info/PKG-INFO +1 -1
  30. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes.egg-info/SOURCES.txt +4 -0
  31. agent_notes-2.25.0/tests/unit/commands/wizard/test_cost_report_step.py +120 -0
  32. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/scripts/test_cost_report_scoping.py +10 -2
  33. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/services/test_rendering_includes.py +5 -1
  34. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/services/test_state_store.py +298 -0
  35. agent_notes-2.25.0/tests/unit/services/test_user_config_cost_report.py +330 -0
  36. agent_notes-2.24.0/agent_notes/VERSION +0 -1
  37. agent_notes-2.24.0/agent_notes/commands/install.py +0 -125
  38. {agent_notes-2.24.0 → agent_notes-2.25.0}/LICENSE +0 -0
  39. {agent_notes-2.24.0 → agent_notes-2.25.0}/README.md +0 -0
  40. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/__init__.py +0 -0
  41. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/__main__.py +0 -0
  42. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/__init__.py +0 -0
  43. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/_install_helpers.py +0 -0
  44. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/build.py +0 -0
  45. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/list.py +0 -0
  46. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/memory/__init__.py +0 -0
  47. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/memory/_common.py +0 -0
  48. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/memory/migrate.py +0 -0
  49. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/memory/notes.py +0 -0
  50. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/memory/reset.py +0 -0
  51. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/memory/transfer.py +0 -0
  52. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/memory/vault.py +0 -0
  53. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/memory/wiki.py +0 -0
  54. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/set_role.py +0 -0
  55. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/uninstall.py +0 -0
  56. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/validate.py +0 -0
  57. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/wizard/_common.py +0 -0
  58. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/config.py +0 -0
  59. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/constants.py +0 -0
  60. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/agents.yaml +0 -0
  61. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/analyst.md +0 -0
  62. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/api-reviewer.md +0 -0
  63. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/architect.md +0 -0
  64. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/coder.md +0 -0
  65. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/database-specialist.md +0 -0
  66. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/debugger.md +0 -0
  67. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/devil.md +0 -0
  68. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/devops.md +0 -0
  69. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/explorer.md +0 -0
  70. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/integrations.md +0 -0
  71. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/lead.md +0 -0
  72. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/performance-profiler.md +0 -0
  73. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/refactorer.md +0 -0
  74. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/reviewer.md +0 -0
  75. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/security-auditor.md +0 -0
  76. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/shared/cost_reporting.md +0 -0
  77. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/shared/execution.md +0 -0
  78. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/shared/guardrails.md +0 -0
  79. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/shared/hard_limits.md +0 -0
  80. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/shared/phase0.md +0 -0
  81. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/shared/pipelines.md +0 -0
  82. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/shared/review.md +0 -0
  83. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/shared/verification.md +0 -0
  84. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/shared/wiki_compile.md +0 -0
  85. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/system-auditor.md +0 -0
  86. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/tech-writer.md +0 -0
  87. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/test-runner.md +0 -0
  88. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/test-writer.md +0 -0
  89. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/wiki-compiler.md +0 -0
  90. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/cli/copilot.yaml +0 -0
  91. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/cli/opencode.yaml +0 -0
  92. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/commands/brainstorm.md +0 -0
  93. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/commands/debug.md +0 -0
  94. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/commands/review.md +0 -0
  95. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/global-claude.md +0 -0
  96. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/global-copilot.md +0 -0
  97. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/global-opencode.md +0 -0
  98. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/hooks/session-context.md.tpl +0 -0
  99. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/models/claude-haiku-4-5.yaml +0 -0
  100. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/models/claude-opus-4-1.yaml +0 -0
  101. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/models/claude-opus-4-5.yaml +0 -0
  102. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/models/claude-opus-4-6.yaml +0 -0
  103. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/models/claude-sonnet-4-5.yaml +0 -0
  104. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/models/claude-sonnet-4-6.yaml +0 -0
  105. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/models/claude-sonnet-4.yaml +0 -0
  106. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/plugin/claude.yaml +0 -0
  107. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/plugin/opencode-index.js.template +0 -0
  108. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/plugin/opencode.yaml +0 -0
  109. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/pricing.yaml +0 -0
  110. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/roles/orchestrator.yaml +0 -0
  111. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/roles/scout.yaml +0 -0
  112. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/roles/worker.yaml +0 -0
  113. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/rules/code-quality.md +0 -0
  114. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/rules/safety.md +0 -0
  115. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/brainstorming/SKILL.md +0 -0
  116. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/caveman/SKILL.md +0 -0
  117. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/code-review/SKILL.md +0 -0
  118. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/debugging-protocol/SKILL.md +0 -0
  119. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/docker/SKILL.md +0 -0
  120. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/docker/compose.md +0 -0
  121. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/docker/dockerfile.md +0 -0
  122. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/git/SKILL.md +0 -0
  123. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/grill-me/SKILL.md +0 -0
  124. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/grill-with-docs/SKILL.md +0 -0
  125. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/handoff/SKILL.md +0 -0
  126. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/improve-codebase-architecture/SKILL.md +0 -0
  127. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/ingest/SKILL.md +0 -0
  128. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/migrate-memory/SKILL.md +0 -0
  129. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/obsidian-memory/SKILL.md +0 -0
  130. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/prototype/LOGIC.md +0 -0
  131. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/prototype/SKILL.md +0 -0
  132. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/prototype/UI.md +0 -0
  133. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/rails/SKILL.md +0 -0
  134. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/rails/controllers.md +0 -0
  135. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/rails/frontend.md +0 -0
  136. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/rails/infra.md +0 -0
  137. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/rails/models.md +0 -0
  138. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/rails/testing.md +0 -0
  139. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/rails/views.md +0 -0
  140. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/refactoring-protocol/SKILL.md +0 -0
  141. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/setup-project-context/SKILL.md +0 -0
  142. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/tdd/SKILL.md +0 -0
  143. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/to-issues/SKILL.md +0 -0
  144. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/to-prd/SKILL.md +0 -0
  145. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/write-a-skill/SKILL.md +0 -0
  146. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/zoom-out/SKILL.md +0 -0
  147. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/templates/__init__.py +0 -0
  148. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/templates/__pycache__/__init__.cpython-314.pyc +0 -0
  149. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/templates/frontmatter/__init__.py +0 -0
  150. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/templates/frontmatter/__pycache__/__init__.cpython-314.pyc +0 -0
  151. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/templates/frontmatter/__pycache__/claude.cpython-314.pyc +0 -0
  152. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/templates/frontmatter/__pycache__/opencode.cpython-314.pyc +0 -0
  153. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/templates/frontmatter/claude.py +0 -0
  154. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/templates/frontmatter/opencode.py +0 -0
  155. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/doctor_checks.py +0 -0
  156. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/domain/__init__.py +0 -0
  157. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/domain/agent.py +0 -0
  158. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/domain/diagnostics.py +0 -0
  159. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/domain/diff.py +0 -0
  160. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/domain/model.py +0 -0
  161. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/domain/role.py +0 -0
  162. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/domain/rule.py +0 -0
  163. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/domain/skill.py +0 -0
  164. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/registries/__init__.py +0 -0
  165. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/registries/_base.py +0 -0
  166. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/registries/agent_registry.py +0 -0
  167. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/registries/model_registry.py +0 -0
  168. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/registries/role_registry.py +0 -0
  169. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/registries/rule_registry.py +0 -0
  170. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/registries/skill_registry.py +0 -0
  171. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/scripts/__init__.py +0 -0
  172. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/scripts/_formatting.py +0 -0
  173. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/scripts/_opencode_backend.py +0 -0
  174. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/scripts/_pricing.py +0 -0
  175. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/__init__.py +0 -0
  176. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/_memory_utils.py +0 -0
  177. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/counts.py +0 -0
  178. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/credentials.py +0 -0
  179. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/diagnostics/__init__.py +0 -0
  180. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/diagnostics/_display.py +0 -0
  181. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/diagnostics/_fix.py +0 -0
  182. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/diff.py +0 -0
  183. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/fs.py +0 -0
  184. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/local_backend.py +0 -0
  185. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/memory_router.py +0 -0
  186. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/migrations/__init__.py +0 -0
  187. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/obsidian_backend.py +0 -0
  188. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/session_context.py +0 -0
  189. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/settings_writer.py +0 -0
  190. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/ui.py +0 -0
  191. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/validation.py +0 -0
  192. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/wiki/__init__.py +0 -0
  193. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/wiki/_wiki_utils.py +0 -0
  194. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/wiki/wiki_index.py +0 -0
  195. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/wiki/wiki_ingest.py +0 -0
  196. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/wiki/wiki_lint.py +0 -0
  197. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/wiki/wiki_query.py +0 -0
  198. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/wiki/wiki_storage.py +0 -0
  199. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/wiki_backend.py +0 -0
  200. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes.egg-info/dependency_links.txt +0 -0
  201. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes.egg-info/entry_points.txt +0 -0
  202. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes.egg-info/requires.txt +0 -0
  203. {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes.egg-info/top_level.txt +0 -0
  204. {agent_notes-2.24.0 → agent_notes-2.25.0}/pyproject.toml +0 -0
  205. {agent_notes-2.24.0 → agent_notes-2.25.0}/setup.cfg +0 -0
  206. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/conftest.py +0 -0
  207. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/functional/__init__.py +0 -0
  208. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/functional/commands/__init__.py +0 -0
  209. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/functional/commands/test_config_command.py +0 -0
  210. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/functional/commands/test_doctor_command.py +0 -0
  211. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/functional/commands/test_info_command.py +0 -0
  212. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/functional/commands/test_install_command.py +0 -0
  213. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/functional/commands/test_list_command.py +0 -0
  214. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/functional/commands/test_regenerate_command.py +0 -0
  215. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/functional/commands/test_uninstall_command.py +0 -0
  216. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/functional/commands/test_validate_command.py +0 -0
  217. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/functional/memory/__init__.py +0 -0
  218. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/functional/memory/test_memory_command.py +0 -0
  219. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/functional/scripts/__init__.py +0 -0
  220. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/functional/scripts/test_release_script.py +0 -0
  221. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/integration/__init__.py +0 -0
  222. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/integration/build_output/__init__.py +0 -0
  223. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/integration/build_output/test_build_output.py +0 -0
  224. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/integration/install/__init__.py +0 -0
  225. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/integration/install/test_install_methods.py +0 -0
  226. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/integration/plugin_builders/__init__.py +0 -0
  227. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/integration/plugin_builders/test_plugin_builders.py +0 -0
  228. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/plugins/__init__.py +0 -0
  229. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/plugins/claude/__init__.py +0 -0
  230. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/plugins/claude/test_agents.py +0 -0
  231. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/plugins/test_skills.py +0 -0
  232. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/__init__.py +0 -0
  233. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/commands/__init__.py +0 -0
  234. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/commands/test_cost_report_subcommand.py +0 -0
  235. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/commands/test_count_agents.py +0 -0
  236. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/commands/test_info.py +0 -0
  237. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/commands/test_memory_add_description.py +0 -0
  238. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/commands/test_memory_imports.py +0 -0
  239. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/commands/test_memory_migrate.py +0 -0
  240. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/commands/test_wizard_imports.py +0 -0
  241. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/commands/test_wizard_orchestrator_skip.py +0 -0
  242. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/commands/test_wizard_preflight.py +0 -0
  243. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/commands/test_wizard_steps.py +0 -0
  244. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/registries/__init__.py +0 -0
  245. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/registries/test_registries.py +0 -0
  246. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/scripts/__init__.py +0 -0
  247. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/scripts/test_cost_report.py +0 -0
  248. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/scripts/test_formatting_tty.py +0 -0
  249. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/scripts/test_time_aggregation.py +0 -0
  250. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/services/__init__.py +0 -0
  251. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/services/test_build_functions.py +0 -0
  252. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/services/test_credential_filter.py +0 -0
  253. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/services/test_credentials.py +0 -0
  254. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/services/test_fs.py +0 -0
  255. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/services/test_installer_hooks.py +0 -0
  256. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/services/test_installer_plan.py +0 -0
  257. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/services/test_local_backend.py +0 -0
  258. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/services/test_memory_backend.py +0 -0
  259. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/services/test_memory_backend_io.py +0 -0
  260. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/services/test_memory_router.py +0 -0
  261. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/services/test_session_context.py +0 -0
  262. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/services/test_settings_writer.py +0 -0
  263. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/services/test_skill_filtering.py +0 -0
  264. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/services/test_validation.py +0 -0
  265. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/services/test_wiki_backend.py +0 -0
  266. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/services/test_wiki_imports.py +0 -0
  267. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/test_import_health.py +0 -0
  268. {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/test_memory_dir_for_backend.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agent-notes
3
- Version: 2.24.0
3
+ Version: 2.25.0
4
4
  Summary: AI agent configuration manager for Claude Code, OpenCode, and Copilot
5
5
  Author-email: Eugene Naumov <min.verkligheten@gmail.com>
6
6
  License-Expression: MIT
@@ -0,0 +1 @@
1
+ 2.25.0
@@ -226,6 +226,12 @@ def main():
226
226
  p_install.add_argument("--copy", action="store_true", help="Copy instead of symlink (with --local)")
227
227
  p_install.add_argument("--reconfigure", action="store_true",
228
228
  help="Clear existing state for this scope and re-run the wizard")
229
+ p_install.add_argument("--profile", metavar="LABEL",
230
+ help="Profile label for multi-subscription setups (e.g. work, personal)")
231
+ p_install.add_argument("--folder", metavar="DIR",
232
+ help="Local folder name override (e.g. .claude-work)")
233
+ p_install.add_argument("--global-home", metavar="DIR", dest="global_home",
234
+ help="Global home directory override (e.g. ~/.claude-work)")
229
235
 
230
236
  # build
231
237
  subparsers.add_parser("build", help="Build agent configuration files from source")
@@ -234,6 +240,11 @@ def main():
234
240
  p_uninstall = subparsers.add_parser("uninstall", help="Remove installed components")
235
241
  p_uninstall.add_argument("--local", action="store_true", help="Remove from current project only")
236
242
  p_uninstall.add_argument("--global", action="store_true", dest="global_", help="Remove from global scope only")
243
+ profile_group = p_uninstall.add_mutually_exclusive_group()
244
+ profile_group.add_argument("--profile", metavar="LABEL",
245
+ help="Profile label to uninstall (e.g. work)")
246
+ profile_group.add_argument("--all-profiles", action="store_true",
247
+ help="Uninstall all profiles for the target scope")
237
248
 
238
249
  # doctor
239
250
  p_doctor = subparsers.add_parser("doctor", help="Check installation health")
@@ -267,6 +278,7 @@ def main():
267
278
  p_regen.add_argument("--scope", choices=["global", "local"], help="Install scope")
268
279
  p_regen.add_argument("--cli", help="Regenerate specific CLI only")
269
280
  p_regen.add_argument("--local", action="store_true", help="Use local scope")
281
+ p_regen.add_argument("--profile", metavar="LABEL", help="Profile label")
270
282
 
271
283
  # memory
272
284
  p_memory = subparsers.add_parser("memory", help="Manage agent memory")
@@ -279,7 +291,7 @@ def main():
279
291
 
280
292
  # hook
281
293
  p_hook = subparsers.add_parser("hook", help="Claude Code hook integrations")
282
- p_hook.add_argument("subaction", choices=["memory-bridge"],
294
+ p_hook.add_argument("subaction", choices=["memory-bridge", "session-discover"],
283
295
  help="Hook to run")
284
296
 
285
297
  # cost-report
@@ -290,7 +302,7 @@ def main():
290
302
  # config
291
303
  p_config = subparsers.add_parser("config", help="Reconfigure role/agent/model/memory/skill assignments after install")
292
304
  p_config.add_argument("action", nargs="?", default="wizard",
293
- choices=["wizard", "show", "role-model", "role-agent", "provider", "providers", "memory"],
305
+ choices=["wizard", "show", "role-model", "role-agent", "provider", "providers", "memory", "cost-report"],
294
306
  help="Config action (default: wizard)")
295
307
  p_config.add_argument("extra", nargs="*", help="Additional positional args (role, model, agent)")
296
308
  p_config.add_argument("--cli", help="Target CLI (claude / opencode / both)")
@@ -311,15 +323,24 @@ def main():
311
323
  from .commands.build import build
312
324
  build()
313
325
  elif args.command == "install":
314
- if args.local or args.copy:
326
+ if args.local or args.copy or args.profile or args.folder or args.global_home:
315
327
  from .commands.install import install
316
- install(local=args.local, copy=args.copy, reconfigure=args.reconfigure)
328
+ install(
329
+ local=args.local, copy=args.copy, reconfigure=args.reconfigure,
330
+ profile_label=args.profile or "",
331
+ folder=args.folder or "",
332
+ global_home=args.global_home or "",
333
+ )
317
334
  else:
318
335
  from .commands.wizard import interactive_install
319
336
  interactive_install()
320
337
  elif args.command == "uninstall":
338
+ all_profiles = getattr(args, 'all_profiles', False)
339
+ profile_label = getattr(args, 'profile', '') or ""
321
340
  from .commands.install import uninstall
322
- uninstall(local=args.local, global_=args.global_)
341
+ uninstall(local=args.local, global_=args.global_,
342
+ profile_label=profile_label,
343
+ all_profiles=all_profiles)
323
344
  elif args.command == "doctor":
324
345
  from .commands.doctor import doctor
325
346
  doctor(local=args.local, fix=args.fix)
@@ -338,7 +359,8 @@ def main():
338
359
  set_role(args.role_name, args.model_id, cli=args.cli, scope=args.scope, local=args.local)
339
360
  elif args.command == "regenerate":
340
361
  from .commands.regenerate import regenerate
341
- regenerate(scope=args.scope, cli=args.cli, local=args.local)
362
+ regenerate(scope=args.scope, cli=args.cli, local=args.local,
363
+ profile_label=getattr(args, 'profile', '') or "")
342
364
  elif args.command == "memory":
343
365
  from .commands.memory import memory
344
366
  memory(args.action, args.name, getattr(args, "extra", None), description=getattr(args, "description", ""))
@@ -194,8 +194,13 @@ def show(state=None) -> None:
194
194
  else:
195
195
  mem_label = "Disabled"
196
196
 
197
+ from ..services.user_config import load_user_config
198
+ cost_report_enabled = load_user_config().get("cost_report_enabled", False)
199
+ cost_report_label = "enabled" if cost_report_enabled else "disabled"
200
+
197
201
  print("Current configuration:")
198
- print(f" Memory: {mem_label}")
202
+ print(f" Memory: {mem_label}")
203
+ print(f" Cost report: {cost_report_label}")
199
204
 
200
205
  # Scopes
201
206
  scopes = []
@@ -465,6 +470,17 @@ def interactive_config_memory() -> None:
465
470
  _wizard_memory(state, before)
466
471
 
467
472
 
473
+ def cost_report_toggle(value: str) -> None:
474
+ """Enable or disable cost reporting in user config."""
475
+ from ..services.user_config import load_user_config, save_user_config
476
+ cfg = load_user_config()
477
+ cfg["cost_report_enabled"] = (value == "on")
478
+ save_user_config(cfg)
479
+ state_label = "enabled" if value == "on" else "disabled"
480
+ print(f"Cost reporting {state_label}.")
481
+ print("Run 'agent-notes regenerate' to update generated rules.")
482
+
483
+
468
484
  # ── Entry point ──────────────────────────────────────────────────────────────
469
485
 
470
486
  def config(action: str = "wizard", args: Optional[list] = None, cli_filter: Optional[str] = None) -> None:
@@ -497,7 +513,12 @@ def config(action: str = "wizard", args: Optional[list] = None, cli_filter: Opti
497
513
  _wizard_provider_status(args[0])
498
514
  elif action == "memory":
499
515
  interactive_config_memory()
516
+ elif action == "cost-report":
517
+ if len(args) != 1 or args[0] not in ("on", "off"):
518
+ print("Usage: agent-notes config cost-report <on|off>")
519
+ sys.exit(1)
520
+ cost_report_toggle(args[0])
500
521
  else:
501
522
  print(f"Unknown config action: {action}")
502
- print("Actions: wizard, show, role-model, role-agent, providers, provider, memory")
523
+ print("Actions: wizard, show, role-model, role-agent, providers, provider, memory, cost-report")
503
524
  sys.exit(1)
@@ -1,5 +1,7 @@
1
1
  """Health check for agent-notes installation."""
2
2
 
3
+ from pathlib import Path
4
+
3
5
  # Re-export for backward compatibility. New code should import from agent_notes.domain.
4
6
  from ..domain.diagnostics import Issue, FixAction # noqa: F401
5
7
 
@@ -53,19 +55,33 @@ def _check_session_hook(scope: str, issues: list) -> None:
53
55
  except KeyError:
54
56
  return
55
57
 
56
- settings_path, _context_file, hook_command = _session_hook_paths(claude_backend, scope)
57
- if not has_hook(settings_path, "SessionStart", hook_command):
58
- issues.append(Issue(
59
- "missing_hook",
60
- str(settings_path),
61
- "SessionStart hook not found — run: agent-notes install to re-add the hook",
62
- ))
58
+ from ..services.state_store import load_state, get_profiles_for_project
59
+ state = load_state()
63
60
 
61
+ # Check all profiles for the current project (local scope) or default (global)
62
+ backends_to_check = [claude_backend]
63
+ if state and scope == "local":
64
+ for _key, ss in get_profiles_for_project(state, Path.cwd()):
65
+ bs = ss.clis.get("claude")
66
+ if bs and bs.local_dir_override:
67
+ backends_to_check.append(claude_backend.with_local_dir(bs.local_dir_override))
68
+
69
+ for backend in backends_to_check:
70
+ settings_path, _context_file, hook_command = _session_hook_paths(backend, scope)
71
+ if not settings_path.exists():
72
+ continue
73
+ if not has_hook(settings_path, "SessionStart", hook_command):
74
+ issues.append(Issue(
75
+ "missing_hook",
76
+ str(settings_path),
77
+ "SessionStart hook not found — run: agent-notes install to re-add the hook",
78
+ ))
79
+
80
+ # Memory bridge check on the default backend only
81
+ settings_path, _, _ = _session_hook_paths(claude_backend, scope)
64
82
  from ..constants import Hooks
65
- from ..services.state_store import load_state
66
- state = load_state()
67
83
  if state and state.memory.backend in ("obsidian", "wiki"):
68
- if not has_hook(settings_path, "SessionStart", Hooks.MEMORY_BRIDGE):
84
+ if settings_path.exists() and not has_hook(settings_path, "SessionStart", Hooks.MEMORY_BRIDGE):
69
85
  issues.append(Issue(
70
86
  "missing_hook",
71
87
  str(settings_path),
@@ -111,12 +127,31 @@ def diagnose(scope: str, fix: bool = False) -> bool:
111
127
  issues = []
112
128
  fix_actions = []
113
129
 
114
- # Run checks
115
- check_stale_files(scope, issues, fix_actions)
116
- check_broken_symlinks(scope, issues, fix_actions)
117
- check_shadowed_files(scope, issues, fix_actions)
118
- check_missing_files(scope, issues, fix_actions)
119
- check_content_drift(scope, issues, fix_actions)
130
+ from ..services.state_store import load_current_state, get_profiles_for_project
131
+ from ..services.state_store import label_from_key
132
+
133
+ # For local scope, run checks against each installed profile
134
+ if scope == "local":
135
+ state = load_current_state()
136
+ profiles = []
137
+ if state:
138
+ profiles = get_profiles_for_project(state, Path.cwd().resolve())
139
+ # Fall back to default profile if none recorded
140
+ if not profiles:
141
+ profiles = [("", None)]
142
+ for key, _ss in profiles:
143
+ label = label_from_key(key, Path.cwd())
144
+ check_stale_files(scope, issues, fix_actions, profile_label=label)
145
+ check_broken_symlinks(scope, issues, fix_actions, profile_label=label)
146
+ check_shadowed_files(scope, issues, fix_actions, profile_label=label)
147
+ check_missing_files(scope, issues, fix_actions, profile_label=label)
148
+ check_content_drift(scope, issues, fix_actions, profile_label=label)
149
+ else:
150
+ check_stale_files(scope, issues, fix_actions)
151
+ check_broken_symlinks(scope, issues, fix_actions)
152
+ check_shadowed_files(scope, issues, fix_actions)
153
+ check_missing_files(scope, issues, fix_actions)
154
+ check_content_drift(scope, issues, fix_actions)
120
155
 
121
156
  # Build freshness check (scope-independent)
122
157
  check_build_freshness(issues, fix_actions)
@@ -128,7 +163,6 @@ def diagnose(scope: str, fix: bool = False) -> bool:
128
163
  _check_session_hook(scope, issues)
129
164
 
130
165
  # Print role→model assignments
131
- from ..services.state_store import load_current_state
132
166
  state = load_current_state()
133
167
  if state is not None:
134
168
  _check_role_models(state)
@@ -7,6 +7,33 @@ def hook(subaction: str) -> None:
7
7
  """Handle hook subactions."""
8
8
  if subaction == "memory-bridge":
9
9
  _memory_bridge()
10
+ elif subaction == "session-discover":
11
+ _session_discover()
12
+
13
+
14
+ def _session_discover() -> None:
15
+ """Discover all agent-notes profiles for the current project and emit combined context."""
16
+ try:
17
+ from ..services.state_store import load_state, get_profiles_for_project
18
+ from ..registries.cli_registry import load_registry
19
+
20
+ state = load_state()
21
+ if state is None:
22
+ return
23
+
24
+ registry = load_registry()
25
+ default_local_dirs = {b.name: b.local_dir for b in registry.all()}
26
+
27
+ for key, scope_state in get_profiles_for_project(state, Path.cwd()):
28
+ for cli_name, backend_state in scope_state.clis.items():
29
+ local_dir = backend_state.local_dir_override or default_local_dirs.get(cli_name, ".claude")
30
+ context_file = Path(local_dir) / "agent-notes-context.md"
31
+ if context_file.exists():
32
+ label = scope_state.profile_label or "default"
33
+ print(f"<!-- agent-notes profile: {label} -->")
34
+ print(context_file.read_text(encoding="utf-8"))
35
+ except Exception:
36
+ return
10
37
 
11
38
 
12
39
  def _memory_bridge() -> None:
@@ -73,10 +73,30 @@ def show_info() -> None:
73
73
  else:
74
74
  print(" Global: none")
75
75
 
76
+ # Named global profiles
77
+ if st.global_installs:
78
+ for label, gs in sorted(st.global_installs.items()):
79
+ print(f" Global [{label}]: installed {gs.installed_at}, {gs.mode}")
80
+ if gs.clis:
81
+ backend_summaries = []
82
+ for backend_name, bs in sorted(gs.clis.items()):
83
+ parts = []
84
+ for component_type, items in bs.installed.items():
85
+ if items:
86
+ parts.append(f"{len(items)} {component_type}")
87
+ if parts:
88
+ extra = ""
89
+ if bs.global_home_override:
90
+ extra = f", home={bs.global_home_override}"
91
+ backend_summaries.append(f"{backend_name} ({', '.join(parts)}{extra})")
92
+ if backend_summaries:
93
+ print(f" Storage: {', '.join(backend_summaries)}")
94
+
76
95
  # Local installs
77
96
  if st.local_installs:
78
97
  for project_path, ls in sorted(st.local_installs.items()):
79
- print(f" Local: {project_path} (installed {ls.installed_at}, {ls.mode})")
98
+ profile_hint = f" [{ls.profile_label}]" if ls.profile_label else ""
99
+ print(f" Local{profile_hint}: {project_path} (installed {ls.installed_at}, {ls.mode})")
80
100
  if ls.clis:
81
101
  backend_summaries = []
82
102
  for backend_name, bs in sorted(ls.clis.items()):
@@ -85,7 +105,10 @@ def show_info() -> None:
85
105
  if items:
86
106
  counts.append(f"{len(items)} {component_type}")
87
107
  if counts:
88
- backend_summaries.append(f"{backend_name} ({', '.join(counts)})")
108
+ extra = ""
109
+ if bs.local_dir_override:
110
+ extra = f", folder={bs.local_dir_override}"
111
+ backend_summaries.append(f"{backend_name} ({', '.join(counts)}{extra})")
89
112
  if backend_summaries:
90
113
  print(f" Storage: {', '.join(backend_summaries)}")
91
114
  else:
@@ -0,0 +1,225 @@
1
+ """Install command."""
2
+
3
+ from pathlib import Path
4
+
5
+ from ..config import Color, PKG_DIR
6
+ from ..services.install_state_builder import build_install_state
7
+ from ..services.state_store import load_current_state, record_install_state, remove_install_state, label_from_key
8
+ from ._install_helpers import _verify_install
9
+
10
+
11
+ def install(local: bool = False, copy: bool = False, reconfigure: bool = False,
12
+ profile_label: str = "", folder: str = "", global_home: str = "") -> None:
13
+ """Build from source and install to targets."""
14
+ from ..services.state_store import get_scope, state_file
15
+ from pathlib import Path
16
+
17
+ scope = "local" if local else "global"
18
+ project_path = Path.cwd().resolve() if local else None
19
+
20
+ # Build folder overrides from --folder / --profile
21
+ folder_overrides = None
22
+ if folder:
23
+ folder_overrides = {"claude": folder}
24
+ elif profile_label and not folder:
25
+ folder_overrides = {"claude": f".claude-{profile_label}"}
26
+
27
+ # Default --global-home from profile label if not explicit
28
+ if profile_label and not global_home:
29
+ global_home = f"~/.claude-{profile_label}"
30
+
31
+ state = load_current_state()
32
+ existing = get_scope(state, scope, project_path, profile_label=profile_label) if state else None
33
+
34
+ profile_hint = f" (profile: {profile_label})" if profile_label else ""
35
+
36
+ if existing and not reconfigure:
37
+ # Print existing-install summary
38
+ print(f"Found existing {scope} installation{profile_hint} at {state_file()}")
39
+ print(f" Installed: {existing.installed_at}")
40
+ cli_labels = []
41
+ from ..registries.cli_registry import load_registry
42
+ registry = load_registry()
43
+ for cli_name in existing.clis.keys():
44
+ try:
45
+ cli_labels.append(registry.get(cli_name).label)
46
+ except KeyError:
47
+ cli_labels.append(cli_name)
48
+ print(f" CLIs: {', '.join(cli_labels)}")
49
+ print(f" Mode: {existing.mode}")
50
+ print()
51
+ print("Verifying ...")
52
+ issues = _verify_install(existing, scope, project_path, registry)
53
+ if not issues:
54
+ print()
55
+ print("Installation is healthy.")
56
+ print()
57
+ print("Tip: To reinstall with different choices, run:")
58
+ print(" agent-notes uninstall")
59
+ print(" agent-notes install")
60
+ print()
61
+ print(" Or to re-run the wizard and overwrite in place:")
62
+ print(" agent-notes install --reconfigure")
63
+ else:
64
+ print()
65
+ print(f"Installation has {len(issues)} issue(s).")
66
+ print()
67
+ print("Tip: Run `agent-notes doctor --fix` to repair, or `agent-notes install --reconfigure` to rewizard.")
68
+ return
69
+
70
+ if existing and reconfigure:
71
+ print(f"Clearing existing {scope} state{profile_hint} (--reconfigure) ...")
72
+ remove_install_state(scope, project_path, profile_label=profile_label)
73
+ # Fall through to normal install flow
74
+
75
+ # Validate args
76
+ if copy and not local:
77
+ print("Error: --copy is only valid with --local installs.")
78
+ print("Global installs always use symlinks.")
79
+ return
80
+
81
+ # Build first
82
+ print("Building from source...")
83
+ try:
84
+ from ..commands.build import build
85
+ build()
86
+ except Exception as e:
87
+ print(f"{Color.RED}Build failed: {e}{Color.NC}")
88
+ return
89
+
90
+ # Execute
91
+ label_msg = f", profile={profile_label}" if profile_label else ""
92
+ print(f"Installing ({'local' if local else 'global'}, {'copy' if copy else 'symlink'}{label_msg}) ...")
93
+ print("")
94
+
95
+ from ..services import installer
96
+ scope = "local" if local else "global"
97
+ copy_mode = copy
98
+ installer.install_all(scope, copy_mode,
99
+ folder_overrides=folder_overrides,
100
+ global_home_override=global_home or None)
101
+
102
+ print("")
103
+ print(f"{Color.GREEN}Done.{Color.NC} Restart Claude Code / OpenCode to pick up changes.")
104
+
105
+ # Record state
106
+ try:
107
+ project_path = Path.cwd() if local else None
108
+ st = build_install_state(
109
+ mode="copy" if copy else "symlink",
110
+ scope="local" if local else "global",
111
+ repo_root=PKG_DIR.parent,
112
+ project_path=project_path,
113
+ profile_label=profile_label,
114
+ folder_overrides=folder_overrides,
115
+ global_home_override=global_home or None,
116
+ )
117
+ record_install_state(st)
118
+ except Exception as e:
119
+ print(f"{Color.YELLOW}Warning: failed to write state.json: {e}{Color.NC}")
120
+
121
+
122
+ def _resolve_overrides_from_state(scope: str, project_path, profile_label: str = ""):
123
+ """Read folder/global_home overrides from state.json for the target scope."""
124
+ from ..services.state_store import load_state, get_scope
125
+
126
+ folder_overrides = None
127
+ global_home_override = None
128
+
129
+ state = load_state()
130
+ if state is None:
131
+ return folder_overrides, global_home_override
132
+
133
+ ss = get_scope(state, scope, project_path, profile_label=profile_label)
134
+ if ss is None:
135
+ return folder_overrides, global_home_override
136
+
137
+ for cli_name, bs in ss.clis.items():
138
+ if bs.local_dir_override:
139
+ folder_overrides = folder_overrides or {}
140
+ folder_overrides[cli_name] = bs.local_dir_override
141
+ if bs.global_home_override:
142
+ global_home_override = bs.global_home_override
143
+
144
+ return folder_overrides, global_home_override
145
+
146
+
147
+ def uninstall(local: bool = False, global_: bool = False,
148
+ profile_label: str = "", all_profiles: bool = False) -> None:
149
+ """Remove installed components managed by agent-notes."""
150
+ from ..services import installer
151
+ from ..services.state_store import load_state, get_profiles_for_project
152
+
153
+ # Determine which scopes to uninstall
154
+ if local and not global_:
155
+ scopes = [("local", Path.cwd().resolve())]
156
+ elif global_ and not local:
157
+ scopes = [("global", None)]
158
+ else:
159
+ scopes = [("global", None), ("local", Path.cwd().resolve())]
160
+
161
+ if all_profiles:
162
+ state = load_state()
163
+ if state is None:
164
+ print("Nothing to uninstall — no agent-notes state found.")
165
+ return
166
+ for scope, project_path in scopes:
167
+ if scope == "local":
168
+ profiles = get_profiles_for_project(state, project_path) if state else []
169
+ if not profiles:
170
+ print(f" No profiles found for {project_path}")
171
+ continue
172
+ for key, _ss in profiles:
173
+ label = label_from_key(key, project_path)
174
+ folder_overrides, global_home_override = _resolve_overrides_from_state(
175
+ scope, project_path, label)
176
+ label_hint = f" profile={label}" if label else ""
177
+ print(f"Uninstalling agent-notes ({scope}{label_hint}) ...")
178
+ installer.uninstall_all(scope,
179
+ folder_overrides=folder_overrides,
180
+ global_home_override=global_home_override,
181
+ profile_label=label)
182
+ try:
183
+ remove_install_state(scope, project_path, profile_label=label)
184
+ except Exception as e:
185
+ print(f"{Color.YELLOW}Warning: failed to clear state.json: {e}{Color.NC}")
186
+ else:
187
+ # Global: uninstall default + all labeled profiles
188
+ global_labels = [""] if (state and state.global_install) else []
189
+ if state:
190
+ global_labels += list(state.global_installs.keys())
191
+ for label in global_labels:
192
+ folder_overrides, global_home_override = _resolve_overrides_from_state(
193
+ scope, None, label)
194
+ label_hint = f" profile={label}" if label else ""
195
+ print(f"Uninstalling agent-notes ({scope}{label_hint}) ...")
196
+ installer.uninstall_all(scope,
197
+ folder_overrides=folder_overrides,
198
+ global_home_override=global_home_override,
199
+ profile_label=label)
200
+ try:
201
+ remove_install_state(scope, None, profile_label=label)
202
+ except Exception as e:
203
+ print(f"{Color.YELLOW}Warning: failed to clear state.json: {e}{Color.NC}")
204
+ print(f"{Color.GREEN}Done.{Color.NC} agent-notes components removed.")
205
+ return
206
+
207
+ for scope, project_path in scopes:
208
+ # Always resolve overrides from state so we clean the right directories
209
+ folder_overrides, global_home_override = _resolve_overrides_from_state(
210
+ scope, project_path, profile_label)
211
+
212
+ label_hint = f" profile={profile_label}" if profile_label else ""
213
+ print(f"Uninstalling agent-notes ({scope}{label_hint}) ...")
214
+ installer.uninstall_all(scope,
215
+ folder_overrides=folder_overrides,
216
+ global_home_override=global_home_override,
217
+ profile_label=profile_label)
218
+
219
+ # Remove state entry for this scope
220
+ try:
221
+ remove_install_state(scope, project_path, profile_label=profile_label)
222
+ except Exception as e:
223
+ print(f"{Color.YELLOW}Warning: failed to clear state.json: {e}{Color.NC}")
224
+
225
+ print(f"{Color.GREEN}Done.{Color.NC} agent-notes components removed.")