reprompt-cli 1.3.0__tar.gz → 1.4.1__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 (246) hide show
  1. reprompt_cli-1.4.1/.testmondata +0 -0
  2. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/CLAUDE.md +3 -2
  3. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/PKG-INFO +1 -1
  4. reprompt_cli-1.4.1/docs/roadmap.md +97 -0
  5. reprompt_cli-1.4.1/docs/superpowers/specs/2026-03-23-v131-suggestions-source-design.md +179 -0
  6. reprompt_cli-1.4.1/docs/superpowers/specs/2026-03-24-v14-context-recovery-design.md +342 -0
  7. reprompt_cli-1.4.1/docs/superpowers/specs/2026-03-24-v141-polish-design.md +184 -0
  8. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/pyproject.toml +1 -1
  9. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/__init__.py +1 -1
  10. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/adapters/chatgpt.py +1 -3
  11. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/adapters/claude_code.py +3 -5
  12. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/cli.py +376 -182
  13. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/core/conversation.py +1 -0
  14. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/core/digest.py +11 -10
  15. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/core/distill.py +42 -21
  16. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/core/insights.py +92 -1
  17. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/core/style.py +62 -1
  18. reprompt_cli-1.4.1/src/reprompt/core/suggestions.py +22 -0
  19. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/core/trends.py +4 -2
  20. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/output/compress_terminal.py +1 -0
  21. reprompt_cli-1.4.1/src/reprompt/output/export.py +270 -0
  22. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/output/terminal.py +139 -3
  23. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/storage/db.py +66 -7
  24. reprompt_cli-1.4.1/tests/fixtures/export/default_export.md +29 -0
  25. reprompt_cli-1.4.1/tests/fixtures/export/full_export.md +36 -0
  26. reprompt_cli-1.4.1/tests/test_compare_best_worst.py +233 -0
  27. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_compress.py +1 -2
  28. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_compress_cli.py +1 -0
  29. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_conversation.py +1 -3
  30. reprompt_cli-1.4.1/tests/test_deprecated_commands.py +60 -0
  31. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_distill.py +83 -37
  32. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_distill_cli.py +12 -5
  33. reprompt_cli-1.4.1/tests/test_distill_weights.py +96 -0
  34. reprompt_cli-1.4.1/tests/test_export.py +332 -0
  35. reprompt_cli-1.4.1/tests/test_export_cli.py +122 -0
  36. reprompt_cli-1.4.1/tests/test_export_snapshot.py +182 -0
  37. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_import_cli.py +7 -0
  38. reprompt_cli-1.4.1/tests/test_insights_expanded.py +140 -0
  39. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_parse_conversation_base.py +8 -4
  40. reprompt_cli-1.4.1/tests/test_source_filter.py +176 -0
  41. reprompt_cli-1.4.1/tests/test_style_trends.py +256 -0
  42. reprompt_cli-1.4.1/tests/test_suggestions.py +55 -0
  43. reprompt_cli-1.4.1/tests/test_template_cli.py +180 -0
  44. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/uv.lock +1 -1
  45. reprompt_cli-1.3.0/.testmondata +0 -0
  46. reprompt_cli-1.3.0/.testmondata-shm +0 -0
  47. reprompt_cli-1.3.0/.testmondata-wal +0 -0
  48. reprompt_cli-1.3.0/docs/roadmap.md +0 -74
  49. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/.editorconfig +0 -0
  50. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  51. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  52. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  53. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  54. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  55. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/.github/dependabot.yml +0 -0
  56. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/.github/workflows/ci.yml +0 -0
  57. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/.github/workflows/publish.yml +0 -0
  58. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/.gitignore +0 -0
  59. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/.pre-commit-config.yaml +0 -0
  60. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/CHANGELOG.md +0 -0
  61. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/CODE_OF_CONDUCT.md +0 -0
  62. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/CONTRIBUTING.md +0 -0
  63. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/LICENSE +0 -0
  64. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/README.md +0 -0
  65. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/SECURITY.md +0 -0
  66. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/action.yml +0 -0
  67. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/docs/launch-post.md +0 -0
  68. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/docs/superpowers/specs/2026-03-11-html-dashboard-design.md +0 -0
  69. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/docs/superpowers/specs/2026-03-11-merge-view-design.md +0 -0
  70. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/docs/superpowers/specs/2026-03-11-prompt-templates-design.md +0 -0
  71. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/docs/superpowers/specs/2026-03-22-prompt-compress-design.md +0 -0
  72. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/docs/superpowers/specs/2026-03-23-distill-design.md +0 -0
  73. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/module.yaml +0 -0
  74. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/scripts/generate_demo_data.py +0 -0
  75. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/scripts/launch/hn_monitor.py +0 -0
  76. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/scripts/launch/reddit_helper.py +0 -0
  77. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/adapters/__init__.py +0 -0
  78. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/adapters/aider.py +0 -0
  79. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/adapters/base.py +0 -0
  80. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/adapters/claude_chat.py +0 -0
  81. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/adapters/cline.py +0 -0
  82. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/adapters/cursor.py +0 -0
  83. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/adapters/filters.py +0 -0
  84. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/adapters/gemini.py +0 -0
  85. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/adapters/openclaw.py +0 -0
  86. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/bridge/__init__.py +0 -0
  87. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/bridge/handler.py +0 -0
  88. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/bridge/host.py +0 -0
  89. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/bridge/manifest.py +0 -0
  90. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/bridge/protocol.py +0 -0
  91. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/commands/__init__.py +0 -0
  92. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/commands/telemetry.py +0 -0
  93. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/commands/wrapped.py +0 -0
  94. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/config.py +0 -0
  95. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/core/__init__.py +0 -0
  96. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/core/analyzer.py +0 -0
  97. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/core/compress.py +0 -0
  98. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/core/dedup.py +0 -0
  99. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/core/effectiveness.py +0 -0
  100. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/core/extractors.py +0 -0
  101. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/core/extractors_zh.py +0 -0
  102. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/core/lang_detect.py +0 -0
  103. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/core/library.py +0 -0
  104. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/core/lint.py +0 -0
  105. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/core/merge_view.py +0 -0
  106. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/core/models.py +0 -0
  107. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/core/persona.py +0 -0
  108. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/core/pipeline.py +0 -0
  109. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/core/privacy.py +0 -0
  110. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/core/prompt_dna.py +0 -0
  111. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/core/recommend.py +0 -0
  112. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/core/scorer.py +0 -0
  113. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/core/segmenter.py +0 -0
  114. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/core/session_meta.py +0 -0
  115. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/core/templates.py +0 -0
  116. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/core/timeutil.py +0 -0
  117. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/core/wrapped.py +0 -0
  118. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/demo.py +0 -0
  119. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/embeddings/__init__.py +0 -0
  120. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/embeddings/base.py +0 -0
  121. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/embeddings/local_embed.py +0 -0
  122. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/embeddings/ollama.py +0 -0
  123. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/embeddings/openai_embed.py +0 -0
  124. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/embeddings/tfidf.py +0 -0
  125. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/mcp.py +0 -0
  126. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/mcp_main.py +0 -0
  127. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/output/__init__.py +0 -0
  128. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/output/chartjs.min.js +0 -0
  129. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/output/distill_terminal.py +0 -0
  130. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/output/html_report.py +0 -0
  131. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/output/json_out.py +0 -0
  132. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/output/markdown.py +0 -0
  133. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/output/wrapped_html.py +0 -0
  134. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/output/wrapped_terminal.py +0 -0
  135. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/py.typed +0 -0
  136. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/sharing/__init__.py +0 -0
  137. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/sharing/client.py +0 -0
  138. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/sharing/clipboard.py +0 -0
  139. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/storage/__init__.py +0 -0
  140. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/telemetry/__init__.py +0 -0
  141. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/telemetry/collector.py +0 -0
  142. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/telemetry/consent.py +0 -0
  143. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/telemetry/events.py +0 -0
  144. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/telemetry/prompt.py +0 -0
  145. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/telemetry/queue.py +0 -0
  146. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/src/reprompt/telemetry/sender.py +0 -0
  147. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/__init__.py +0 -0
  148. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/conftest.py +0 -0
  149. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/fixtures/aider_chat_history.md +0 -0
  150. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/fixtures/chatgpt_conversations.json +0 -0
  151. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/fixtures/claude_chat_export.json +0 -0
  152. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/fixtures/claude_session.jsonl +0 -0
  153. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/fixtures/cline_task/api_conversation_history.json +0 -0
  154. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/fixtures/gemini_session.json +0 -0
  155. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/fixtures/openclaw_session.jsonl +0 -0
  156. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_adapter_aider.py +0 -0
  157. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_adapter_chatgpt.py +0 -0
  158. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_adapter_claude.py +0 -0
  159. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_adapter_claude_chat.py +0 -0
  160. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_adapter_cline.py +0 -0
  161. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_adapter_gemini.py +0 -0
  162. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_adapter_openclaw.py +0 -0
  163. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_analyzer.py +0 -0
  164. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_bridge_cli.py +0 -0
  165. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_bridge_handler.py +0 -0
  166. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_bridge_integration.py +0 -0
  167. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_bridge_manifest.py +0 -0
  168. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_bridge_protocol.py +0 -0
  169. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_cli.py +0 -0
  170. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_cli_library_effectiveness.py +0 -0
  171. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_clipboard.py +0 -0
  172. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_compress_dna.py +0 -0
  173. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_compress_html.py +0 -0
  174. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_compress_insights.py +0 -0
  175. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_config.py +0 -0
  176. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_coverage_boost.py +0 -0
  177. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_cursor_adapter.py +0 -0
  178. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_db.py +0 -0
  179. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_db_digest.py +0 -0
  180. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_db_effectiveness.py +0 -0
  181. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_db_trends.py +0 -0
  182. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_dedup.py +0 -0
  183. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_demo.py +0 -0
  184. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_digest.py +0 -0
  185. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_digest_cli.py +0 -0
  186. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_e2e.py +0 -0
  187. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_effectiveness.py +0 -0
  188. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_embeddings_local.py +0 -0
  189. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_embeddings_ollama.py +0 -0
  190. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_embeddings_openai.py +0 -0
  191. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_empty_state.py +0 -0
  192. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_extractors.py +0 -0
  193. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_extractors_routing.py +0 -0
  194. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_extractors_zh.py +0 -0
  195. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_extractors_zh_e2e.py +0 -0
  196. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_html_report.py +0 -0
  197. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_import_e2e.py +0 -0
  198. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_insights.py +0 -0
  199. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_insights_cli.py +0 -0
  200. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_install_hook.py +0 -0
  201. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_lang_detect.py +0 -0
  202. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_library.py +0 -0
  203. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_lint.py +0 -0
  204. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_lint_cli.py +0 -0
  205. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_markdown.py +0 -0
  206. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_mcp.py +0 -0
  207. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_merge_view.py +0 -0
  208. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_models.py +0 -0
  209. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_output.py +0 -0
  210. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_parse_conversation_chatgpt.py +0 -0
  211. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_parse_conversation_claude.py +0 -0
  212. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_persona.py +0 -0
  213. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_pipeline.py +0 -0
  214. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_privacy.py +0 -0
  215. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_privacy_cli.py +0 -0
  216. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_privacy_e2e.py +0 -0
  217. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_privacy_output.py +0 -0
  218. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_prompt_dna.py +0 -0
  219. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_public_api.py +0 -0
  220. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_recommend.py +0 -0
  221. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_schema_version.py +0 -0
  222. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_score_cli.py +0 -0
  223. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_scorer.py +0 -0
  224. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_segmenter.py +0 -0
  225. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_share_e2e.py +0 -0
  226. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_sharing_client.py +0 -0
  227. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_style.py +0 -0
  228. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_telemetry_cli.py +0 -0
  229. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_telemetry_collector.py +0 -0
  230. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_telemetry_consent.py +0 -0
  231. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_telemetry_e2e.py +0 -0
  232. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_telemetry_events.py +0 -0
  233. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_telemetry_prompt.py +0 -0
  234. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_telemetry_queue.py +0 -0
  235. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_telemetry_sender.py +0 -0
  236. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_templates.py +0 -0
  237. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_timeutil.py +0 -0
  238. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_trends.py +0 -0
  239. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_trends_cli.py +0 -0
  240. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_use_cli.py +0 -0
  241. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_wrapped.py +0 -0
  242. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_wrapped_cli.py +0 -0
  243. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_wrapped_e2e.py +0 -0
  244. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_wrapped_html.py +0 -0
  245. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_wrapped_output.py +0 -0
  246. {reprompt_cli-1.3.0 → reprompt_cli-1.4.1}/tests/test_wrapped_share.py +0 -0
Binary file
@@ -18,7 +18,7 @@ uv run python -m build # build wheel
18
18
 
19
19
  ```
20
20
  src/reprompt/
21
- ├── cli.py # Typer CLI (scan, import, report, search, library, recommend, demo, status, purge, install-hook, install-extension, extension-status, score, compare, insights, digest, style, use, privacy, compress, distill) + plugin loading
21
+ ├── cli.py # Typer CLI (scan, import, report, search, library, recommend, demo, status, purge, install-hook, install-extension, extension-status, score, compare, insights, digest, style, template [save|list|use], privacy, compress, distill) + plugin loading
22
22
  ├── config.py # pydantic-settings, env vars (REPROMPT_ prefix) + TOML config
23
23
  ├── demo.py # Built-in demo data generator (no network required)
24
24
  ├── core/
@@ -41,6 +41,7 @@ src/reprompt/
41
41
  │ ├── wrapped.py # WrappedReport dataclass + build_wrapped(db) aggregation
42
42
  │ ├── privacy.py # Privacy metadata registry + exposure summary per adapter
43
43
  │ ├── compress.py # 4-layer prompt compression (char norm + phrase simplify + filler delete + structure cleanup)
44
+ │ ├── suggestions.py # Command journey suggestions ("→ Try:" hints for 5 core commands)
44
45
  │ ├── conversation.py # ConversationTurn, Conversation, DistillResult dataclasses
45
46
  │ └── distill.py # 6-signal importance scoring + filtering + summary generation
46
47
  ├── adapters/
@@ -123,7 +124,7 @@ reprompt-extension (private) ← Browser extension: Chrome/Firefox prompt capt
123
124
  - Pattern upsert (not clear+re-insert) for stable IDs
124
125
  - Prompts starting with `<` are filtered (system-injected XML)
125
126
  - Config: env vars (REPROMPT_ prefix) > TOML (~/.config/reprompt/config.toml) > defaults
126
- - Tests: pytest, 1217 tests, 95% coverage target
127
+ - Tests: pytest, 1295 tests, 95% coverage target
127
128
 
128
129
  ## Prompt Science Engine
129
130
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: reprompt-cli
3
- Version: 1.3.0
3
+ Version: 1.4.1
4
4
  Summary: Discover, analyze, and optimize your prompts from AI coding sessions
5
5
  Project-URL: Homepage, https://github.com/reprompt-dev/reprompt
6
6
  Project-URL: Repository, https://github.com/reprompt-dev/reprompt
@@ -0,0 +1,97 @@
1
+ # reprompt Roadmap
2
+
3
+ > Last updated: 2026-03-25 · Current version: v1.4.1
4
+
5
+ ## Vision
6
+
7
+ reprompt is the **prompt intelligence** tool for AI sessions — distill your conversations, compress your prompts, score them against research, and track your progress. Zero-config, privacy-first, CLI-first.
8
+
9
+ **Category definition:** reprompt analyzes *human inputs* (how you prompt), not *LLM outputs* (how models respond). Every other tool in the eval/observability space — Promptfoo, Braintrust, DeepEval, Langfuse — answers "did my AI system answer correctly?" reprompt answers "am I asking well?" This is an unoccupied category.
10
+
11
+ ---
12
+
13
+ ## Current State (v1.4.0) — Production Stable
14
+
15
+ ### Adapters (8)
16
+ Claude Code · OpenClaw · Cursor IDE · Aider · Gemini CLI · Cline · ChatGPT · Claude.ai
17
+
18
+ ### Commands (23 visible, 5 deprecated)
19
+ `scan` · `import` · `report` · `library` · `trends` · `recommend` · `template [save|list|use]` · `lint` · `search` · `demo` · `status` · `purge` · `install-hook` · `install-extension` · `extension-status` · `score` · `compare` · `insights` · `digest` · `style` · `wrapped` · `telemetry` · `mcp-serve` · `compress` · `distill` · `privacy`
20
+
21
+ ### Integrations
22
+ - MCP server (`reprompt mcp-serve`) for IDE integration
23
+ - GitHub Action (`action.yml`) for CI prompt quality checks
24
+ - HTML dashboard (`reprompt report --html`)
25
+ - Browser extension (Chrome/Firefox) via Native Messaging bridge
26
+ - JSON output on all commands for pipeline integration
27
+
28
+ ### Key Features by Version
29
+
30
+ | Version | Feature | Description |
31
+ |---------|---------|-------------|
32
+ | v1.0.0 | Core platform | Scoring, dedup, report, trends, digest, style, effectiveness, templates, MCP, HTML dashboard |
33
+ | v1.1.0 | Privacy exposure | `reprompt privacy` — where your prompts went, training risk analysis |
34
+ | v1.2.0 | Prompt compression | `reprompt compress` — 4-layer rule-based compression (43 zh + 51 en rules) |
35
+ | v1.3.0 | Conversation distillation | `reprompt distill` — 6-signal importance scoring for conversation turns |
36
+ | v1.3.1 | UX polish | Actionable suggestions on 5 commands, `--source` filter on all data commands |
37
+ | v1.4.0 | Context recovery + consolidation | `distill --export` context document, signal transparency, command consolidation (27→23) |
38
+ | v1.4.1 | Compare + style polish | `compare --best-worst` auto-pick, `style --trends` period-over-period deltas |
39
+
40
+ ### Quality
41
+ - 1316 tests, ≥90% coverage
42
+ - Strict mypy, ruff lint/format
43
+ - CI: coverage gate + pre-publish test step
44
+ - Stable public API (`score_prompt`, `compare_prompts`, `extract_features`)
45
+
46
+ ---
47
+
48
+ ## v1.4 — Context Recovery + Command Consolidation
49
+
50
+ | Priority | Item | Rationale |
51
+ |----------|------|-----------|
52
+ | P1 | `distill --export` context recovery | **DONE** — community signal: resume sessions after compaction/timeout |
53
+ | P2 | Command consolidation: `save`/`templates`/`use` → `template [save\|list\|use]` | **DONE** — 3 commands doing 1 thing = cognitive overload |
54
+ | P2 | Command consolidation: `effectiveness`/`merge-view` → `insights` sub-insights | **DONE** — concepts unclear to users |
55
+ | P3 | `style` shows change trends | **DONE** — `--trends` flag with period-over-period deltas |
56
+ | P4 | `distill --show-weights` / `--weights` signal transparency | Community request for weight visibility |
57
+ | P5 | `compare --best-worst` auto-pick | **DONE** — auto-selects from DB scores |
58
+ | P5 | `--copy` as standard option on remaining commands | Decided against — no clear paste destination for analysis commands |
59
+
60
+ **Status: 27 → 23 visible commands. P1+P2+P3+P5 shipped.**
61
+
62
+ ---
63
+
64
+ ## v1.5+ — Future Work
65
+
66
+ | Feature | Description |
67
+ |---------|-------------|
68
+ | Distill false positive reduction | Position signal breaks on small-talk openers / "thanks bye" closers; long error dumps score high on length+uniqueness but aren't decision points; "ok try again" triggers error_recovery but is noise. Community feedback from r/LLMDevs. |
69
+ | Sensitive content detection | Privacy narrative; PII in prompts |
70
+ | Agent workflow analysis | Multi-step agent session patterns |
71
+ | `.reprompt.yml` configurable lint | Team/Pro direction |
72
+ | `reprompt suggest` (Ollama rewrite) | LLM-powered prompt improvement |
73
+ | Homebrew formula | `brew install reprompt` |
74
+ | More adapters | Perplexity, Mistral, Grok, Gemini Takeout |
75
+ | Windows Native Messaging | Extension support on Windows |
76
+
77
+ ---
78
+
79
+ ## Architecture Principles
80
+
81
+ 1. **Zero-config first** — Every feature works without LLM by default
82
+ 2. **Privacy by design** — All data stays local; extension has zero server
83
+ 3. **Adapter pattern** — New AI tools supported by adding ~50 lines
84
+ 4. **Input not output** — We analyze human prompts (inputs); LLM eval tools analyze model responses (outputs)
85
+ 5. **CLI first, GUI second** — Terminal is primary, HTML dashboard is secondary
86
+ 6. **Composable** — Every command supports JSON output for piping
87
+
88
+ ---
89
+
90
+ ## How to Contribute
91
+
92
+ - **New adapter** (~50 lines) — see `src/reprompt/adapters/base.py`
93
+ - **New lint rules** — see `src/reprompt/core/lint.py`
94
+ - **Better categorization** — improve keyword rules in `core/library.py`
95
+ - **Browser extension** — see `reprompt-extension` repo
96
+
97
+ See [CONTRIBUTING.md](../CONTRIBUTING.md) for details.
@@ -0,0 +1,179 @@
1
+ # v1.3.1 — Actionable Suggestions + `--source` Consistency
2
+
3
+ ## Goal
4
+
5
+ Two improvements: (1) guide users to the next useful command after each analysis, (2) make `--source` filtering available on all data-querying commands.
6
+
7
+ ## P2: Actionable Suggestions
8
+
9
+ ### Problem
10
+
11
+ Commands show data but don't tell users what to do next. New users run `reprompt scan`, see results, and don't know to try `reprompt report` or `reprompt insights`. The "展示 → 行动" gap reduces retention.
12
+
13
+ ### Design
14
+
15
+ A single dim "Next step" line appended to 5 core commands:
16
+
17
+ | Command | Suggestion |
18
+ |---------|-----------|
19
+ | `scan` | `reprompt report (see results) · reprompt insights (personal patterns)` |
20
+ | `report` | `reprompt insights (patterns) · reprompt distill --last (session review)` |
21
+ | `score` | `reprompt compress "..." (optimize) · reprompt insights (all patterns)` |
22
+ | `insights` | `reprompt compress "..." (verbose prompts) · reprompt distill --last (sessions)` |
23
+ | `distill` | `reprompt compress "..." (shorten turns) · reprompt report (full analytics)` |
24
+
25
+ ### Implementation
26
+
27
+ **New file:** `src/reprompt/core/suggestions.py`
28
+
29
+ ```python
30
+ """Command journey suggestions — guide users to the next useful action."""
31
+
32
+ from __future__ import annotations
33
+
34
+ SUGGESTIONS: dict[str, str] = {
35
+ "scan": "reprompt report (see results) · reprompt insights (personal patterns)",
36
+ "report": "reprompt insights (patterns) · reprompt distill --last (session review)",
37
+ "score": 'reprompt compress "..." (optimize) · reprompt insights (all patterns)',
38
+ "insights": 'reprompt compress "..." (verbose prompts) · reprompt distill --last (sessions)',
39
+ "distill": 'reprompt compress "..." (shorten turns) · reprompt report (full analytics)',
40
+ }
41
+
42
+
43
+ def get_suggestion(command: str) -> str | None:
44
+ """Return the suggestion line for a command, or None."""
45
+ return SUGGESTIONS.get(command)
46
+ ```
47
+
48
+ **CLI integration pattern** (same for all 5 commands):
49
+
50
+ ```python
51
+ # At the end of the command function, before return:
52
+ from reprompt.core.suggestions import get_suggestion
53
+ hint = get_suggestion("command_name")
54
+ if hint and not json_output:
55
+ console.print(f"\n [dim]→ Try: {hint}[/dim]")
56
+ ```
57
+
58
+ ### Display Rules
59
+
60
+ - Only in terminal mode — suppressed when `--json` or `--copy` is used
61
+ - `[dim]` Rich styling — visible but not distracting
62
+ - Not shown when the command produces no output (e.g. `scan` with 0 new sessions, `distill` with no sessions found)
63
+ - Single line — power users can ignore it instantly
64
+
65
+ ### `scan` Conflict Resolution
66
+
67
+ `scan` already has a "Try next" block (cli.py:109-114) that shows when new prompts are imported and the DB is small. The new suggestion line must NOT duplicate this. Rule: **only show the dim suggestion when the existing "Try next" block does NOT fire** — i.e. when `result.new_stored == 0` or the DB already has substantial data.
68
+
69
+ ### Why Only 5 Commands
70
+
71
+ These are the commands users hit in their first session and on return visits. Adding suggestions to all 27 commands would be noise. The 5 form a natural discovery loop:
72
+
73
+ ```
74
+ scan → report → insights → compress/distill → report (loop)
75
+ ```
76
+
77
+ ## P3: `--source` Filter Consistency
78
+
79
+ ### Problem
80
+
81
+ `report`, `search`, `scan`, `lint`, `distill` support `--source` to filter by adapter. But `insights`, `trends`, `digest`, `style` don't — users with multiple tools (e.g. Claude Code + Cursor) can't analyze them separately.
82
+
83
+ ### Current State
84
+
85
+ | Has `--source` | Missing (should have) | N/A (single-prompt commands) |
86
+ |---|---|---|
87
+ | `scan`, `report`, `search`, `lint`, `distill` | `insights`, `trends`, `digest`, `style` | `score`, `compare`, `compress`, `privacy` |
88
+
89
+ ### Design
90
+
91
+ Add `--source` / `-s` to the 4 missing commands. Each uses existing DB query functions that already support source filtering, except `get_all_features()`.
92
+
93
+ #### DB Change: `get_all_features(source=None)`
94
+
95
+ ```python
96
+ def get_all_features(self, source: str | None = None) -> list[dict[str, Any]]:
97
+ """Return all stored feature vectors, optionally filtered by source."""
98
+ conn = self._conn()
99
+ try:
100
+ if source:
101
+ rows = conn.execute(
102
+ """SELECT pf.features_json FROM prompt_features pf
103
+ JOIN prompts p ON pf.prompt_hash = p.hash
104
+ WHERE p.source = ?
105
+ ORDER BY pf.overall_score DESC""",
106
+ (source,),
107
+ ).fetchall()
108
+ else:
109
+ rows = conn.execute(
110
+ "SELECT features_json FROM prompt_features ORDER BY overall_score DESC"
111
+ ).fetchall()
112
+ return [json.loads(r["features_json"]) for r in rows]
113
+ finally:
114
+ conn.close()
115
+ ```
116
+
117
+ #### Per-Command Changes
118
+
119
+ | Command | Data function | Change needed |
120
+ |---------|--------------|---------------|
121
+ | `insights` | `db.get_all_features()` | Add `source` CLI param, pass to `get_all_features(source=)` |
122
+ | `style` | `db.get_all_prompts()` | Add `source` CLI param, pass to `get_all_prompts(source=)` (NOTE: `style` uses `get_all_prompts`, not `get_all_features`) |
123
+ | `trends` | `db.get_all_prompts()` | `get_all_prompts()` already accepts `source` — add CLI param and pass through |
124
+ | `digest` | `build_digest()` → `compute_window_snapshot()` → `db.get_prompts_in_range()` | Full call chain needs `source` threaded through (see below) |
125
+
126
+ #### `digest` Call Chain Fix
127
+
128
+ `digest` has a 3-function call chain that all need `source` added:
129
+
130
+ ```
131
+ CLI digest(source=) → build_digest(db, period, source=) → compute_window_snapshot(db, window, period, source=) → db.get_prompts_in_range(start, end, source=)
132
+ ```
133
+
134
+ **Files to modify:**
135
+ - `src/reprompt/core/digest.py`: add `source: str | None = None` param to `build_digest()`, pass to `compute_window_snapshot()`
136
+ - `src/reprompt/core/trends.py`: add `source: str | None = None` param to `compute_window_snapshot()`, pass to `db.get_prompts_in_range()`
137
+ - `db.get_prompts_in_range()` already accepts `source` — no change needed
138
+
139
+ **Digest log edge case:** When `source` is set, skip `db.log_digest()` — a source-filtered digest run should not overwrite the unfiltered digest history.
140
+
141
+ #### CLI Parameter Pattern
142
+
143
+ Standardize on `None` default (matching `distill`), not empty string:
144
+ ```python
145
+ source: str | None = typer.Option(
146
+ None, "--source", "-s", help="Filter by source (e.g. claude-code, cursor, aider)"
147
+ )
148
+ ```
149
+
150
+ ## Files Changed
151
+
152
+ | File | Action | What |
153
+ |------|--------|------|
154
+ | `src/reprompt/core/suggestions.py` | Create | Suggestion map + `get_suggestion()` |
155
+ | `src/reprompt/storage/db.py` | Modify | Add `source` param to `get_all_features()` |
156
+ | `src/reprompt/core/digest.py` | Modify | Add `source` param to `build_digest()` |
157
+ | `src/reprompt/core/trends.py` | Modify | Add `source` param to `compute_window_snapshot()` |
158
+ | `src/reprompt/cli.py` | Modify | Suggestions on 5 commands + `--source` on 4 commands |
159
+ | `tests/test_suggestions.py` | Create | Suggestion map tests |
160
+ | `tests/test_source_filter.py` | Create | `--source` CLI + behavioral tests (seeded DB with 2 sources) |
161
+
162
+ ## DB Changes
163
+
164
+ **None.** No schema changes, no migrations. Only a query modification in `get_all_features()`.
165
+
166
+ ## Testing Strategy
167
+
168
+ | Test file | Coverage |
169
+ |-----------|----------|
170
+ | `tests/test_suggestions.py` | All 5 commands return suggestions, unknown command returns None, suggestions contain valid command names |
171
+ | `tests/test_source_filter.py` | CLI `--source` flag on insights/trends/digest/style (`--help` shows flag), behavioral test with seeded DB (2 sources, verify filtered count != total count), `get_all_features(source=)` JOIN returns correct subset, digest source-filtered run skips log_digest |
172
+
173
+ ## Success Criteria
174
+
175
+ 1. `reprompt report` ends with a dim suggestion line pointing to `insights` and `distill`
176
+ 2. `reprompt insights --source claude-code` shows patterns only from Claude Code sessions
177
+ 3. `reprompt style --source cursor` shows style fingerprint from Cursor-only prompts
178
+ 4. Suggestions suppressed in `--json` mode
179
+ 5. Zero regressions in existing tests
@@ -0,0 +1,342 @@
1
+ # v1.4 Design Spec: Context Recovery + Consolidation
2
+
3
+ > **Version:** v1.4.0
4
+ > **Date:** 2026-03-24
5
+ > **Status:** Draft
6
+ > **Community signal:** pvdyck (r/ClaudeAI), LLMDevs commenters, LeadingFarmer3923 (r/ClaudeAI)
7
+
8
+ ---
9
+
10
+ ## Problem
11
+
12
+ AI coding sessions lose context through compaction, timeouts, and tool-switching. Users are forced to re-explain what they were doing, what decisions were made, and where they left off. This is a daily pain point for every Claude Code, Cursor, and Aider power user.
13
+
14
+ No tool produces a structured, portable, human-readable distillation of a coding session optimized for re-injection into a new session.
15
+
16
+ ## Solution
17
+
18
+ Add `--export` flag to the existing `reprompt distill` command. Produces a markdown context document designed to be pasted into any AI tool as session resumption context.
19
+
20
+ ```bash
21
+ # Primary workflow
22
+ reprompt distill --last 1 --export | pbcopy
23
+ # → paste into new Claude Code / Cursor / ChatGPT session
24
+
25
+ # With clipboard shortcut
26
+ reprompt distill --last 1 --export --copy
27
+
28
+ # Full mode (includes assistant responses)
29
+ reprompt distill --last 1 --export --full
30
+ ```
31
+
32
+ ## Design Principles
33
+
34
+ 1. **Generic markdown** — works in any AI tool, not coupled to one platform
35
+ 2. **User turns only** by default — the goal is "what the human decided and did," not replaying the conversation
36
+ 3. **~500 tokens default** — fits comfortably in any context window alongside other context
37
+ 4. **Lost-in-the-Middle aware** — actionable sections at top and bottom, reference material in the middle (Stanford 2307.03172, MIT 2025 follow-up)
38
+ 5. **Cache-friendly header** — stable identifiers first, volatile metadata second (arXiv 2601.06007)
39
+ 6. **Zero-config** — no LLM required, rule-based extraction from existing distill engine
40
+
41
+ ## Export Document Structure
42
+
43
+ ```markdown
44
+ # Session Context: <project>
45
+
46
+ **Source:** <adapter> | **Date:** <YYYY-MM-DD> | **Duration:** <N>min
47
+ **Turns:** <total> → <kept> key turns | **~<N> tokens**
48
+
49
+ ## Goal
50
+
51
+ <first user turn, compressed via compress_text()>
52
+
53
+ ## Current State
54
+
55
+ <last high-importance user turn, compressed>
56
+
57
+ ## Key Decisions
58
+
59
+ 1. <turn with high semantic_shift — why a choice was made>
60
+ 2. <turn with high semantic_shift — why a choice was made>
61
+ 3. ...
62
+
63
+ ## What Was Done
64
+
65
+ - <turn with high tool_trigger — what was implemented/changed>
66
+ - ...
67
+
68
+ ## Files Changed
69
+
70
+ `file1.py`, `file2.py`, `file3.py`
71
+
72
+ ## Resume
73
+
74
+ <last turn with forward-looking intent, if detected; omitted otherwise>
75
+ ```
76
+
77
+ ### Section Design Details
78
+
79
+ #### Header
80
+ - Project name first (stable, cache-friendly), volatile metadata on second line.
81
+ - Token count is approximate: `len(output) // 4`. No external tokenizer dependency.
82
+
83
+ #### Goal
84
+ - Source: first user turn (`user_turns[0]`), processed through `compress_text()`.
85
+ - Truncated to 200 chars max.
86
+ - Always present (every conversation has a first turn).
87
+
88
+ #### Current State
89
+ - Source: last user turn with `importance >= threshold`, compressed.
90
+ - Represents where the session ended up, not where it started.
91
+ - If same as Goal (single-turn session), this section is omitted.
92
+
93
+ #### Key Decisions
94
+ - Source: user turns sorted by `semantic_shift` signal (descending), top 5.
95
+ - These are turns where the user changed direction or made a choice.
96
+ - Each entry compressed and truncated to 150 chars.
97
+ - Deduplicated against Goal and Current State (no repeats).
98
+
99
+ #### What Was Done
100
+ - Source: user turns sorted by `tool_trigger` signal (descending), top 5.
101
+ - These are turns that caused the most tool activity (implementation work).
102
+ - Each entry compressed and truncated to 150 chars.
103
+ - Deduplicated against Key Decisions (a turn appears in only one section).
104
+
105
+ #### Files Changed
106
+ - Source: existing `_extract_files_changed()` from distill engine.
107
+ - Displayed as inline code, comma-separated. Max 10 files shown (aligned with existing `generate_summary()` cap).
108
+
109
+ #### Resume
110
+ - Source: last 3 user turns, checked for forward-looking keywords.
111
+ - Keywords: `next`, `todo`, `now let's`, `then`, `after that`, `move on`, `接下来`, `然后`, `下一步`.
112
+ - If no forward-looking turn found, section is omitted entirely.
113
+ - Not fabricated — only extracted from actual user text.
114
+
115
+ ### Turn Classification Logic
116
+
117
+ A user turn's primary section is determined by its highest-scoring signal:
118
+
119
+ | Highest signal | Section |
120
+ |---------------|---------|
121
+ | `semantic_shift` | Key Decisions |
122
+ | `tool_trigger` | What Was Done |
123
+ | Both equal | Key Decisions (decision > action) |
124
+
125
+ Turns used for Goal, Current State, or Resume are excluded from both lists to avoid repetition.
126
+
127
+ ## `--full` Mode
128
+
129
+ When `--full` is passed, each user turn in Key Decisions and What Was Done includes the paired assistant response summary:
130
+
131
+ ```markdown
132
+ ## Key Decisions
133
+
134
+ 1. **User:** Used TF-IDF cosine distance for semantic_shift instead of embeddings
135
+ **Result:** Implemented in `_compute_semantic_signals()`, 4 helper functions added
136
+ ```
137
+
138
+ Assistant response is summarized as: first sentence of the response text, or "N tool calls, M files changed" if the response is primarily tool use. This roughly doubles token count (~1000-1500 tokens).
139
+
140
+ ## Weight Transparency Flags
141
+
142
+ Two separate flags (Typer does not support a single option that acts as both bool flag and string option):
143
+
144
+ ```bash
145
+ # Show current weights
146
+ reprompt distill --show-weights
147
+ # position=0.15, length=0.15, tool_trigger=0.20,
148
+ # error_recovery=0.15, semantic_shift=0.20, uniqueness=0.15
149
+
150
+ # Override weights (advanced)
151
+ reprompt distill --last 1 --export --weights "semantic_shift=0.4,tool_trigger=0.3"
152
+ ```
153
+
154
+ **`--show-weights`** (bool flag): Prints current signal weights and exits. Ignores all other flags.
155
+
156
+ **`--weights TEXT`** (string option): Parses comma-separated `key=value` pairs, merges with defaults for unspecified keys. Validation:
157
+ - Unknown keys (typos like `tool_tigger`) → error with "unknown weight key" message listing valid keys
158
+ - Sum != 1.0 → warning printed to stderr, execution continues
159
+ - Override applies to this invocation only, does not persist
160
+
161
+ ## Open/Pro Boundary
162
+
163
+ | Feature | Layer | Rationale |
164
+ |---------|-------|-----------|
165
+ | `--export` markdown output | **Open** | Rule-based, zero-config, individual tool |
166
+ | `--full` user+assistant pairs | **Open** | Same data, different format |
167
+ | `--weights` transparency | **Open** | Transparency builds trust |
168
+ | LLM-powered semantic summary | **Pro** | Requires Ollama, clear upgrade path |
169
+ | Cross-session memory ("what did I discuss about auth across 100 sessions?") | **Pro** | Needs persistent index + embeddings |
170
+
171
+ If Pro plugin is installed, `--export --summary` uses LLM to produce a condensed 3-sentence brief instead of rule-based extraction. Graceful degradation message if Pro is not installed.
172
+
173
+ ## Architecture
174
+
175
+ ### New Files
176
+
177
+ | File | Purpose | ~Lines |
178
+ |------|---------|--------|
179
+ | `output/export.py` | `generate_export(result, full=False) → str` | ~120 |
180
+
181
+ ### Modified Files
182
+
183
+ | File | Change |
184
+ |------|--------|
185
+ | `cli.py` | Add `--export`, `--full`, `--show-weights`, `--weights` flags to `distill` command |
186
+ | `core/distill.py` | Expose per-signal scores on `ConversationTurn` for section classification; accept optional `weights` dict |
187
+ | `core/conversation.py` | Add `signal_scores: dict[str, float]` field to `ConversationTurn` |
188
+ | `core/suggestions.py` | Update distill suggestion to mention `--export` |
189
+
190
+ ### Data Flow
191
+
192
+ ```
193
+ Session files → Adapter.parse_conversation() → Conversation
194
+ → distill_conversation(conv, threshold, weights?) → DistillResult
195
+ (turns now have per-signal scores in signal_scores dict)
196
+ → generate_export(result, full=False) → str (markdown)
197
+ → stdout / clipboard / file
198
+ ```
199
+
200
+ ### Key Implementation Details
201
+
202
+ 1. **Per-signal scores on ConversationTurn:** Currently `importance` is a single float (weighted sum). To classify turns into "Key Decisions" vs "What Was Done," we need access to individual signal scores. Add `signal_scores: dict[str, float] = field(default_factory=dict)` to `ConversationTurn`. Populate during scoring inside `distill_conversation()`:
203
+
204
+ ```python
205
+ # Inside the user turn scoring loop (after computing all 6 scores):
206
+ user_turn.signal_scores = {
207
+ "position": pos_score,
208
+ "length": len_score,
209
+ "tool_trigger": tool_score,
210
+ "error_recovery": error_score,
211
+ "semantic_shift": shift_score,
212
+ "uniqueness": unique_score,
213
+ }
214
+ user_turn.importance = (
215
+ weights["position"] * pos_score
216
+ + weights["length"] * len_score
217
+ + ...
218
+ )
219
+ ```
220
+
221
+ 2. **`distill_conversation()` new signature:**
222
+
223
+ ```python
224
+ def distill_conversation(
225
+ conversation: Conversation,
226
+ threshold: float = 0.3,
227
+ weights: dict[str, float] | None = None,
228
+ ) -> DistillResult:
229
+ ```
230
+
231
+ When `weights` is None, use the existing `W_*` module constants as defaults. When provided, merge: `effective = {**DEFAULT_WEIGHTS, **weights}`. Unknown keys are already rejected at the CLI layer (see `--weights` validation).
232
+
233
+ 3. **Forward-looking detection for Resume:** Simple keyword match on last 3 high-importance user turns. Bilingual (en + zh). No NLP dependency.
234
+
235
+ 4. **Token estimation:** `len(output_text) // 4` — rough but sufficient. No external tokenizer.
236
+
237
+ 5. **Deduplication across sections:** Goal turn, Current State turn, and Resume turn are tracked by `turn_index`. Excluded from Key Decisions and What Was Done candidate pools.
238
+
239
+ 6. **`--full` mode assistant summary:** An assistant turn is "primarily tool use" when `tool_calls > 0 and len(text.strip()) < 200`. In that case, summarize as `"{N} tool calls, {M} files changed"`. Otherwise, use the first sentence of the response text (split on `. ` or `\n`, take first element, truncate to 150 chars).
240
+
241
+ 7. **`--export` restricted to single session:** `--export` requires `--last 1` (or a specific session_id). If `--last N` with N > 1 is combined with `--export`, print error: `"--export works with a single session. Use --last 1 or specify a session ID."` and exit.
242
+
243
+ 8. **`--export --json` envelope:** Outputs `{"export": "<markdown string>", "session_id": "...", "source": "...", "tokens": N}`. The markdown is a single string field, not the raw DistillResult.
244
+
245
+ 9. **Empty filtered_turns fallback:** When `filtered_turns` is empty (threshold too high), `generate_export()` falls back to a minimal document using the first and last raw user turns from `conversation.turns`, with a note: `"(No turns above threshold {threshold}. Showing first and last turns.)"`.
246
+
247
+ 10. **Suggestions update:** Replace the `distill` entry in `SUGGESTIONS` dict (`core/suggestions.py` line 10) with: `'reprompt distill --export --copy (context recovery) · reprompt compress "..." (shorten turns)'`. This replaces the current `report` hint (less relevant after distill) with the new `--export` hint, keeping `compress` as the second option.
248
+
249
+ 11. **`--full` without `--export` warning:** If `--full` is passed without `--export`, print a warning to stderr: `"--full has no effect without --export"` and continue normally. Do not error.
250
+
251
+ ## CLI Interface
252
+
253
+ ```
254
+ reprompt distill [SESSION_ID] [OPTIONS]
255
+
256
+ Existing flags (unchanged):
257
+ --last N Distill N most recent sessions (default: 1)
258
+ --source TEXT Filter by adapter name
259
+ --summary Show compressed summary
260
+ --json Output as JSON
261
+ --copy Copy to clipboard
262
+ --threshold FLOAT Importance cutoff 0.0-1.0 (default: 0.3)
263
+
264
+ New flags (v1.4):
265
+ --export Output as markdown context document for session resumption
266
+ --full Include assistant responses in export (requires --export)
267
+ --show-weights Print current signal weights and exit
268
+ --weights TEXT Override signal weights, e.g. "semantic_shift=0.4,tool_trigger=0.3"
269
+ ```
270
+
271
+ Flag interactions:
272
+ - `--export` and `--summary` are mutually exclusive (both produce text, different formats)
273
+ - `--export` requires single session: `--last 1` or a session_id. Error if `--last N` with N > 1.
274
+ - `--export --json` outputs `{"export": "<markdown>", "session_id": "...", "source": "...", "tokens": N}`
275
+ - `--export --copy` copies the markdown to clipboard
276
+ - `--full` without `--export` is ignored (only affects export format)
277
+ - `--show-weights` prints weights and exits (ignores all other flags)
278
+ - `--weights "k=v,..."` overrides weights for the current invocation; unknown keys → error
279
+
280
+ ## v1.4 Full Scope (Context Recovery + Consolidation)
281
+
282
+ | Priority | Item | Type |
283
+ |----------|------|------|
284
+ | **P1** | `distill --export` context recovery | New feature |
285
+ | **P2** | Command consolidation: `save`/`templates`/`use` → `template [save\|list\|use]` | UX cleanup |
286
+ | **P2** | Command consolidation: `effectiveness`/`merge-view` → subcommands of `insights` | UX cleanup |
287
+ | **P3** | `style` change trends ("specificity +12% this week") | Enhancement |
288
+ | **P4** | `distill --weights` signal transparency | Enhancement |
289
+ | **P5** | `compare --best-worst` auto-pick | Enhancement |
290
+ | **P5** | `--copy` as standard option on remaining commands | Consistency |
291
+
292
+ **Target: 27 → ~21 commands after consolidation. 1 new flag (`--export`), not 1 new command.**
293
+
294
+ ## Testing Strategy
295
+
296
+ | Layer | Tests | What |
297
+ |-------|-------|------|
298
+ | Unit | ~20 | `generate_export()` with various DistillResult shapes (empty, single turn, many turns, no forward-looking, etc.) |
299
+ | Unit | ~10 | Per-signal score classification (semantic_shift dominant → Key Decisions, tool_trigger dominant → What Was Done) |
300
+ | Unit | ~5 | Forward-looking keyword detection (en + zh) |
301
+ | Unit | ~5 | `--weights` parsing and validation |
302
+ | Unit | ~5 | Token estimation accuracy |
303
+ | Integration | ~5 | `distill --export` end-to-end through CLI |
304
+ | Integration | ~3 | `--export --full` vs default comparison |
305
+ | Integration | ~2 | `--export --copy` clipboard integration |
306
+ | Unit | ~3 | Empty filtered_turns fallback behavior |
307
+ | Snapshot | ~3 | Golden file tests for export format stability (fixtures in `tests/fixtures/export/`) |
308
+
309
+ **~61 new tests. Target: 1298+ total (currently 1237).**
310
+
311
+ ### Snapshot Test Strategy
312
+
313
+ Golden file fixtures live in `tests/fixtures/export/`. Each fixture is a `.md` file containing the expected export output for a specific DistillResult shape. Tests compare `generate_export()` output against these files. When the export format intentionally changes, fixtures are regenerated with `pytest --update-snapshots` (custom marker).
314
+
315
+ ## Competitive Position
316
+
317
+ | Tool | What it does | How reprompt differs |
318
+ |------|-------------|---------------------|
319
+ | continues (`npx continues`) | Cross-tool session handoff (14 tools) | reprompt adds *importance scoring* — not all turns are equal |
320
+ | claude-session-restore | Rust-based extraction of everything | reprompt extracts *what matters*, not everything |
321
+ | open-mem | LLM-compressed tool outputs | reprompt is rule-based, zero-config, tool-agnostic |
322
+ | Cline Memory Bank | Persistent project memory across tasks | reprompt is retrospective analysis, not live state |
323
+ | Cognetivy | Structured prompt creation templates | Complementary: Cognetivy = before, reprompt = after |
324
+
325
+ **Unique value:** reprompt is the only tool that produces an importance-scored, research-calibrated, portable context recovery document from any AI coding session without requiring an LLM.
326
+
327
+ ## Success Criteria
328
+
329
+ 1. `reprompt distill --last 1 --export` produces a markdown document under 600 tokens for a typical 50-turn session
330
+ 2. The document, when pasted into a new AI session, gives the model enough context to continue the previous task without the user re-explaining
331
+ 3. Export format is stable (golden file tests prevent accidental changes)
332
+ 4. Works with all 8 adapters that support `parse_conversation()`
333
+
334
+ ## References
335
+
336
+ - Stanford "Lost in the Middle" (arXiv 2307.03172) — U-shaped attention, critical info at top/bottom
337
+ - "Don't Break the Cache" (arXiv 2601.06007) — stable prefixes for prompt caching
338
+ - Anthropic Context Engineering Guide — compaction + structured notes pattern
339
+ - OpenAI GPT-4.1 Prompting Guide — section ordering best practices
340
+ - Cline new_task tool — structured handoff format (Completed/Current/Next)
341
+ - td (marcus/td) — minimalist handoff: done/remaining/decisions/uncertain
342
+ - CONTINUITY (duke-of-beans) — decisions as first-class objects