@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.
Files changed (3) hide show
  1. package/README.md +5 -5
  2. package/dist/index.js +84 -21
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # DevBoxer CLI
2
2
 
3
- ![](https://img.shields.io/badge/Node.js-18%2B-brightgreen?style=flat-square) [![npm]](https://www.npmjs.com/package/@devboxerhub/cli)
3
+ ![](https://img.shields.io/badge/Node.js-18%2B-brightgreen?style=flat-square) [![npm]](https://www.npmjs.com/package/@devboxer/cli)
4
4
 
5
- [npm]: https://img.shields.io/npm/v/@devboxerhub/cli.svg?style=flat-square
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 @devboxerhub/cli
13
+ npm install -g @devboxer/cli
14
14
 
15
15
  # Using pnpm
16
- pnpm add -g @devboxerhub/cli
16
+ pnpm add -g @devboxer/cli
17
17
 
18
18
  # Using yarn
19
- yarn global add @devboxerhub/cli
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
- return { success: false, error: branchError };
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
- setProcessingStatus(
546
- `Successfully switched to branch: ${data.branchName}`
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 } = useApp();
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.1.21",
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 @devboxerhub/cli"), /* @__PURE__ */ React7.createElement(Text6, { color: "gray" }, " to update"));
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").action((threadId, options) => {
1123
- render(
1124
- /* @__PURE__ */ React9.createElement(QueryProvider, null, /* @__PURE__ */ React9.createElement(RootLayout, null, /* @__PURE__ */ React9.createElement(PullCommand, { threadId, resume: options.resume })))
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 <message>").description("Create a new task with the given message").option(
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
- (message, options) => {
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) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devboxer/cli",
3
- "version": "0.1.21",
3
+ "version": "0.3.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "devboxer": "./dist/index.js"