reprompt-cli 2.2.0__py3-none-any.whl → 2.2.2__py3-none-any.whl
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.
- reprompt/cli.py +34 -9
- reprompt/mcp.py +83 -22
- {reprompt_cli-2.2.0.dist-info → reprompt_cli-2.2.2.dist-info}/METADATA +2 -2
- {reprompt_cli-2.2.0.dist-info → reprompt_cli-2.2.2.dist-info}/RECORD +7 -7
- {reprompt_cli-2.2.0.dist-info → reprompt_cli-2.2.2.dist-info}/WHEEL +0 -0
- {reprompt_cli-2.2.0.dist-info → reprompt_cli-2.2.2.dist-info}/entry_points.txt +0 -0
- {reprompt_cli-2.2.0.dist-info → reprompt_cli-2.2.2.dist-info}/licenses/LICENSE +0 -0
reprompt/cli.py
CHANGED
|
@@ -15,6 +15,21 @@ if TYPE_CHECKING:
|
|
|
15
15
|
from reprompt.storage.db import PromptDB
|
|
16
16
|
|
|
17
17
|
|
|
18
|
+
def _resolve_text(text: str, file: str) -> str:
|
|
19
|
+
"""Resolve prompt text from argument or --file option."""
|
|
20
|
+
if file:
|
|
21
|
+
p = Path(file)
|
|
22
|
+
if not p.is_file():
|
|
23
|
+
typer.echo(f"Error: file not found: {file}", err=True)
|
|
24
|
+
raise typer.Exit(1)
|
|
25
|
+
return p.read_text(encoding="utf-8").strip()
|
|
26
|
+
if text == "-":
|
|
27
|
+
import sys
|
|
28
|
+
|
|
29
|
+
return sys.stdin.read().strip()
|
|
30
|
+
return text
|
|
31
|
+
|
|
32
|
+
|
|
18
33
|
def _copy_to_clip(text: str, quiet: bool = False) -> None:
|
|
19
34
|
"""Copy text to clipboard with user feedback."""
|
|
20
35
|
from reprompt.sharing.clipboard import copy_to_clipboard
|
|
@@ -948,9 +963,10 @@ def lint(
|
|
|
948
963
|
|
|
949
964
|
@app.command(rich_help_panel="Analyze")
|
|
950
965
|
def check(
|
|
951
|
-
text: str = typer.Argument(..., help="Prompt text to check"),
|
|
966
|
+
text: str = typer.Argument(..., help="Prompt text to check (use '-' for stdin)"),
|
|
952
967
|
model: str = typer.Option("", "--model", "-m", help="Target model (claude/gpt/gemini)"),
|
|
953
968
|
max_tokens: int = typer.Option(0, "--max-tokens", help="Token budget (0 = disabled)"),
|
|
969
|
+
file: str = typer.Option("", "--file", "-f", help="Read prompt from file"),
|
|
954
970
|
json_output: bool = typer.Option(False, "--json", help="Output as JSON"),
|
|
955
971
|
copy: bool = typer.Option(False, "--copy", help="Copy rewritten prompt to clipboard"),
|
|
956
972
|
) -> None:
|
|
@@ -967,6 +983,7 @@ def check(
|
|
|
967
983
|
|
|
968
984
|
reprompt check "help me debug this crash" --json
|
|
969
985
|
"""
|
|
986
|
+
text = _resolve_text(text, file)
|
|
970
987
|
from reprompt.core.check import check_prompt
|
|
971
988
|
|
|
972
989
|
result = check_prompt(text, model=model, max_tokens=max_tokens)
|
|
@@ -1009,7 +1026,8 @@ def check(
|
|
|
1009
1026
|
|
|
1010
1027
|
@app.command(rich_help_panel="Analyze")
|
|
1011
1028
|
def explain(
|
|
1012
|
-
text: str = typer.Argument(..., help="Prompt text to explain"),
|
|
1029
|
+
text: str = typer.Argument(..., help="Prompt text to explain (use '-' for stdin)"),
|
|
1030
|
+
file: str = typer.Option("", "--file", "-f", help="Read prompt from file"),
|
|
1013
1031
|
json_output: bool = typer.Option(False, "--json", help="Output as JSON"),
|
|
1014
1032
|
) -> None:
|
|
1015
1033
|
"""Explain what makes a prompt good or bad in plain English.
|
|
@@ -1021,8 +1039,9 @@ def explain(
|
|
|
1021
1039
|
|
|
1022
1040
|
reprompt explain "fix the auth bug"
|
|
1023
1041
|
|
|
1024
|
-
reprompt explain
|
|
1042
|
+
reprompt explain --file prompt.txt --json
|
|
1025
1043
|
"""
|
|
1044
|
+
text = _resolve_text(text, file)
|
|
1026
1045
|
from reprompt.core.explain import explain_prompt
|
|
1027
1046
|
|
|
1028
1047
|
result = explain_prompt(text)
|
|
@@ -1053,7 +1072,8 @@ def explain(
|
|
|
1053
1072
|
|
|
1054
1073
|
@app.command(rich_help_panel="Analyze")
|
|
1055
1074
|
def score(
|
|
1056
|
-
text: str = typer.Argument(..., help="Prompt text to score"),
|
|
1075
|
+
text: str = typer.Argument(..., help="Prompt text to score (use '-' for stdin)"),
|
|
1076
|
+
file: str = typer.Option("", "--file", "-f", help="Read prompt from file"),
|
|
1057
1077
|
json_output: bool = typer.Option(False, "--json", help="Output as JSON"),
|
|
1058
1078
|
copy: bool = typer.Option(False, "--copy", help="Copy result to clipboard"),
|
|
1059
1079
|
) -> None:
|
|
@@ -1063,10 +1083,11 @@ def score(
|
|
|
1063
1083
|
|
|
1064
1084
|
reprompt score "Fix the auth bug in login.ts where JWT expires"
|
|
1065
1085
|
|
|
1066
|
-
reprompt score
|
|
1086
|
+
reprompt score --file prompt.txt --json
|
|
1067
1087
|
|
|
1068
1088
|
reprompt score "Fix bug" --copy
|
|
1069
1089
|
"""
|
|
1090
|
+
text = _resolve_text(text, file)
|
|
1070
1091
|
from reprompt.core.cost import estimate_cost, format_cost, model_for_source
|
|
1071
1092
|
from reprompt.core.extractors import extract_features
|
|
1072
1093
|
from reprompt.core.scorer import score_prompt
|
|
@@ -1174,7 +1195,8 @@ def score(
|
|
|
1174
1195
|
|
|
1175
1196
|
@app.command(rich_help_panel="Optimize")
|
|
1176
1197
|
def compress(
|
|
1177
|
-
text: str = typer.Argument(..., help="Prompt text to compress"),
|
|
1198
|
+
text: str = typer.Argument(..., help="Prompt text to compress (use '-' for stdin)"),
|
|
1199
|
+
file: str = typer.Option("", "--file", "-f", help="Read prompt from file"),
|
|
1178
1200
|
json_output: bool = typer.Option(False, "--json", help="Output as JSON"),
|
|
1179
1201
|
copy: bool = typer.Option(False, "--copy", help="Copy compressed text to clipboard"),
|
|
1180
1202
|
) -> None:
|
|
@@ -1184,10 +1206,11 @@ def compress(
|
|
|
1184
1206
|
|
|
1185
1207
|
reprompt compress "Can you please help me refactor this code?"
|
|
1186
1208
|
|
|
1187
|
-
reprompt compress
|
|
1209
|
+
reprompt compress --file prompt.txt --json
|
|
1188
1210
|
|
|
1189
1211
|
reprompt compress "verbose prompt here" --copy
|
|
1190
1212
|
"""
|
|
1213
|
+
text = _resolve_text(text, file)
|
|
1191
1214
|
from reprompt.core.compress import compress_text
|
|
1192
1215
|
|
|
1193
1216
|
result = compress_text(text)
|
|
@@ -1208,7 +1231,8 @@ def compress(
|
|
|
1208
1231
|
|
|
1209
1232
|
@app.command(rich_help_panel="Optimize")
|
|
1210
1233
|
def rewrite(
|
|
1211
|
-
text: str = typer.Argument(..., help="Prompt text to improve"),
|
|
1234
|
+
text: str = typer.Argument(..., help="Prompt text to improve (use '-' for stdin)"),
|
|
1235
|
+
file: str = typer.Option("", "--file", "-f", help="Read prompt from file"),
|
|
1212
1236
|
json_output: bool = typer.Option(False, "--json", help="Output as JSON"),
|
|
1213
1237
|
diff: bool = typer.Option(False, "--diff", help="Show unified diff (red/green)"),
|
|
1214
1238
|
copy: bool = typer.Option(False, "--copy", help="Copy rewritten text to clipboard"),
|
|
@@ -1223,10 +1247,11 @@ def rewrite(
|
|
|
1223
1247
|
|
|
1224
1248
|
reprompt rewrite "I was wondering if you could fix the authentication bug"
|
|
1225
1249
|
|
|
1226
|
-
reprompt rewrite
|
|
1250
|
+
reprompt rewrite --file prompt.txt --diff
|
|
1227
1251
|
|
|
1228
1252
|
reprompt rewrite "please help me refactor this code to be better" --copy
|
|
1229
1253
|
"""
|
|
1254
|
+
text = _resolve_text(text, file)
|
|
1230
1255
|
from reprompt.core.rewrite import rewrite_prompt
|
|
1231
1256
|
|
|
1232
1257
|
result = rewrite_prompt(text)
|
reprompt/mcp.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""MCP server for reprompt — exposes prompt analytics as
|
|
1
|
+
"""MCP server for reprompt — exposes prompt analytics as 7 focused tools.
|
|
2
2
|
|
|
3
3
|
Usage:
|
|
4
4
|
python -m reprompt.mcp # stdio transport (default)
|
|
@@ -187,37 +187,42 @@ def compress_prompt(text: str) -> str:
|
|
|
187
187
|
|
|
188
188
|
|
|
189
189
|
@mcp.tool
|
|
190
|
-
def score_prompt(text: str) -> str:
|
|
191
|
-
"""Score a prompt
|
|
190
|
+
def score_prompt(text: str, model: str | None = None) -> str:
|
|
191
|
+
"""Score a prompt and get a full quality report (0-100).
|
|
192
192
|
|
|
193
|
-
Returns
|
|
194
|
-
|
|
193
|
+
Returns tier label, dimensional breakdown, strengths, improvement
|
|
194
|
+
suggestions with point values, lint issues, and an auto-rewritten
|
|
195
|
+
version. This is the single tool for all prompt quality analysis.
|
|
195
196
|
|
|
196
197
|
Args:
|
|
197
|
-
text: The prompt text to
|
|
198
|
+
text: The prompt text to analyze
|
|
199
|
+
model: Target model for model-specific lint (claude/gpt/gemini). Optional.
|
|
198
200
|
"""
|
|
199
201
|
try:
|
|
200
|
-
from reprompt.core.
|
|
201
|
-
from reprompt.core.extractors import extract_features
|
|
202
|
-
from reprompt.core.scorer import score_prompt as _score
|
|
202
|
+
from reprompt.core.check import check_prompt as _check
|
|
203
203
|
|
|
204
|
-
|
|
205
|
-
breakdown = _score(dna)
|
|
206
|
-
cost_usd = estimate_cost(dna.token_count, source="mcp")
|
|
204
|
+
result = _check(text, model=model or "")
|
|
207
205
|
return json.dumps(
|
|
208
206
|
{
|
|
209
|
-
"total":
|
|
210
|
-
"
|
|
211
|
-
"
|
|
212
|
-
"
|
|
213
|
-
"
|
|
214
|
-
"
|
|
215
|
-
"
|
|
216
|
-
"
|
|
217
|
-
"
|
|
207
|
+
"total": result.total,
|
|
208
|
+
"tier": result.tier,
|
|
209
|
+
"clarity": result.clarity,
|
|
210
|
+
"context": result.context,
|
|
211
|
+
"position": result.position,
|
|
212
|
+
"structure": result.structure,
|
|
213
|
+
"repetition": result.repetition,
|
|
214
|
+
"word_count": result.word_count,
|
|
215
|
+
"token_count": result.token_count,
|
|
216
|
+
"strengths": [c["message"] for c in result.confirmations[:3]],
|
|
218
217
|
"suggestions": [
|
|
219
|
-
{"message": s
|
|
218
|
+
{"message": s["message"], "points": s.get("points", 0)}
|
|
219
|
+
for s in result.suggestions[:3]
|
|
220
220
|
],
|
|
221
|
+
"lint_issues": [
|
|
222
|
+
{"rule": i["rule"], "message": i["message"]} for i in result.lint_issues
|
|
223
|
+
],
|
|
224
|
+
"rewritten": result.rewritten if result.rewrite_changes else None,
|
|
225
|
+
"rewrite_changes": result.rewrite_changes or None,
|
|
221
226
|
},
|
|
222
227
|
indent=2,
|
|
223
228
|
)
|
|
@@ -297,6 +302,62 @@ def scan_sessions(source: str | None = None) -> str:
|
|
|
297
302
|
return json.dumps({"error": str(exc)})
|
|
298
303
|
|
|
299
304
|
|
|
305
|
+
@mcp.tool
|
|
306
|
+
def build_prompt_from_parts(
|
|
307
|
+
task: str,
|
|
308
|
+
context: str = "",
|
|
309
|
+
files: str = "",
|
|
310
|
+
error: str = "",
|
|
311
|
+
constraints: str = "",
|
|
312
|
+
role: str = "",
|
|
313
|
+
model: str = "",
|
|
314
|
+
) -> str:
|
|
315
|
+
"""Build a well-structured prompt from components.
|
|
316
|
+
|
|
317
|
+
Assembles a prompt that maximizes quality score from individual parts.
|
|
318
|
+
Model-aware: uses XML tags for Claude, markdown for GPT.
|
|
319
|
+
|
|
320
|
+
Args:
|
|
321
|
+
task: What the AI should do (required)
|
|
322
|
+
context: Background information
|
|
323
|
+
files: Comma-separated file paths (e.g., "src/auth.ts,src/token.ts")
|
|
324
|
+
error: Error message or stack trace
|
|
325
|
+
constraints: Comma-separated constraints (e.g., "keep tests,no breaking changes")
|
|
326
|
+
role: AI role/persona (e.g., "senior backend engineer")
|
|
327
|
+
model: Target model (claude/gpt/gemini) for format optimization
|
|
328
|
+
"""
|
|
329
|
+
try:
|
|
330
|
+
from reprompt.core.build import build_prompt as _build
|
|
331
|
+
|
|
332
|
+
file_list = [f.strip() for f in files.split(",") if f.strip()] if files else None
|
|
333
|
+
constraint_list = (
|
|
334
|
+
[c.strip() for c in constraints.split(",") if c.strip()] if constraints else None
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
result = _build(
|
|
338
|
+
task,
|
|
339
|
+
context=context,
|
|
340
|
+
files=file_list,
|
|
341
|
+
error=error,
|
|
342
|
+
constraints=constraint_list,
|
|
343
|
+
role=role,
|
|
344
|
+
model=model,
|
|
345
|
+
)
|
|
346
|
+
return json.dumps(
|
|
347
|
+
{
|
|
348
|
+
"prompt": result.prompt,
|
|
349
|
+
"score": result.score,
|
|
350
|
+
"tier": result.tier,
|
|
351
|
+
"components_used": result.components_used,
|
|
352
|
+
"suggestions": result.suggestions,
|
|
353
|
+
},
|
|
354
|
+
indent=2,
|
|
355
|
+
)
|
|
356
|
+
except Exception as exc:
|
|
357
|
+
logger.debug("build_prompt_from_parts error: %s", exc)
|
|
358
|
+
return json.dumps({"error": str(exc)})
|
|
359
|
+
|
|
360
|
+
|
|
300
361
|
# ─── Resources ──────────────────────────────────────────────────────────────
|
|
301
362
|
|
|
302
363
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: reprompt-cli
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.2
|
|
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
|
|
@@ -230,7 +230,7 @@ Captured prompts sync locally via Native Messaging -- nothing leaves your machin
|
|
|
230
230
|
# .pre-commit-config.yaml
|
|
231
231
|
repos:
|
|
232
232
|
- repo: https://github.com/reprompt-dev/reprompt
|
|
233
|
-
rev: v2.2.
|
|
233
|
+
rev: v2.2.1
|
|
234
234
|
hooks:
|
|
235
235
|
- id: reprompt-lint
|
|
236
236
|
```
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
reprompt/__init__.py,sha256=vd9LG0aypbHUkpGEvLY9J-ZVsrGacwImfZwVdwb6_T8,2415
|
|
2
|
-
reprompt/cli.py,sha256=
|
|
2
|
+
reprompt/cli.py,sha256=9OqAzAxX3jQ_El7pxG-SGc4maVmd-ujSoqGJvxILYWY,88428
|
|
3
3
|
reprompt/config.py,sha256=ZxzkPOUBPytl1jY0vWk6KtNSMhZxAimKQ9wYy5SpiBo,3500
|
|
4
4
|
reprompt/demo.py,sha256=6koYXimMczGF0rYmLYfv4qC72QbLcqJwKSIyw7HEkSE,7744
|
|
5
|
-
reprompt/mcp.py,sha256=
|
|
5
|
+
reprompt/mcp.py,sha256=DrjHnx1TOUvqzkH-TWM6thqdTHA-Ho7yZHAMe2AMQpA,13617
|
|
6
6
|
reprompt/mcp_main.py,sha256=k947MJtfdpmMaGhrK1WNAilG4OAA7uj7aMG9o0xTzZI,128
|
|
7
7
|
reprompt/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
8
|
reprompt/adapters/__init__.py,sha256=_LbAhUS_85bD9weFW9LnM-4x-EkIo-sTPZGP6z1fgVM,88
|
|
@@ -104,8 +104,8 @@ reprompt/telemetry/events.py,sha256=WZPCK4KQAk6NLHXbDNJJukXy_nHJ8t0UDao2kiCh410,
|
|
|
104
104
|
reprompt/telemetry/prompt.py,sha256=ouErxEWvi0OCw91RpU0DXJf72fvai0GQMRk3jAs9mK8,2434
|
|
105
105
|
reprompt/telemetry/queue.py,sha256=G1qqOF9vRGXAn7Y8K2wFstYZne0K99IP-lzOmn_05d0,3437
|
|
106
106
|
reprompt/telemetry/sender.py,sha256=ErNkmRTzRMl9qNQsnU6zqbFBSD-qWN13v6gcLrmA5tc,1460
|
|
107
|
-
reprompt_cli-2.2.
|
|
108
|
-
reprompt_cli-2.2.
|
|
109
|
-
reprompt_cli-2.2.
|
|
110
|
-
reprompt_cli-2.2.
|
|
111
|
-
reprompt_cli-2.2.
|
|
107
|
+
reprompt_cli-2.2.2.dist-info/METADATA,sha256=Twhf06nmG1tn6F9hbBe0ky3LU2nuF1aR9jYoT82MNWM,11870
|
|
108
|
+
reprompt_cli-2.2.2.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
109
|
+
reprompt_cli-2.2.2.dist-info/entry_points.txt,sha256=VQTi0S-vVU8YIfEZU_aOm6SHBpRPuN3Wh7MzLhemb_Y,46
|
|
110
|
+
reprompt_cli-2.2.2.dist-info/licenses/LICENSE,sha256=5xJBBHKoDOoUfG1iXzCmBScu7I-L4qIxWEm8jaYnzgo,1069
|
|
111
|
+
reprompt_cli-2.2.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|