@devboxer/cli 0.1.21 → 0.3.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 +5 -5
- package/dist/index.js +84 -21
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# DevBoxer CLI
|
|
2
2
|
|
|
3
|
-
 [![npm]](https://www.npmjs.com/package/@
|
|
3
|
+
 [![npm]](https://www.npmjs.com/package/@devboxer/cli)
|
|
4
4
|
|
|
5
|
-
[npm]: https://img.shields.io/npm/v/@
|
|
5
|
+
[npm]: https://img.shields.io/npm/v/@devboxer/cli.svg?style=flat-square
|
|
6
6
|
|
|
7
7
|
The official CLI for DevBoxer - your AI-powered coding assistant.
|
|
8
8
|
|
|
@@ -10,13 +10,13 @@ The official CLI for DevBoxer - your AI-powered coding assistant.
|
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
12
|
# Using npm
|
|
13
|
-
npm install -g @
|
|
13
|
+
npm install -g @devboxer/cli
|
|
14
14
|
|
|
15
15
|
# Using pnpm
|
|
16
|
-
pnpm add -g @
|
|
16
|
+
pnpm add -g @devboxer/cli
|
|
17
17
|
|
|
18
18
|
# Using yarn
|
|
19
|
-
yarn global add @
|
|
19
|
+
yarn global add @devboxer/cli
|
|
20
20
|
```
|
|
21
21
|
|
|
22
22
|
## Commands
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,7 @@ import React9 from "react";
|
|
|
7
7
|
import { readFile } from "fs/promises";
|
|
8
8
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
9
9
|
import { dirname as dirname2, join as join4 } from "path";
|
|
10
|
+
import { createInterface } from "readline";
|
|
10
11
|
|
|
11
12
|
// src/commands/auth.tsx
|
|
12
13
|
import React, { useState, useEffect } from "react";
|
|
@@ -523,7 +524,7 @@ async function saveSessionData(sessionId, cwdWithHyphens, jsonl) {
|
|
|
523
524
|
await fs2.writeFile(jsonlPath, jsonlContent);
|
|
524
525
|
return jsonlPath;
|
|
525
526
|
}
|
|
526
|
-
async function processSessionData(data, setProcessingStatus, onComplete) {
|
|
527
|
+
async function processSessionData(data, setProcessingStatus, onComplete, sessionOnly) {
|
|
527
528
|
try {
|
|
528
529
|
setProcessingStatus("Finding git repository root...");
|
|
529
530
|
const { gitRoot, error: gitError } = await findGitRoot();
|
|
@@ -532,7 +533,7 @@ async function processSessionData(data, setProcessingStatus, onComplete) {
|
|
|
532
533
|
}
|
|
533
534
|
process.chdir(gitRoot);
|
|
534
535
|
setProcessingStatus(`Changed to git root: ${gitRoot}`);
|
|
535
|
-
if (data.branchName) {
|
|
536
|
+
if (data.branchName && !sessionOnly) {
|
|
536
537
|
setProcessingStatus(
|
|
537
538
|
`Pulling latest version of branch: ${data.branchName}`
|
|
538
539
|
);
|
|
@@ -540,11 +541,23 @@ async function processSessionData(data, setProcessingStatus, onComplete) {
|
|
|
540
541
|
data.branchName
|
|
541
542
|
);
|
|
542
543
|
if (!success) {
|
|
543
|
-
|
|
544
|
+
if (!data.hasChanges) {
|
|
545
|
+
setProcessingStatus(
|
|
546
|
+
`\u2139 This is a plan-only session with no code changes`
|
|
547
|
+
);
|
|
548
|
+
setProcessingStatus(
|
|
549
|
+
` Pulling conversation history only (skipping git checkout)`
|
|
550
|
+
);
|
|
551
|
+
} else {
|
|
552
|
+
return { success: false, error: branchError };
|
|
553
|
+
}
|
|
554
|
+
} else {
|
|
555
|
+
setProcessingStatus(
|
|
556
|
+
`Successfully switched to branch: ${data.branchName}`
|
|
557
|
+
);
|
|
544
558
|
}
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
);
|
|
559
|
+
} else if (sessionOnly && data.branchName) {
|
|
560
|
+
setProcessingStatus(`Skipping git operations (--session-only mode)`);
|
|
548
561
|
}
|
|
549
562
|
const cwd = process.cwd();
|
|
550
563
|
const cwdWithHyphens = cwd.replace(/\//g, "-");
|
|
@@ -576,7 +589,8 @@ async function processSessionData(data, setProcessingStatus, onComplete) {
|
|
|
576
589
|
}
|
|
577
590
|
function PullCommand({
|
|
578
591
|
threadId,
|
|
579
|
-
resume
|
|
592
|
+
resume,
|
|
593
|
+
sessionOnly
|
|
580
594
|
}) {
|
|
581
595
|
const [selectedThreadId, setSelectedThreadId] = useState3(
|
|
582
596
|
threadId
|
|
@@ -609,7 +623,8 @@ function PullCommand({
|
|
|
609
623
|
launchClaude(sessionId);
|
|
610
624
|
}, 100);
|
|
611
625
|
}
|
|
612
|
-
}
|
|
626
|
+
},
|
|
627
|
+
sessionOnly
|
|
613
628
|
);
|
|
614
629
|
if (!result.success) {
|
|
615
630
|
setProcessingError(result.error || "Unknown error during processing");
|
|
@@ -617,7 +632,7 @@ function PullCommand({
|
|
|
617
632
|
}
|
|
618
633
|
};
|
|
619
634
|
process2();
|
|
620
|
-
}, [sessionData, resume]);
|
|
635
|
+
}, [sessionData, resume, sessionOnly]);
|
|
621
636
|
const handleThreadSelect = (threadId2) => {
|
|
622
637
|
setSelectedThreadId(threadId2);
|
|
623
638
|
};
|
|
@@ -647,7 +662,7 @@ function PullCommand({
|
|
|
647
662
|
|
|
648
663
|
// src/commands/create.tsx
|
|
649
664
|
import React4, { useState as useState4, useEffect as useEffect3 } from "react";
|
|
650
|
-
import { Box as Box4, Text as Text4 } from "ink";
|
|
665
|
+
import { Box as Box4, Text as Text4, useApp } from "ink";
|
|
651
666
|
import Spinner3 from "ink-spinner";
|
|
652
667
|
import { useMutation as useMutation2 } from "@tanstack/react-query";
|
|
653
668
|
function CreateCommand({
|
|
@@ -658,6 +673,7 @@ function CreateCommand({
|
|
|
658
673
|
mode = "execute",
|
|
659
674
|
model
|
|
660
675
|
}) {
|
|
676
|
+
const { exit } = useApp();
|
|
661
677
|
const [error, setError] = useState4(null);
|
|
662
678
|
const gitInfo = useGitInfo();
|
|
663
679
|
const createMutation = useMutation2({
|
|
@@ -690,6 +706,16 @@ function CreateCommand({
|
|
|
690
706
|
createMutation.mutate();
|
|
691
707
|
}
|
|
692
708
|
}, [gitInfo.isLoading]);
|
|
709
|
+
useEffect3(() => {
|
|
710
|
+
if (createMutation.isSuccess) {
|
|
711
|
+
exit();
|
|
712
|
+
}
|
|
713
|
+
}, [createMutation.isSuccess, exit]);
|
|
714
|
+
useEffect3(() => {
|
|
715
|
+
if (createMutation.isError || error) {
|
|
716
|
+
exit();
|
|
717
|
+
}
|
|
718
|
+
}, [createMutation.isError, error, exit]);
|
|
693
719
|
if (gitInfo.isLoading || createMutation.isPending) {
|
|
694
720
|
return /* @__PURE__ */ React4.createElement(Box4, { flexDirection: "column" }, /* @__PURE__ */ React4.createElement(Text4, null, /* @__PURE__ */ React4.createElement(Spinner3, { type: "dots" }), " ", gitInfo.isLoading ? "Detecting repository..." : "Creating new task..."));
|
|
695
721
|
}
|
|
@@ -705,9 +731,9 @@ function CreateCommand({
|
|
|
705
731
|
|
|
706
732
|
// src/commands/list.tsx
|
|
707
733
|
import React5, { useEffect as useEffect4, useState as useState5 } from "react";
|
|
708
|
-
import { Box as Box5, Text as Text5, useApp } from "ink";
|
|
734
|
+
import { Box as Box5, Text as Text5, useApp as useApp2 } from "ink";
|
|
709
735
|
function ListCommand() {
|
|
710
|
-
const { exit } =
|
|
736
|
+
const { exit } = useApp2();
|
|
711
737
|
const repoQuery = useCurrentGitHubRepo();
|
|
712
738
|
const currentRepo = repoQuery.data;
|
|
713
739
|
const {
|
|
@@ -783,7 +809,7 @@ import updateNotifier from "update-notifier";
|
|
|
783
809
|
// package.json
|
|
784
810
|
var package_default = {
|
|
785
811
|
name: "@devboxer/cli",
|
|
786
|
-
version: "0.
|
|
812
|
+
version: "0.3.0",
|
|
787
813
|
type: "module",
|
|
788
814
|
bin: {
|
|
789
815
|
devboxer: "./dist/index.js"
|
|
@@ -885,7 +911,7 @@ function UpdateNotifier() {
|
|
|
885
911
|
if (!updateInfo) {
|
|
886
912
|
return null;
|
|
887
913
|
}
|
|
888
|
-
return /* @__PURE__ */ React7.createElement(Box6, { marginBottom: 1, borderStyle: "round", borderColor: "yellow", paddingX: 1 }, /* @__PURE__ */ React7.createElement(Text6, { color: "yellow" }, "Update available: ", updateInfo.current, " \u2192 ", updateInfo.latest), /* @__PURE__ */ React7.createElement(Text6, { color: "gray" }, " Run "), /* @__PURE__ */ React7.createElement(Text6, { color: "cyan" }, "npm install -g @
|
|
914
|
+
return /* @__PURE__ */ React7.createElement(Box6, { marginBottom: 1, borderStyle: "round", borderColor: "yellow", paddingX: 1 }, /* @__PURE__ */ React7.createElement(Text6, { color: "yellow" }, "Update available: ", updateInfo.current, " \u2192 ", updateInfo.latest), /* @__PURE__ */ React7.createElement(Text6, { color: "gray" }, " Run "), /* @__PURE__ */ React7.createElement(Text6, { color: "cyan" }, "npm install -g @devboxer/cli"), /* @__PURE__ */ React7.createElement(Text6, { color: "gray" }, " to update"));
|
|
889
915
|
}
|
|
890
916
|
|
|
891
917
|
// src/components/RootLayout.tsx
|
|
@@ -1113,17 +1139,42 @@ var __dirname2 = dirname2(__filename2);
|
|
|
1113
1139
|
var packageJson = JSON.parse(
|
|
1114
1140
|
await readFile(join4(__dirname2, "../package.json"), "utf-8")
|
|
1115
1141
|
);
|
|
1142
|
+
async function readStdin() {
|
|
1143
|
+
return new Promise((resolve2, reject) => {
|
|
1144
|
+
let data = "";
|
|
1145
|
+
const rl = createInterface({
|
|
1146
|
+
input: process.stdin,
|
|
1147
|
+
terminal: false
|
|
1148
|
+
});
|
|
1149
|
+
rl.on("line", (line) => {
|
|
1150
|
+
data += (data ? "\n" : "") + line;
|
|
1151
|
+
});
|
|
1152
|
+
rl.on("close", () => {
|
|
1153
|
+
resolve2(data.trim());
|
|
1154
|
+
});
|
|
1155
|
+
rl.on("error", reject);
|
|
1156
|
+
});
|
|
1157
|
+
}
|
|
1116
1158
|
program.name("devboxer").description("DevBoxer CLI - AI-powered coding assistant").version(packageJson.version);
|
|
1117
1159
|
program.command("auth [apiKey]").description("Authenticate with your DevBoxer API key").action((apiKey) => {
|
|
1118
1160
|
render(
|
|
1119
1161
|
/* @__PURE__ */ React9.createElement(QueryProvider, null, /* @__PURE__ */ React9.createElement(RootLayout, null, /* @__PURE__ */ React9.createElement(AuthCommand, { apiKey })))
|
|
1120
1162
|
);
|
|
1121
1163
|
});
|
|
1122
|
-
program.command("pull [threadId]").description("Fetch session data for a task").option("-r, --resume", "Automatically launch Claude after pulling").
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1164
|
+
program.command("pull [threadId]").description("Fetch session data for a task").option("-r, --resume", "Automatically launch Claude after pulling").option("-s, --session-only", "Skip git operations, only pull session data").action(
|
|
1165
|
+
(threadId, options) => {
|
|
1166
|
+
render(
|
|
1167
|
+
/* @__PURE__ */ React9.createElement(QueryProvider, null, /* @__PURE__ */ React9.createElement(RootLayout, null, /* @__PURE__ */ React9.createElement(
|
|
1168
|
+
PullCommand,
|
|
1169
|
+
{
|
|
1170
|
+
threadId,
|
|
1171
|
+
resume: options.resume,
|
|
1172
|
+
sessionOnly: options.sessionOnly
|
|
1173
|
+
}
|
|
1174
|
+
)))
|
|
1175
|
+
);
|
|
1176
|
+
}
|
|
1177
|
+
);
|
|
1127
1178
|
var CLI_MODEL_OPTIONS = [
|
|
1128
1179
|
"amp",
|
|
1129
1180
|
"haiku",
|
|
@@ -1166,11 +1217,23 @@ var CLI_MODEL_OPTIONS = [
|
|
|
1166
1217
|
"gemini-3-pro",
|
|
1167
1218
|
"gemini-2.5-pro"
|
|
1168
1219
|
];
|
|
1169
|
-
program.command("create
|
|
1220
|
+
program.command("create [message]").description(
|
|
1221
|
+
"Create a new task with the given message. Message can also be piped via stdin."
|
|
1222
|
+
).option(
|
|
1170
1223
|
"-r, --repo <repo>",
|
|
1171
1224
|
"GitHub repository (default: current repository)"
|
|
1172
1225
|
).option("-b, --branch <branch>", "Base branch name (default: current branch)").option("--no-new-branch", "Don't create a new branch").option("-m, --model <model>", `AI model: ${CLI_MODEL_OPTIONS.join(", ")}`).option("-M, --mode <mode>", "Task mode: plan or execute (default: execute)").action(
|
|
1173
|
-
(
|
|
1226
|
+
async (messageArg, options) => {
|
|
1227
|
+
let message = messageArg;
|
|
1228
|
+
if (!message && !process.stdin.isTTY) {
|
|
1229
|
+
message = await readStdin();
|
|
1230
|
+
}
|
|
1231
|
+
if (!message) {
|
|
1232
|
+
console.error(
|
|
1233
|
+
"Error: Message is required. Provide as argument or pipe via stdin."
|
|
1234
|
+
);
|
|
1235
|
+
process.exit(1);
|
|
1236
|
+
}
|
|
1174
1237
|
const mode = options.mode === "plan" ? "plan" : "execute";
|
|
1175
1238
|
let model;
|
|
1176
1239
|
if (options.model) {
|