prq-cli 0.7.0 → 0.8.0
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.
- package/README.md +20 -4
- package/dist/bin/prq.js +35 -24
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -95,19 +95,21 @@ prq skill --global # install globally
|
|
|
95
95
|
|
|
96
96
|
## Pluggable Actions
|
|
97
97
|
|
|
98
|
-
PRQ doesn't force a workflow. Every action is a configurable shell command template. Override the defaults or add your own in `.prqrc.json
|
|
98
|
+
PRQ doesn't force a workflow. Every action is a configurable shell command template — inline commands or scripts. Override the defaults or add your own in `.prqrc.json`.
|
|
99
|
+
|
|
100
|
+
Actions run with full terminal control. When you trigger an action, prq suspends its TUI, the command takes over the screen (interactive tools like Claude Code work as normal), and prq resumes when the command exits.
|
|
99
101
|
|
|
100
102
|
### Use Claude Code for reviews
|
|
101
103
|
|
|
102
104
|
```json
|
|
103
105
|
{
|
|
104
106
|
"actions": {
|
|
105
|
-
"review": "claude
|
|
107
|
+
"review": "claude '/review {url}'"
|
|
106
108
|
}
|
|
107
109
|
}
|
|
108
110
|
```
|
|
109
111
|
|
|
110
|
-
Now `prq review 482`
|
|
112
|
+
Now `prq review 482` opens an interactive Claude Code session.
|
|
111
113
|
|
|
112
114
|
### Use Codex for reviews
|
|
113
115
|
|
|
@@ -119,6 +121,18 @@ Now `prq review 482` dispatches to Claude Code.
|
|
|
119
121
|
}
|
|
120
122
|
```
|
|
121
123
|
|
|
124
|
+
### Use a script for complex workflows
|
|
125
|
+
|
|
126
|
+
```json
|
|
127
|
+
{
|
|
128
|
+
"actions": {
|
|
129
|
+
"review": "./scripts/review.sh {number} {url}"
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
The script handles its own logic — session management, resuming, branching, whatever you need.
|
|
135
|
+
|
|
122
136
|
### Use gh CLI to checkout
|
|
123
137
|
|
|
124
138
|
```json
|
|
@@ -143,9 +157,11 @@ With no config, `prq review` opens the files changed tab and `prq open` opens th
|
|
|
143
157
|
| `{number}` | `482` |
|
|
144
158
|
| `{owner}` | `org` |
|
|
145
159
|
| `{repo}` | `repo` |
|
|
160
|
+
| `{fullRepo}` | `org/repo` |
|
|
146
161
|
| `{title}` | `fix: handle edge case` |
|
|
147
162
|
| `{author}` | `alice` |
|
|
148
163
|
| `{days}` | `5` |
|
|
164
|
+
| `{category}` | `needs-re-review` |
|
|
149
165
|
|
|
150
166
|
## Agent & Automation
|
|
151
167
|
|
|
@@ -196,7 +212,7 @@ Full example:
|
|
|
196
212
|
"repos": ["org/repo1", "org/repo2"],
|
|
197
213
|
"staleDays": 5,
|
|
198
214
|
"actions": {
|
|
199
|
-
"review": "claude
|
|
215
|
+
"review": "claude '/review {url}'",
|
|
200
216
|
"checkout": "gh pr checkout {number} --repo {owner}/{repo}",
|
|
201
217
|
"approve": "gh pr review {number} --repo {owner}/{repo} --approve"
|
|
202
218
|
}
|
package/dist/bin/prq.js
CHANGED
|
@@ -6424,7 +6424,7 @@ function getAction(name, config) {
|
|
|
6424
6424
|
function listActions(config) {
|
|
6425
6425
|
return { ...DEFAULT_ACTIONS, ...config.actions };
|
|
6426
6426
|
}
|
|
6427
|
-
function buildContext(pr) {
|
|
6427
|
+
function buildContext(pr, category = "") {
|
|
6428
6428
|
const days = Math.floor((Date.now() - new Date(pr.updatedAt || Date.now()).getTime()) / 86400000);
|
|
6429
6429
|
return {
|
|
6430
6430
|
url: pr.url,
|
|
@@ -6434,7 +6434,8 @@ function buildContext(pr) {
|
|
|
6434
6434
|
fullRepo: `${pr.owner}/${pr.repo}`,
|
|
6435
6435
|
title: pr.title,
|
|
6436
6436
|
author: pr.author,
|
|
6437
|
-
days
|
|
6437
|
+
days,
|
|
6438
|
+
category
|
|
6438
6439
|
};
|
|
6439
6440
|
}
|
|
6440
6441
|
function interpolate(template, context) {
|
|
@@ -6797,14 +6798,34 @@ function render(state) {
|
|
|
6797
6798
|
process.stdout.write(lines.join(`
|
|
6798
6799
|
`));
|
|
6799
6800
|
}
|
|
6800
|
-
|
|
6801
|
-
|
|
6802
|
-
|
|
6801
|
+
function suspend() {
|
|
6802
|
+
process.stdin.setRawMode(false);
|
|
6803
|
+
process.stdin.pause();
|
|
6804
|
+
process.stdin.removeAllListeners("data");
|
|
6805
|
+
process.stdout.write("\x1B[?25h\x1B[2J\x1B[H");
|
|
6806
|
+
}
|
|
6807
|
+
function resume(state, onData) {
|
|
6808
|
+
process.stdin.setRawMode(true);
|
|
6809
|
+
process.stdin.resume();
|
|
6810
|
+
process.stdin.setEncoding("utf8");
|
|
6811
|
+
process.stdout.write("\x1B[?25l");
|
|
6812
|
+
process.stdin.on("data", onData);
|
|
6803
6813
|
render(state);
|
|
6814
|
+
}
|
|
6815
|
+
async function runAction(actionName, template, pr, state, onData) {
|
|
6816
|
+
const context = buildContext(toResolvedPR(pr), pr.category);
|
|
6817
|
+
const cmd = interpolate(template, context);
|
|
6818
|
+
suspend();
|
|
6819
|
+
process.stdout.write(source_default.dim(`
|
|
6820
|
+
running ${actionName} on ${pr.repo}#${pr.number}...
|
|
6821
|
+
|
|
6822
|
+
`));
|
|
6804
6823
|
try {
|
|
6805
6824
|
await executeCommand(cmd);
|
|
6825
|
+
resume(state, onData);
|
|
6806
6826
|
return source_default.green(`${actionName}: ${pr.repo}#${pr.number}`);
|
|
6807
6827
|
} catch {
|
|
6828
|
+
resume(state, onData);
|
|
6808
6829
|
return source_default.red(`${actionName} failed`);
|
|
6809
6830
|
}
|
|
6810
6831
|
}
|
|
@@ -6828,33 +6849,22 @@ async function interactiveMode(result, config) {
|
|
|
6828
6849
|
`);
|
|
6829
6850
|
return;
|
|
6830
6851
|
}
|
|
6831
|
-
process.stdin.setRawMode(true);
|
|
6832
|
-
process.stdin.resume();
|
|
6833
|
-
process.stdin.setEncoding("utf8");
|
|
6834
|
-
process.stdout.write("\x1B[?25l");
|
|
6835
|
-
render(state);
|
|
6836
6852
|
return new Promise((resolve) => {
|
|
6837
|
-
const
|
|
6838
|
-
process.stdin.setRawMode(false);
|
|
6839
|
-
process.stdin.pause();
|
|
6840
|
-
process.stdin.removeAllListeners("data");
|
|
6841
|
-
process.stdout.write("\x1B[?25h\x1B[2J\x1B[H");
|
|
6842
|
-
};
|
|
6843
|
-
process.stdin.on("data", async (key) => {
|
|
6853
|
+
const onData = async (key) => {
|
|
6844
6854
|
const pr = result.prs[state.selectedIndex];
|
|
6845
6855
|
if (state.actionMenu) {
|
|
6846
6856
|
if (key === "q" || key === "\x1B" || key === "a") {
|
|
6847
6857
|
state.actionMenu = null;
|
|
6848
6858
|
state.message = "";
|
|
6849
6859
|
} else if (key === "\x03") {
|
|
6850
|
-
|
|
6860
|
+
suspend();
|
|
6851
6861
|
resolve();
|
|
6852
6862
|
return;
|
|
6853
6863
|
} else {
|
|
6854
6864
|
const idx = parseInt(key, 10);
|
|
6855
6865
|
if (idx >= 1 && idx <= state.actionMenu.length) {
|
|
6856
6866
|
const action = state.actionMenu[idx - 1];
|
|
6857
|
-
state.message = await runAction(action.name, action.template, pr, state);
|
|
6867
|
+
state.message = await runAction(action.name, action.template, pr, state, onData);
|
|
6858
6868
|
state.actionMenu = null;
|
|
6859
6869
|
}
|
|
6860
6870
|
}
|
|
@@ -6864,7 +6874,7 @@ async function interactiveMode(result, config) {
|
|
|
6864
6874
|
switch (key) {
|
|
6865
6875
|
case "q":
|
|
6866
6876
|
case "\x03":
|
|
6867
|
-
|
|
6877
|
+
suspend();
|
|
6868
6878
|
resolve();
|
|
6869
6879
|
return;
|
|
6870
6880
|
case "\x1B[A":
|
|
@@ -6878,21 +6888,21 @@ async function interactiveMode(result, config) {
|
|
|
6878
6888
|
case "o": {
|
|
6879
6889
|
const template = allActions.open;
|
|
6880
6890
|
if (template) {
|
|
6881
|
-
state.message = await runAction("open", template, pr, state);
|
|
6891
|
+
state.message = await runAction("open", template, pr, state, onData);
|
|
6882
6892
|
}
|
|
6883
6893
|
break;
|
|
6884
6894
|
}
|
|
6885
6895
|
case "r": {
|
|
6886
6896
|
const template = allActions.review;
|
|
6887
6897
|
if (template) {
|
|
6888
|
-
state.message = await runAction("review", template, pr, state);
|
|
6898
|
+
state.message = await runAction("review", template, pr, state, onData);
|
|
6889
6899
|
}
|
|
6890
6900
|
break;
|
|
6891
6901
|
}
|
|
6892
6902
|
case "n": {
|
|
6893
6903
|
const template = allActions.nudge;
|
|
6894
6904
|
if (template) {
|
|
6895
|
-
state.message = await runAction("nudge", template, pr, state);
|
|
6905
|
+
state.message = await runAction("nudge", template, pr, state, onData);
|
|
6896
6906
|
}
|
|
6897
6907
|
break;
|
|
6898
6908
|
}
|
|
@@ -6920,7 +6930,8 @@ async function interactiveMode(result, config) {
|
|
|
6920
6930
|
break;
|
|
6921
6931
|
}
|
|
6922
6932
|
render(state);
|
|
6923
|
-
}
|
|
6933
|
+
};
|
|
6934
|
+
resume(state, onData);
|
|
6924
6935
|
});
|
|
6925
6936
|
}
|
|
6926
6937
|
|