reprompt-cli 1.9.1__tar.gz → 2.0.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 (300) hide show
  1. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/PKG-INFO +51 -16
  2. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/README.md +50 -15
  3. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/pyproject.toml +1 -1
  4. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/__init__.py +1 -1
  5. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/cli.py +111 -0
  6. reprompt_cli-2.0.0/src/reprompt/core/rewrite.py +221 -0
  7. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/core/suggestions.py +2 -0
  8. reprompt_cli-2.0.0/src/reprompt/output/rewrite_terminal.py +69 -0
  9. reprompt_cli-2.0.0/tests/test_init_cli.py +80 -0
  10. reprompt_cli-2.0.0/tests/test_rewrite.py +157 -0
  11. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_suggestions.py +4 -0
  12. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/uv.lock +1 -1
  13. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/.editorconfig +0 -0
  14. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  15. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  16. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  17. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  18. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  19. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/.github/dependabot.yml +0 -0
  20. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/.github/workflows/ci.yml +0 -0
  21. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/.github/workflows/publish.yml +0 -0
  22. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/.gitignore +0 -0
  23. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/.pre-commit-config.yaml +0 -0
  24. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/.pre-commit-hooks.yaml +0 -0
  25. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/.testmondata-shm +0 -0
  26. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/.testmondata-wal +0 -0
  27. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/CHANGELOG.md +0 -0
  28. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/CODE_OF_CONDUCT.md +0 -0
  29. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/CONTRIBUTING.md +0 -0
  30. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/LICENSE +0 -0
  31. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/SECURITY.md +0 -0
  32. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/Screenshot 2026-03-24 at 09.45.03.png +0 -0
  33. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/action.yml +0 -0
  34. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/docs/demo.gif +0 -0
  35. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/docs/icons/brand-icon-128.png +0 -0
  36. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/docs/icons/brand-icon-16.png +0 -0
  37. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/docs/icons/brand-icon-256.png +0 -0
  38. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/docs/icons/brand-icon-32.png +0 -0
  39. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/docs/icons/brand-icon-48.png +0 -0
  40. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/docs/icons/brand-icon-512.png +0 -0
  41. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/docs/icons/brand-icon-96.png +0 -0
  42. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/docs/icons/brand-icon.svg +0 -0
  43. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/docs/icons/cli-favicon-128.png +0 -0
  44. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/docs/icons/cli-favicon-16.png +0 -0
  45. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/docs/icons/cli-favicon-256.png +0 -0
  46. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/docs/icons/cli-favicon-32.png +0 -0
  47. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/docs/icons/cli-favicon-48.png +0 -0
  48. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/docs/icons/cli-favicon-512.png +0 -0
  49. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/docs/icons/cli-favicon-96.png +0 -0
  50. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/docs/icons/cli-favicon.svg +0 -0
  51. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/docs/icons/cli-icon-128.png +0 -0
  52. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/docs/icons/cli-icon-16.png +0 -0
  53. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/docs/icons/cli-icon-256.png +0 -0
  54. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/docs/icons/cli-icon-32.png +0 -0
  55. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/docs/icons/cli-icon-48.png +0 -0
  56. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/docs/icons/cli-icon-512.png +0 -0
  57. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/docs/icons/cli-icon-96.png +0 -0
  58. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/docs/icons/cli-icon.svg +0 -0
  59. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/docs/icons/favicon-128.png +0 -0
  60. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/docs/icons/favicon-16.png +0 -0
  61. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/docs/icons/favicon-256.png +0 -0
  62. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/docs/icons/favicon-32.png +0 -0
  63. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/docs/icons/favicon-48.png +0 -0
  64. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/docs/icons/favicon-512.png +0 -0
  65. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/docs/icons/favicon-96.png +0 -0
  66. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/docs/icons/favicon.svg +0 -0
  67. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/docs/icons/generate.sh +0 -0
  68. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/docs/superpowers/specs/2026-03-24-v14-command-consolidation-design.md +0 -0
  69. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/docs/superpowers/specs/2026-03-25-v1.5-dashboard-design.md +0 -0
  70. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/scripts/generate_demo_data.py +0 -0
  71. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/adapters/__init__.py +0 -0
  72. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/adapters/aider.py +0 -0
  73. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/adapters/base.py +0 -0
  74. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/adapters/chatgpt.py +0 -0
  75. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/adapters/claude_chat.py +0 -0
  76. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/adapters/claude_code.py +0 -0
  77. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/adapters/cline.py +0 -0
  78. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/adapters/codex.py +0 -0
  79. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/adapters/cursor.py +0 -0
  80. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/adapters/filters.py +0 -0
  81. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/adapters/gemini.py +0 -0
  82. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/adapters/openclaw.py +0 -0
  83. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/bridge/__init__.py +0 -0
  84. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/bridge/handler.py +0 -0
  85. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/bridge/host.py +0 -0
  86. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/bridge/manifest.py +0 -0
  87. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/bridge/protocol.py +0 -0
  88. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/commands/__init__.py +0 -0
  89. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/commands/telemetry.py +0 -0
  90. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/commands/wrapped.py +0 -0
  91. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/config.py +0 -0
  92. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/core/__init__.py +0 -0
  93. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/core/agent.py +0 -0
  94. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/core/analyzer.py +0 -0
  95. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/core/compress.py +0 -0
  96. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/core/conversation.py +0 -0
  97. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/core/cost.py +0 -0
  98. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/core/dashboard.py +0 -0
  99. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/core/dedup.py +0 -0
  100. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/core/digest.py +0 -0
  101. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/core/distill.py +0 -0
  102. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/core/effectiveness.py +0 -0
  103. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/core/extractors.py +0 -0
  104. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/core/extractors_zh.py +0 -0
  105. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/core/insights.py +0 -0
  106. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/core/lang_detect.py +0 -0
  107. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/core/library.py +0 -0
  108. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/core/lint.py +0 -0
  109. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/core/merge_view.py +0 -0
  110. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/core/models.py +0 -0
  111. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/core/persona.py +0 -0
  112. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/core/pipeline.py +0 -0
  113. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/core/privacy.py +0 -0
  114. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/core/privacy_scan.py +0 -0
  115. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/core/prompt_dna.py +0 -0
  116. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/core/recommend.py +0 -0
  117. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/core/repetition.py +0 -0
  118. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/core/scorer.py +0 -0
  119. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/core/segmenter.py +0 -0
  120. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/core/session_meta.py +0 -0
  121. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/core/session_quality.py +0 -0
  122. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/core/session_type.py +0 -0
  123. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/core/style.py +0 -0
  124. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/core/templates.py +0 -0
  125. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/core/timeutil.py +0 -0
  126. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/core/trends.py +0 -0
  127. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/core/wrapped.py +0 -0
  128. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/demo.py +0 -0
  129. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/embeddings/__init__.py +0 -0
  130. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/embeddings/base.py +0 -0
  131. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/embeddings/local_embed.py +0 -0
  132. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/embeddings/ollama.py +0 -0
  133. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/embeddings/openai_embed.py +0 -0
  134. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/embeddings/tfidf.py +0 -0
  135. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/mcp.py +0 -0
  136. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/mcp_main.py +0 -0
  137. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/output/__init__.py +0 -0
  138. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/output/agent_terminal.py +0 -0
  139. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/output/chartjs.min.js +0 -0
  140. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/output/compress_terminal.py +0 -0
  141. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/output/dashboard_terminal.py +0 -0
  142. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/output/distill_terminal.py +0 -0
  143. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/output/export.py +0 -0
  144. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/output/html_report.py +0 -0
  145. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/output/json_out.py +0 -0
  146. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/output/markdown.py +0 -0
  147. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/output/repetition_terminal.py +0 -0
  148. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/output/sessions_terminal.py +0 -0
  149. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/output/terminal.py +0 -0
  150. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/output/wrapped_html.py +0 -0
  151. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/output/wrapped_terminal.py +0 -0
  152. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/py.typed +0 -0
  153. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/sharing/__init__.py +0 -0
  154. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/sharing/client.py +0 -0
  155. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/sharing/clipboard.py +0 -0
  156. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/storage/__init__.py +0 -0
  157. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/storage/db.py +0 -0
  158. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/telemetry/__init__.py +0 -0
  159. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/telemetry/collector.py +0 -0
  160. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/telemetry/consent.py +0 -0
  161. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/telemetry/events.py +0 -0
  162. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/telemetry/prompt.py +0 -0
  163. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/telemetry/queue.py +0 -0
  164. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/src/reprompt/telemetry/sender.py +0 -0
  165. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/__init__.py +0 -0
  166. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/conftest.py +0 -0
  167. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/fixtures/aider_chat_history.md +0 -0
  168. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/fixtures/chatgpt_conversations.json +0 -0
  169. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/fixtures/claude_chat_export.json +0 -0
  170. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/fixtures/claude_session.jsonl +0 -0
  171. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/fixtures/cline_task/api_conversation_history.json +0 -0
  172. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/fixtures/export/default_export.md +0 -0
  173. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/fixtures/export/full_export.md +0 -0
  174. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/fixtures/gemini_session.json +0 -0
  175. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/fixtures/openclaw_session.jsonl +0 -0
  176. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_adapter_aider.py +0 -0
  177. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_adapter_chatgpt.py +0 -0
  178. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_adapter_claude.py +0 -0
  179. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_adapter_claude_chat.py +0 -0
  180. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_adapter_cline.py +0 -0
  181. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_adapter_gemini.py +0 -0
  182. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_adapter_openclaw.py +0 -0
  183. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_agent.py +0 -0
  184. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_agent_cli.py +0 -0
  185. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_analyzer.py +0 -0
  186. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_bridge_cli.py +0 -0
  187. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_bridge_e2e.py +0 -0
  188. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_bridge_handler.py +0 -0
  189. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_bridge_integration.py +0 -0
  190. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_bridge_manifest.py +0 -0
  191. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_bridge_protocol.py +0 -0
  192. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_cli.py +0 -0
  193. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_cli_deprecations.py +0 -0
  194. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_cli_library_effectiveness.py +0 -0
  195. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_clipboard.py +0 -0
  196. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_codex_adapter.py +0 -0
  197. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_compare_best_worst.py +0 -0
  198. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_compress.py +0 -0
  199. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_compress_cli.py +0 -0
  200. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_compress_dna.py +0 -0
  201. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_compress_html.py +0 -0
  202. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_compress_insights.py +0 -0
  203. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_config.py +0 -0
  204. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_conversation.py +0 -0
  205. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_copy_flag.py +0 -0
  206. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_cost.py +0 -0
  207. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_coverage_boost.py +0 -0
  208. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_cursor_adapter.py +0 -0
  209. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_dashboard.py +0 -0
  210. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_db.py +0 -0
  211. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_db_digest.py +0 -0
  212. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_db_effectiveness.py +0 -0
  213. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_db_session_quality.py +0 -0
  214. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_db_trends.py +0 -0
  215. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_dedup.py +0 -0
  216. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_demo.py +0 -0
  217. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_deprecated_commands.py +0 -0
  218. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_digest.py +0 -0
  219. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_digest_cli.py +0 -0
  220. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_distill.py +0 -0
  221. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_distill_cli.py +0 -0
  222. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_distill_weights.py +0 -0
  223. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_e2e.py +0 -0
  224. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_effectiveness.py +0 -0
  225. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_embeddings_local.py +0 -0
  226. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_embeddings_ollama.py +0 -0
  227. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_embeddings_openai.py +0 -0
  228. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_empty_state.py +0 -0
  229. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_export.py +0 -0
  230. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_export_cli.py +0 -0
  231. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_export_snapshot.py +0 -0
  232. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_extractors.py +0 -0
  233. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_extractors_routing.py +0 -0
  234. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_extractors_zh.py +0 -0
  235. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_extractors_zh_e2e.py +0 -0
  236. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_html_report.py +0 -0
  237. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_import_cli.py +0 -0
  238. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_import_e2e.py +0 -0
  239. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_insights.py +0 -0
  240. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_insights_cli.py +0 -0
  241. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_insights_expanded.py +0 -0
  242. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_install_hook.py +0 -0
  243. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_lang_detect.py +0 -0
  244. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_library.py +0 -0
  245. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_lint.py +0 -0
  246. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_lint_cli.py +0 -0
  247. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_markdown.py +0 -0
  248. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_mcp.py +0 -0
  249. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_merge_view.py +0 -0
  250. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_models.py +0 -0
  251. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_output.py +0 -0
  252. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_parse_conversation_base.py +0 -0
  253. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_parse_conversation_chatgpt.py +0 -0
  254. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_parse_conversation_claude.py +0 -0
  255. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_persona.py +0 -0
  256. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_pipeline.py +0 -0
  257. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_privacy.py +0 -0
  258. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_privacy_cli.py +0 -0
  259. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_privacy_e2e.py +0 -0
  260. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_privacy_output.py +0 -0
  261. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_privacy_scan.py +0 -0
  262. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_prompt_dna.py +0 -0
  263. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_public_api.py +0 -0
  264. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_recommend.py +0 -0
  265. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_repetition.py +0 -0
  266. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_repetition_cli.py +0 -0
  267. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_repetition_output.py +0 -0
  268. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_schema_version.py +0 -0
  269. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_score_cli.py +0 -0
  270. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_scorer.py +0 -0
  271. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_segmenter.py +0 -0
  272. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_session_quality.py +0 -0
  273. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_session_type.py +0 -0
  274. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_sessions_cli.py +0 -0
  275. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_sessions_output.py +0 -0
  276. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_share_e2e.py +0 -0
  277. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_sharing_client.py +0 -0
  278. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_source_filter.py +0 -0
  279. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_style.py +0 -0
  280. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_style_trends.py +0 -0
  281. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_telemetry_cli.py +0 -0
  282. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_telemetry_collector.py +0 -0
  283. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_telemetry_consent.py +0 -0
  284. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_telemetry_e2e.py +0 -0
  285. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_telemetry_events.py +0 -0
  286. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_telemetry_prompt.py +0 -0
  287. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_telemetry_queue.py +0 -0
  288. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_telemetry_sender.py +0 -0
  289. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_template_cli.py +0 -0
  290. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_templates.py +0 -0
  291. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_timeutil.py +0 -0
  292. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_trends.py +0 -0
  293. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_trends_cli.py +0 -0
  294. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_use_cli.py +0 -0
  295. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_wrapped.py +0 -0
  296. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_wrapped_cli.py +0 -0
  297. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_wrapped_e2e.py +0 -0
  298. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_wrapped_html.py +0 -0
  299. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_wrapped_output.py +0 -0
  300. {reprompt_cli-1.9.1 → reprompt_cli-2.0.0}/tests/test_wrapped_share.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: reprompt-cli
3
- Version: 1.9.1
3
+ Version: 2.0.0
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
@@ -45,7 +45,7 @@ Description-Content-Type: text/markdown
45
45
 
46
46
  # `re:prompt`
47
47
 
48
- **Analyze what you type into AI tools** -- prompt scoring, agent error loops, leaked credential detection, conversation distillation.
48
+ **Score, rewrite, and optimize your AI prompts** -- the only CLI that improves your prompts automatically. No LLM needed.
49
49
 
50
50
  [![PyPI version](https://img.shields.io/pypi/v/reprompt-cli)](https://pypi.org/project/reprompt-cli/)
51
51
  [![Python 3.10+](https://img.shields.io/pypi/pyversions/reprompt-cli)](https://pypi.org/project/reprompt-cli/)
@@ -61,26 +61,39 @@ Description-Content-Type: text/markdown
61
61
 
62
62
  ```bash
63
63
  $ pip install reprompt-cli
64
- $ reprompt
65
- ╭─ Prompt Dashboard ─────────────────────────────────────────╮
66
- │ Prompts: 1,063 (295 unique) Sessions: 890 │
67
- │ Avg Score: 68/100 Top: debug (31%), impl (24%)│
68
- │ Sources: claude-code, cursor, chatgpt │
64
+
65
+ # Rewrite a weak prompt into a better one (no LLM, rule-based)
66
+ $ reprompt rewrite "I was wondering if you could maybe help me fix the auth bug"
67
+ 34 52 (+18)
68
+
69
+ ╭─ Rewritten ────────────────────────────────────────────────╮
70
+ │ Help me fix the auth bug. │
69
71
  ╰────────────────────────────────────────────────────────────╯
70
72
 
73
+ Changes
74
+ ✓ Removed filler (24% shorter)
75
+ ✓ Removed hedging language
76
+
77
+ You should also
78
+ → Add actual code snippets or error messages for context
79
+ → Reference specific files or functions by name
80
+ → Add constraints (e.g., "Do not modify existing tests")
81
+
82
+ # Score any prompt instantly (research-backed, 30+ features)
71
83
  $ reprompt score "Fix the auth bug in src/login.ts where JWT expires"
72
84
  Score: 40/100 (Fair)
73
- Structure: 0/25 | Context: 8/25 | Position: 20/20 | Repetition: 0/15 | Clarity: 12/15
74
85
  Tip: Include the error message -- debug prompts with errors are 3.7x more effective
75
86
 
76
- $ reprompt distill --last 3 --summary
77
- Session: feature-dev (42 turns, 18 important)
78
- Key moments: initial spec → auth module → test failures → JWT fix → passing
79
- Context: "Building auth system with JWT refresh tokens for Express API"
80
-
81
- $ reprompt compress "I was wondering if you could please help me refactor this code. Basically what I need is to split this function into smaller helpers and add error handling."
87
+ # Compress prompts to save tokens
88
+ $ reprompt compress "I was wondering if you could please help me refactor this code. Basically what I need is to split this function into smaller helpers."
82
89
  Before: 28 tokens → After: 14 tokens (50% saved)
83
- "Help me refactor this code. Split this function into smaller helpers and add error handling."
90
+
91
+ # Your personal dashboard
92
+ $ reprompt
93
+ ╭─ Prompt Dashboard ─────────────────────────────────────────╮
94
+ │ Prompts: 1,063 (295 unique) Sessions: 890 │
95
+ │ Avg Score: 68/100 Top: debug (31%), impl (24%)│
96
+ ╰────────────────────────────────────────────────────────────╯
84
97
  ```
85
98
 
86
99
  ## What it does
@@ -96,15 +109,19 @@ $ reprompt compress "I was wondering if you could please help me refactor this c
96
109
  | `reprompt insights` | Personal patterns vs research-optimal benchmarks |
97
110
  | `reprompt style` | Prompting fingerprint with `--trends` for evolution tracking |
98
111
  | `reprompt agent` | Agent workflow analysis -- error loops, tool patterns, session efficiency |
112
+ | `reprompt sessions` | Session quality scores with frustration signal detection |
113
+ | `reprompt repetition` | Cross-session repetition detection -- spot recurring prompts |
99
114
 
100
115
  ### Optimize
101
116
 
102
117
  | Command | Description |
103
118
  |---------|-------------|
119
+ | `reprompt rewrite "prompt"` | **Rewrite prompts to score higher** -- filler removal, restructuring, hedging cleanup |
104
120
  | `reprompt compress "prompt"` | 4-layer prompt compression (40-60% token savings typical) |
105
121
  | `reprompt distill` | Extract important turns from conversations with 6-signal scoring |
106
122
  | `reprompt distill --export` | Recover context when a session runs out -- paste into new session |
107
- | `reprompt lint` | Prompt quality linter with GitHub Action support |
123
+ | `reprompt lint` | Configurable prompt quality linter with CI/GitHub Action support |
124
+ | `reprompt init` | Generate `.reprompt.toml` config for your project |
108
125
 
109
126
  ### Manage
110
127
 
@@ -223,6 +240,24 @@ reprompt lint --strict # exit 1 on warnings
223
240
  reprompt lint --json # machine-readable output
224
241
  ```
225
242
 
243
+ #### Project configuration
244
+
245
+ ```bash
246
+ reprompt init # generates .reprompt.toml with all rules documented
247
+ ```
248
+
249
+ ```toml
250
+ # .reprompt.toml (or [tool.reprompt.lint] in pyproject.toml)
251
+ [lint]
252
+ score-threshold = 50 # fail if avg score < 50
253
+
254
+ [lint.rules]
255
+ min-length = 20 # error if prompt < 20 chars (0 = off)
256
+ short-prompt = 40 # warning if < 40 chars (0 = off)
257
+ vague-prompt = true # error on "fix it" etc (false = off)
258
+ debug-needs-reference = true
259
+ ```
260
+
226
261
  ## Privacy
227
262
 
228
263
  - All analysis runs locally. No prompts leave your machine.
@@ -1,6 +1,6 @@
1
1
  # `re:prompt`
2
2
 
3
- **Analyze what you type into AI tools** -- prompt scoring, agent error loops, leaked credential detection, conversation distillation.
3
+ **Score, rewrite, and optimize your AI prompts** -- the only CLI that improves your prompts automatically. No LLM needed.
4
4
 
5
5
  [![PyPI version](https://img.shields.io/pypi/v/reprompt-cli)](https://pypi.org/project/reprompt-cli/)
6
6
  [![Python 3.10+](https://img.shields.io/pypi/pyversions/reprompt-cli)](https://pypi.org/project/reprompt-cli/)
@@ -16,26 +16,39 @@
16
16
 
17
17
  ```bash
18
18
  $ pip install reprompt-cli
19
- $ reprompt
20
- ╭─ Prompt Dashboard ─────────────────────────────────────────╮
21
- │ Prompts: 1,063 (295 unique) Sessions: 890 │
22
- │ Avg Score: 68/100 Top: debug (31%), impl (24%)│
23
- │ Sources: claude-code, cursor, chatgpt │
19
+
20
+ # Rewrite a weak prompt into a better one (no LLM, rule-based)
21
+ $ reprompt rewrite "I was wondering if you could maybe help me fix the auth bug"
22
+ 34 52 (+18)
23
+
24
+ ╭─ Rewritten ────────────────────────────────────────────────╮
25
+ │ Help me fix the auth bug. │
24
26
  ╰────────────────────────────────────────────────────────────╯
25
27
 
28
+ Changes
29
+ ✓ Removed filler (24% shorter)
30
+ ✓ Removed hedging language
31
+
32
+ You should also
33
+ → Add actual code snippets or error messages for context
34
+ → Reference specific files or functions by name
35
+ → Add constraints (e.g., "Do not modify existing tests")
36
+
37
+ # Score any prompt instantly (research-backed, 30+ features)
26
38
  $ reprompt score "Fix the auth bug in src/login.ts where JWT expires"
27
39
  Score: 40/100 (Fair)
28
- Structure: 0/25 | Context: 8/25 | Position: 20/20 | Repetition: 0/15 | Clarity: 12/15
29
40
  Tip: Include the error message -- debug prompts with errors are 3.7x more effective
30
41
 
31
- $ reprompt distill --last 3 --summary
32
- Session: feature-dev (42 turns, 18 important)
33
- Key moments: initial spec → auth module → test failures → JWT fix → passing
34
- Context: "Building auth system with JWT refresh tokens for Express API"
35
-
36
- $ reprompt compress "I was wondering if you could please help me refactor this code. Basically what I need is to split this function into smaller helpers and add error handling."
42
+ # Compress prompts to save tokens
43
+ $ reprompt compress "I was wondering if you could please help me refactor this code. Basically what I need is to split this function into smaller helpers."
37
44
  Before: 28 tokens → After: 14 tokens (50% saved)
38
- "Help me refactor this code. Split this function into smaller helpers and add error handling."
45
+
46
+ # Your personal dashboard
47
+ $ reprompt
48
+ ╭─ Prompt Dashboard ─────────────────────────────────────────╮
49
+ │ Prompts: 1,063 (295 unique) Sessions: 890 │
50
+ │ Avg Score: 68/100 Top: debug (31%), impl (24%)│
51
+ ╰────────────────────────────────────────────────────────────╯
39
52
  ```
40
53
 
41
54
  ## What it does
@@ -51,15 +64,19 @@ $ reprompt compress "I was wondering if you could please help me refactor this c
51
64
  | `reprompt insights` | Personal patterns vs research-optimal benchmarks |
52
65
  | `reprompt style` | Prompting fingerprint with `--trends` for evolution tracking |
53
66
  | `reprompt agent` | Agent workflow analysis -- error loops, tool patterns, session efficiency |
67
+ | `reprompt sessions` | Session quality scores with frustration signal detection |
68
+ | `reprompt repetition` | Cross-session repetition detection -- spot recurring prompts |
54
69
 
55
70
  ### Optimize
56
71
 
57
72
  | Command | Description |
58
73
  |---------|-------------|
74
+ | `reprompt rewrite "prompt"` | **Rewrite prompts to score higher** -- filler removal, restructuring, hedging cleanup |
59
75
  | `reprompt compress "prompt"` | 4-layer prompt compression (40-60% token savings typical) |
60
76
  | `reprompt distill` | Extract important turns from conversations with 6-signal scoring |
61
77
  | `reprompt distill --export` | Recover context when a session runs out -- paste into new session |
62
- | `reprompt lint` | Prompt quality linter with GitHub Action support |
78
+ | `reprompt lint` | Configurable prompt quality linter with CI/GitHub Action support |
79
+ | `reprompt init` | Generate `.reprompt.toml` config for your project |
63
80
 
64
81
  ### Manage
65
82
 
@@ -178,6 +195,24 @@ reprompt lint --strict # exit 1 on warnings
178
195
  reprompt lint --json # machine-readable output
179
196
  ```
180
197
 
198
+ #### Project configuration
199
+
200
+ ```bash
201
+ reprompt init # generates .reprompt.toml with all rules documented
202
+ ```
203
+
204
+ ```toml
205
+ # .reprompt.toml (or [tool.reprompt.lint] in pyproject.toml)
206
+ [lint]
207
+ score-threshold = 50 # fail if avg score < 50
208
+
209
+ [lint.rules]
210
+ min-length = 20 # error if prompt < 20 chars (0 = off)
211
+ short-prompt = 40 # warning if < 40 chars (0 = off)
212
+ vague-prompt = true # error on "fix it" etc (false = off)
213
+ debug-needs-reference = true
214
+ ```
215
+
181
216
  ## Privacy
182
217
 
183
218
  - All analysis runs locally. No prompts leave your machine.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "reprompt-cli"
3
- version = "1.9.1"
3
+ version = "2.0.0"
4
4
  description = "Discover, analyze, and optimize your prompts from AI coding sessions"
5
5
  readme = "README.md"
6
6
  license = { text = "MIT" }
@@ -1,6 +1,6 @@
1
1
  """reprompt — Discover, analyze, and evolve your best prompts from AI coding sessions."""
2
2
 
3
- __version__ = "1.9.1"
3
+ __version__ = "2.0.0"
4
4
 
5
5
  __all__ = [
6
6
  "__version__",
@@ -1065,6 +1065,58 @@ def compress(
1065
1065
  _copy_to_clip(result.compressed, quiet=json_output)
1066
1066
 
1067
1067
 
1068
+ @app.command(rich_help_panel="Optimize")
1069
+ def rewrite(
1070
+ text: str = typer.Argument(..., help="Prompt text to improve"),
1071
+ json_output: bool = typer.Option(False, "--json", help="Output as JSON"),
1072
+ copy: bool = typer.Option(False, "--copy", help="Copy rewritten text to clipboard"),
1073
+ ) -> None:
1074
+ """Rewrite a prompt to improve its score. Rule-based, no LLM needed.
1075
+
1076
+ Applies 4 layers: filler removal, instruction front-loading,
1077
+ key requirement echo, and hedging cleanup. Also suggests manual
1078
+ improvements you can make.
1079
+
1080
+ Examples:
1081
+
1082
+ reprompt rewrite "I was wondering if you could fix the authentication bug"
1083
+
1084
+ reprompt rewrite "please help me refactor this code to be better" --copy
1085
+
1086
+ reprompt rewrite "fix the login" --json
1087
+ """
1088
+ from reprompt.core.rewrite import rewrite_prompt
1089
+
1090
+ result = rewrite_prompt(text)
1091
+
1092
+ if json_output:
1093
+ import json as json_mod
1094
+
1095
+ data = {
1096
+ "original": result.original,
1097
+ "rewritten": result.rewritten,
1098
+ "score_before": result.score_before,
1099
+ "score_after": result.score_after,
1100
+ "score_delta": result.score_delta,
1101
+ "changes": result.changes,
1102
+ "manual_suggestions": result.manual_suggestions,
1103
+ }
1104
+ typer.echo(json_mod.dumps(data, indent=2, ensure_ascii=False))
1105
+ else:
1106
+ from reprompt.output.rewrite_terminal import render_rewrite
1107
+
1108
+ typer.echo(render_rewrite(result))
1109
+
1110
+ if copy:
1111
+ _copy_to_clip(result.rewritten, quiet=json_output)
1112
+
1113
+ from reprompt.core.suggestions import get_suggestion
1114
+
1115
+ hint = get_suggestion("rewrite")
1116
+ if hint and not json_output:
1117
+ console.print(f" [dim]→ Try: {hint}[/dim]\n")
1118
+
1119
+
1068
1120
  @app.command(rich_help_panel="Optimize")
1069
1121
  def distill(
1070
1122
  session_id: str = typer.Argument(None, help="Session ID to distill"),
@@ -1935,6 +1987,65 @@ def extension_status() -> None:
1935
1987
  console.print(" Last sync: never")
1936
1988
 
1937
1989
 
1990
+ @app.command(rich_help_panel="Setup")
1991
+ def init(
1992
+ force: bool = typer.Option(False, "--force", "-f", help="Overwrite existing config"),
1993
+ ) -> None:
1994
+ """Generate a .reprompt.toml config file in the current directory.
1995
+
1996
+ Creates a starter config with all lint rules documented and commented.
1997
+ Use this to customize reprompt for your project or CI pipeline.
1998
+
1999
+ Examples:
2000
+
2001
+ reprompt init # create .reprompt.toml
2002
+
2003
+ reprompt init --force # overwrite existing config
2004
+ """
2005
+ config_path = Path.cwd() / ".reprompt.toml"
2006
+
2007
+ if config_path.exists() and not force:
2008
+ console.print(
2009
+ f"[yellow]{config_path.name} already exists.[/yellow]"
2010
+ " Use [bold]--force[/bold] to overwrite."
2011
+ )
2012
+ raise typer.Exit(1)
2013
+
2014
+ config_content = """\
2015
+ # reprompt configuration
2016
+ # Docs: https://github.com/reprompt-dev/reprompt
2017
+ #
2018
+ # This file configures `reprompt lint` rules and CI thresholds.
2019
+ # Place in your project root — reprompt walks up from CWD to find it.
2020
+ # Alternatively, add [tool.reprompt.lint] to pyproject.toml.
2021
+
2022
+ [lint]
2023
+ # Fail `reprompt lint` if average prompt score < threshold (0 = disabled)
2024
+ # Useful for CI: reprompt lint --score-threshold reads this value
2025
+ # score-threshold = 50
2026
+
2027
+ [lint.rules]
2028
+ # min-length: error if prompt < N chars (0 = disabled)
2029
+ min-length = 20
2030
+
2031
+ # short-prompt: warning if prompt < N chars (0 = disabled)
2032
+ short-prompt = 40
2033
+
2034
+ # vague-prompt: error on vague prompts like "fix it" (false = disabled)
2035
+ vague-prompt = true
2036
+
2037
+ # debug-needs-reference: warning if debug prompt lacks file reference (false = disabled)
2038
+ debug-needs-reference = true
2039
+
2040
+ # file-extensions: extensions recognized as file references
2041
+ # file-extensions = [".py", ".ts", ".js", ".go", ".rs", ".java", ".rb", ".cpp", ".c"]
2042
+ """
2043
+
2044
+ config_path.write_text(config_content)
2045
+ console.print(f"[green]Created[/green] {config_path.name}")
2046
+ console.print(" Edit rules, then run [bold]reprompt lint[/bold] to verify.")
2047
+
2048
+
1938
2049
  @app.command(rich_help_panel="Analyze")
1939
2050
  def sessions(
1940
2051
  last: int = typer.Option(10, "--last", help="Show N most recent sessions"),
@@ -0,0 +1,221 @@
1
+ """Rule-based prompt rewrite engine.
2
+
3
+ Transforms low-scoring prompts into better versions using research-backed
4
+ rules. No LLM required — pure regex + structural transforms.
5
+
6
+ Layers:
7
+ 1. Compress — remove filler (reuse compress engine)
8
+ 2. Restructure — front-load instructions (move imperative to start)
9
+ 3. Reinforce — echo key requirement at end for long prompts
10
+ 4. Annotate — suggest what the user should add manually
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ import re
16
+ from dataclasses import dataclass, field
17
+
18
+
19
+ @dataclass
20
+ class RewriteResult:
21
+ """Result of rewriting a prompt."""
22
+
23
+ original: str
24
+ rewritten: str
25
+ changes: list[str] = field(default_factory=list)
26
+ manual_suggestions: list[str] = field(default_factory=list)
27
+ score_before: float = 0.0
28
+ score_after: float = 0.0
29
+ score_delta: float = 0.0
30
+
31
+
32
+ def rewrite_prompt(text: str) -> RewriteResult:
33
+ """Rewrite a prompt to improve its score. Returns before/after with changes."""
34
+ from reprompt.core.compress import compress_text
35
+ from reprompt.core.extractors import extract_features
36
+ from reprompt.core.scorer import score_prompt
37
+ from reprompt.core.segmenter import segment_prompt
38
+
39
+ # Score original
40
+ dna = extract_features(text, source="rewrite", session_id="")
41
+ score_before = score_prompt(dna)
42
+
43
+ result = text
44
+ changes: list[str] = []
45
+
46
+ # Layer 1: Compress (filler removal)
47
+ compressed = compress_text(result)
48
+ if compressed.savings_pct > 5:
49
+ result = compressed.compressed
50
+ changes.append(f"Removed filler ({compressed.savings_pct:.0f}% shorter)")
51
+
52
+ # Layer 2: Front-load instruction (if buried in middle)
53
+ if dna.key_instruction_position > 0.3:
54
+ segments = segment_prompt(result)
55
+ new_result = _front_load_instruction(result, segments)
56
+ if new_result != result:
57
+ result = new_result
58
+ changes.append("Moved main instruction to front")
59
+
60
+ # Layer 3: Echo key requirement (for long prompts with low repetition)
61
+ current_word_count = len(result.split())
62
+ if dna.keyword_repetition_freq < 0.15 and current_word_count > 40:
63
+ echoed = _echo_key_requirement(result)
64
+ if echoed != result:
65
+ result = echoed
66
+ changes.append("Echoed key requirement at end")
67
+
68
+ # Layer 4: Clarity — replace hedge phrases
69
+ cleaned = _remove_hedging(result)
70
+ if cleaned != result:
71
+ result = cleaned
72
+ changes.append("Removed hedging language")
73
+
74
+ # Score rewritten
75
+ dna_after = extract_features(result, source="rewrite", session_id="")
76
+ score_after = score_prompt(dna_after)
77
+
78
+ # Generate manual suggestions for things we can't auto-fix
79
+ manual = _generate_manual_suggestions(dna)
80
+
81
+ return RewriteResult(
82
+ original=text,
83
+ rewritten=result,
84
+ changes=changes,
85
+ manual_suggestions=manual,
86
+ score_before=score_before.total,
87
+ score_after=score_after.total,
88
+ score_delta=round(score_after.total - score_before.total, 1),
89
+ )
90
+
91
+
92
+ def _front_load_instruction(text: str, segments: list) -> str:
93
+ """Move the first instruction segment to the front of the prompt."""
94
+ instruction_seg = None
95
+ instruction_idx = -1
96
+
97
+ for i, seg in enumerate(segments):
98
+ if seg.segment_type == "instruction" and seg.start_pos > 0.2:
99
+ instruction_seg = seg
100
+ instruction_idx = i
101
+ break
102
+
103
+ if instruction_seg is None:
104
+ return text
105
+
106
+ # Extract the instruction text and rebuild
107
+ inst_text = instruction_seg.text.strip()
108
+ # Remove the instruction from its original position
109
+ remaining_parts = []
110
+ for i, seg in enumerate(segments):
111
+ if i == instruction_idx:
112
+ continue
113
+ remaining_parts.append(seg.text.strip())
114
+
115
+ remaining = "\n\n".join(p for p in remaining_parts if p)
116
+
117
+ # Ensure instruction ends with period for clean sentence
118
+ if inst_text and inst_text[-1] not in ".!?":
119
+ inst_text = inst_text + "."
120
+
121
+ return f"{inst_text}\n\n{remaining}".strip()
122
+
123
+
124
+ def _echo_key_requirement(text: str) -> str:
125
+ """Add a reinforcement of the key requirement at the end."""
126
+ # Extract the most important action phrase from the first sentence
127
+ lines = text.strip().split("\n")
128
+ first_line = ""
129
+ for line in lines:
130
+ stripped = line.strip()
131
+ if stripped and not stripped.startswith("#") and not stripped.startswith("```"):
132
+ first_line = stripped
133
+ break
134
+
135
+ if not first_line or len(first_line) < 10:
136
+ return text
137
+
138
+ # Extract the core verb+object phrase
139
+ key_phrase = _extract_key_phrase(first_line)
140
+ if not key_phrase or len(key_phrase) < 8:
141
+ return text
142
+
143
+ # Don't echo if text already ends with similar content
144
+ last_100 = text[-100:].lower()
145
+ if key_phrase.lower() in last_100:
146
+ return text
147
+
148
+ return f"{text.rstrip()}\n\nImportant: {key_phrase}."
149
+
150
+
151
+ def _extract_key_phrase(sentence: str) -> str:
152
+ """Extract the core verb+object from a sentence."""
153
+ # Remove leading filler
154
+ cleaned = re.sub(
155
+ r"^(?:please\s+|can you\s+|could you\s+|i need you to\s+|i want you to\s+|"
156
+ r"i would like you to\s+|help me\s+)",
157
+ "",
158
+ sentence.strip(),
159
+ flags=re.IGNORECASE,
160
+ )
161
+ # Take the main clause (before first comma or period)
162
+ main = re.split(r"[,.]", cleaned)[0].strip()
163
+ # Cap length
164
+ if len(main) > 80:
165
+ words = main.split()
166
+ main = " ".join(words[:12])
167
+ return main
168
+
169
+
170
+ _HEDGE_PATTERNS = [
171
+ (re.compile(r"\bI was wondering if you could\b", re.IGNORECASE), ""),
172
+ (re.compile(r"\bI think maybe\b", re.IGNORECASE), ""),
173
+ (re.compile(r"\bif possible,?\s*", re.IGNORECASE), ""),
174
+ (re.compile(r"\bif you don'?t mind,?\s*", re.IGNORECASE), ""),
175
+ (re.compile(r"\bbasically,?\s*", re.IGNORECASE), ""),
176
+ (re.compile(r"\bkind of\b", re.IGNORECASE), ""),
177
+ (re.compile(r"\bsort of\b", re.IGNORECASE), ""),
178
+ (re.compile(r"\bjust\s+", re.IGNORECASE), ""),
179
+ (re.compile(r"\bmaybe\s+", re.IGNORECASE), ""),
180
+ (re.compile(r"\bperhaps\s+", re.IGNORECASE), ""),
181
+ (re.compile(r"\ba little bit\b", re.IGNORECASE), ""),
182
+ (re.compile(r"\bI guess\s+", re.IGNORECASE), ""),
183
+ ]
184
+
185
+
186
+ def _remove_hedging(text: str) -> str:
187
+ """Remove hedging language that weakens the prompt."""
188
+ result = text
189
+ for pattern, replacement in _HEDGE_PATTERNS:
190
+ result = pattern.sub(replacement, result)
191
+ # Clean up double spaces
192
+ result = re.sub(r" +", " ", result)
193
+ # Clean up leading spaces on lines
194
+ lines = result.split("\n")
195
+ result = "\n".join(line.lstrip() if line.strip() else line for line in lines)
196
+ return result
197
+
198
+
199
+ def _generate_manual_suggestions(dna: object) -> list[str]:
200
+ """Generate suggestions for improvements that require human input."""
201
+ suggestions: list[str] = []
202
+
203
+ specificity = getattr(dna, "context_specificity", 1.0)
204
+ if specificity < 0.4:
205
+ suggestions.append("Add actual code snippets or error messages for context")
206
+
207
+ if not getattr(dna, "has_constraints", True):
208
+ suggestions.append('Add constraints (e.g., "Do not modify existing tests")')
209
+
210
+ if not getattr(dna, "has_output_format", True):
211
+ suggestions.append("Specify expected output format (e.g., JSON, code block)")
212
+
213
+ if not getattr(dna, "has_file_references", True):
214
+ task = getattr(dna, "task_type", "")
215
+ if task in ("debug", "implement", "refactor", "test"):
216
+ suggestions.append("Reference specific files or functions by name")
217
+
218
+ if not getattr(dna, "has_examples", True):
219
+ suggestions.append("Add an example of expected input/output")
220
+
221
+ return suggestions
@@ -22,6 +22,8 @@ SUGGESTIONS: dict[str, str] = {
22
22
  'reprompt template save "..." (reuse patterns) · reprompt insights (all patterns)'
23
23
  ),
24
24
  "template": "reprompt insights (see which patterns work best)",
25
+ "lint": "reprompt init (generate .reprompt.toml) · reprompt rewrite (improve prompts)",
26
+ "rewrite": "reprompt compress (reduce tokens) · reprompt score (verify improvement)",
25
27
  }
26
28
 
27
29
 
@@ -0,0 +1,69 @@
1
+ """Rich terminal output for rewrite command."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from io import StringIO
6
+ from typing import TYPE_CHECKING
7
+
8
+ from rich.console import Console
9
+ from rich.panel import Panel
10
+
11
+ if TYPE_CHECKING:
12
+ from reprompt.core.rewrite import RewriteResult
13
+
14
+
15
+ def render_rewrite(result: RewriteResult) -> str:
16
+ """Render a rewrite result as a Rich-formatted string."""
17
+ buf = StringIO()
18
+ console = Console(file=buf, width=100, record=True)
19
+
20
+ # Score change header
21
+ delta = result.score_delta
22
+ if delta > 0:
23
+ delta_str = f"[green]+{delta:.0f}[/green]"
24
+ elif delta < 0:
25
+ delta_str = f"[red]{delta:.0f}[/red]"
26
+ else:
27
+ delta_str = "[dim]±0[/dim]"
28
+
29
+ before_color = _score_color(result.score_before)
30
+ after_color = _score_color(result.score_after)
31
+
32
+ console.print(
33
+ f"\n [{before_color}]{result.score_before:.0f}[/{before_color}]"
34
+ f" → [{after_color}]{result.score_after:.0f}[/{after_color}]"
35
+ f" ({delta_str})\n"
36
+ )
37
+
38
+ # Rewritten prompt
39
+ if result.changes:
40
+ console.print(Panel(result.rewritten, title="Rewritten", border_style="green"))
41
+ else:
42
+ console.print("[dim]No automated improvements found.[/dim]")
43
+
44
+ # Changes applied
45
+ if result.changes:
46
+ console.print("\n [bold]Changes[/bold]")
47
+ for change in result.changes:
48
+ console.print(f" [green]✓[/green] {change}")
49
+
50
+ # Manual suggestions
51
+ if result.manual_suggestions:
52
+ console.print("\n [bold]You should also[/bold]")
53
+ for s in result.manual_suggestions:
54
+ console.print(f" [yellow]→[/yellow] {s}")
55
+
56
+ console.print()
57
+ return buf.getvalue()
58
+
59
+
60
+ def _score_color(score: float) -> str:
61
+ if score >= 85:
62
+ return "bold magenta"
63
+ if score >= 70:
64
+ return "bold green"
65
+ if score >= 55:
66
+ return "bold yellow"
67
+ if score >= 40:
68
+ return "yellow"
69
+ return "bold red"