@cubic-dev-ai/cli 0.15.0 → 0.16.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/bin/cubic +10 -0
- package/bin/cubic.cmd +11 -0
- package/bin/cubic.wrapper +71 -0
- package/package.json +12 -12
- package/postinstall.mjs +130 -34
package/bin/cubic
CHANGED
|
@@ -57,5 +57,15 @@ fi
|
|
|
57
57
|
# Handle SIGINT gracefully
|
|
58
58
|
trap '' INT
|
|
59
59
|
|
|
60
|
+
# Intercept installer command from npx wrapper context
|
|
61
|
+
if [ "$1" = "install" ]; then
|
|
62
|
+
exec "$resolved" "$@"
|
|
63
|
+
fi
|
|
64
|
+
|
|
65
|
+
# npx with no args should bootstrap setup flow in exec context
|
|
66
|
+
if [ "$#" -eq 0 ] && [ "${npm_command:-}" = "exec" ]; then
|
|
67
|
+
exec "$resolved" setup --mode install
|
|
68
|
+
fi
|
|
69
|
+
|
|
60
70
|
# Execute the binary with all arguments
|
|
61
71
|
exec "$resolved" "$@"
|
package/bin/cubic.cmd
CHANGED
|
@@ -52,6 +52,17 @@ echo It seems that your package manager failed to install the right version of t
|
|
|
52
52
|
exit /b 1
|
|
53
53
|
|
|
54
54
|
:execute
|
|
55
|
+
rem Intercept installer command from npx wrapper context
|
|
56
|
+
if "%~1"=="install" (
|
|
57
|
+
start /b /wait "" "%resolved%" %*
|
|
58
|
+
exit /b !ERRORLEVEL!
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
if "%~1"=="" if /i "%npm_command%"=="exec" (
|
|
62
|
+
start /b /wait "" "%resolved%" setup --mode install
|
|
63
|
+
exit /b !ERRORLEVEL!
|
|
64
|
+
)
|
|
65
|
+
|
|
55
66
|
rem Execute the binary with all arguments in the same console window
|
|
56
67
|
rem Use start /b /wait to ensure it runs in the current shell context for all shells
|
|
57
68
|
start /b /wait "" "%resolved%" %*
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
set -e
|
|
3
|
+
|
|
4
|
+
if [ -n "$CUBIC_BIN_PATH" ]; then
|
|
5
|
+
resolved="$CUBIC_BIN_PATH"
|
|
6
|
+
else
|
|
7
|
+
# Get the real path of this script, resolving any symlinks
|
|
8
|
+
script_path="$0"
|
|
9
|
+
while [ -L "$script_path" ]; do
|
|
10
|
+
link_target="$(readlink "$script_path")"
|
|
11
|
+
case "$link_target" in
|
|
12
|
+
/*) script_path="$link_target" ;;
|
|
13
|
+
*) script_path="$(dirname "$script_path")/$link_target" ;;
|
|
14
|
+
esac
|
|
15
|
+
done
|
|
16
|
+
script_dir="$(dirname "$script_path")"
|
|
17
|
+
script_dir="$(cd "$script_dir" && pwd)"
|
|
18
|
+
|
|
19
|
+
# Map platform names
|
|
20
|
+
case "$(uname -s)" in
|
|
21
|
+
Darwin) platform="darwin" ;;
|
|
22
|
+
Linux) platform="linux" ;;
|
|
23
|
+
MINGW*|CYGWIN*|MSYS*) platform="win32" ;;
|
|
24
|
+
*) platform="$(uname -s | tr '[:upper:]' '[:lower:]')" ;;
|
|
25
|
+
esac
|
|
26
|
+
|
|
27
|
+
# Map architecture names
|
|
28
|
+
case "$(uname -m)" in
|
|
29
|
+
x86_64|amd64) arch="x64" ;;
|
|
30
|
+
aarch64) arch="arm64" ;;
|
|
31
|
+
armv7l) arch="arm" ;;
|
|
32
|
+
*) arch="$(uname -m)" ;;
|
|
33
|
+
esac
|
|
34
|
+
|
|
35
|
+
name="@cubic-dev-ai/cli-${platform}-${arch}"
|
|
36
|
+
binary="cubic"
|
|
37
|
+
[ "$platform" = "win32" ] && binary="cubic.exe"
|
|
38
|
+
|
|
39
|
+
# Search for the binary starting from real script location
|
|
40
|
+
resolved=""
|
|
41
|
+
current_dir="$script_dir"
|
|
42
|
+
while [ "$current_dir" != "/" ]; do
|
|
43
|
+
candidate="$current_dir/node_modules/$name/bin/$binary"
|
|
44
|
+
if [ -f "$candidate" ]; then
|
|
45
|
+
resolved="$candidate"
|
|
46
|
+
break
|
|
47
|
+
fi
|
|
48
|
+
current_dir="$(dirname "$current_dir")"
|
|
49
|
+
done
|
|
50
|
+
|
|
51
|
+
if [ -z "$resolved" ]; then
|
|
52
|
+
printf "It seems that your package manager failed to install the right version of the cubic CLI for your platform. You can try manually installing the \"%s\" package\n" "$name" >&2
|
|
53
|
+
exit 1
|
|
54
|
+
fi
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
# Handle SIGINT gracefully
|
|
58
|
+
trap '' INT
|
|
59
|
+
|
|
60
|
+
# Intercept installer command from npx wrapper context
|
|
61
|
+
if [ "$1" = "install" ]; then
|
|
62
|
+
exec "$resolved" "$@"
|
|
63
|
+
fi
|
|
64
|
+
|
|
65
|
+
# npx with no args should bootstrap setup flow in exec context
|
|
66
|
+
if [ "$#" -eq 0 ] && [ "${npm_command:-}" = "exec" ]; then
|
|
67
|
+
exec "$resolved" setup --mode install
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
# Execute the binary with all arguments
|
|
71
|
+
exec "$resolved" "$@"
|
package/package.json
CHANGED
|
@@ -7,18 +7,18 @@
|
|
|
7
7
|
"preinstall": "bun ./preinstall.mjs || node ./preinstall.mjs",
|
|
8
8
|
"postinstall": "bun ./postinstall.mjs || node ./postinstall.mjs"
|
|
9
9
|
},
|
|
10
|
-
"version": "0.
|
|
10
|
+
"version": "0.16.0",
|
|
11
11
|
"optionalDependencies": {
|
|
12
|
-
"@cubic-dev-ai/cli-linux-arm64": "0.
|
|
13
|
-
"@cubic-dev-ai/cli-linux-x64": "0.
|
|
14
|
-
"@cubic-dev-ai/cli-linux-x64-baseline": "0.
|
|
15
|
-
"@cubic-dev-ai/cli-linux-arm64-musl": "0.
|
|
16
|
-
"@cubic-dev-ai/cli-linux-x64-musl": "0.
|
|
17
|
-
"@cubic-dev-ai/cli-linux-x64-baseline-musl": "0.
|
|
18
|
-
"@cubic-dev-ai/cli-darwin-arm64": "0.
|
|
19
|
-
"@cubic-dev-ai/cli-darwin-x64": "0.
|
|
20
|
-
"@cubic-dev-ai/cli-darwin-x64-baseline": "0.
|
|
21
|
-
"@cubic-dev-ai/cli-windows-x64": "0.
|
|
22
|
-
"@cubic-dev-ai/cli-windows-x64-baseline": "0.
|
|
12
|
+
"@cubic-dev-ai/cli-linux-arm64": "0.16.0",
|
|
13
|
+
"@cubic-dev-ai/cli-linux-x64": "0.16.0",
|
|
14
|
+
"@cubic-dev-ai/cli-linux-x64-baseline": "0.16.0",
|
|
15
|
+
"@cubic-dev-ai/cli-linux-arm64-musl": "0.16.0",
|
|
16
|
+
"@cubic-dev-ai/cli-linux-x64-musl": "0.16.0",
|
|
17
|
+
"@cubic-dev-ai/cli-linux-x64-baseline-musl": "0.16.0",
|
|
18
|
+
"@cubic-dev-ai/cli-darwin-arm64": "0.16.0",
|
|
19
|
+
"@cubic-dev-ai/cli-darwin-x64": "0.16.0",
|
|
20
|
+
"@cubic-dev-ai/cli-darwin-x64-baseline": "0.16.0",
|
|
21
|
+
"@cubic-dev-ai/cli-windows-x64": "0.16.0",
|
|
22
|
+
"@cubic-dev-ai/cli-windows-x64-baseline": "0.16.0"
|
|
23
23
|
}
|
|
24
24
|
}
|
package/postinstall.mjs
CHANGED
|
@@ -5,7 +5,26 @@ import path from "path"
|
|
|
5
5
|
import os from "os"
|
|
6
6
|
import { fileURLToPath } from "url"
|
|
7
7
|
import { createRequire } from "module"
|
|
8
|
-
import { execSync } from "child_process"
|
|
8
|
+
import { execFileSync, execSync } from "child_process"
|
|
9
|
+
|
|
10
|
+
const CUBIC_WRAPPER_MODE = process.env.CUBIC_WRAPPER_MODE !== "0"
|
|
11
|
+
|
|
12
|
+
function packagePrefix() {
|
|
13
|
+
return process.env.CUBIC_PACKAGE_PREFIX || "@cubic-dev-ai/cli-"
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function shouldRunInstallWizard() {
|
|
17
|
+
if (process.env.CUBIC_DISABLE_INSTALL_WIZARD === "true") return false
|
|
18
|
+
if (process.env.npm_config_ignore_scripts === "true") return false
|
|
19
|
+
if (process.env.CI && process.env.CI !== "false") return false
|
|
20
|
+
if (process.env.npm_config_yes === "true") return false
|
|
21
|
+
if (process.env.TERM === "dumb") return false
|
|
22
|
+
if (!process.stdin.isTTY) return false
|
|
23
|
+
if (!process.stdout.isTTY) return false
|
|
24
|
+
if (process.platform === "win32") return false
|
|
25
|
+
if (!fs.existsSync("/dev/tty")) return false
|
|
26
|
+
return true
|
|
27
|
+
}
|
|
9
28
|
|
|
10
29
|
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
11
30
|
const require = createRequire(import.meta.url)
|
|
@@ -26,9 +45,9 @@ try {
|
|
|
26
45
|
// Use fallback
|
|
27
46
|
}
|
|
28
47
|
|
|
29
|
-
// Validate version format to prevent command injection (must be
|
|
48
|
+
// Validate version format to prevent command injection (must be [v]X.Y.Z format)
|
|
30
49
|
function isValidVersion(version) {
|
|
31
|
-
return /^v
|
|
50
|
+
return /^v?\d+\.\d+\.\d+$/.test(version)
|
|
32
51
|
}
|
|
33
52
|
|
|
34
53
|
if (!isValidVersion(GIT_AI_VERSION)) {
|
|
@@ -76,7 +95,7 @@ function detectPlatformAndArch() {
|
|
|
76
95
|
|
|
77
96
|
function findBinary() {
|
|
78
97
|
const { platform, arch } = detectPlatformAndArch()
|
|
79
|
-
const packageName =
|
|
98
|
+
const packageName = `${packagePrefix()}${platform}-${arch}`
|
|
80
99
|
const binary = platform === "windows" ? "cubic.exe" : "cubic"
|
|
81
100
|
|
|
82
101
|
try {
|
|
@@ -123,52 +142,93 @@ async function regenerateWindowsCmdWrappers() {
|
|
|
123
142
|
}
|
|
124
143
|
}
|
|
125
144
|
|
|
126
|
-
// Install git-ai using official installer
|
|
145
|
+
// Install git-ai silently using official installer
|
|
127
146
|
// 2 minute timeout to prevent indefinite hangs during npm install
|
|
128
147
|
const GIT_AI_INSTALL_TIMEOUT = 120000
|
|
148
|
+
const GIT_AI_COMPATIBLE_MAJOR = 1
|
|
149
|
+
const GIT_AI_REPO_URL = "https://github.com/git-ai-project/git-ai"
|
|
150
|
+
|
|
151
|
+
function getGitAiBinary() {
|
|
152
|
+
return path.join(os.homedir(), ".git-ai", "bin", os.platform() === "win32" ? "git-ai.exe" : "git-ai")
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Returns "none", "compatible", or "incompatible"
|
|
156
|
+
function checkGitAiVersion() {
|
|
157
|
+
const binary = getGitAiBinary()
|
|
158
|
+
try {
|
|
159
|
+
fs.accessSync(binary, fs.constants.X_OK)
|
|
160
|
+
} catch {
|
|
161
|
+
return "none"
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
try {
|
|
165
|
+
const version = execSync(`"${binary}" --version`, { stdio: ["pipe", "pipe", "pipe"], timeout: 5000 })
|
|
166
|
+
.toString()
|
|
167
|
+
.trim()
|
|
168
|
+
const match = version.match(/^v?(\d+)\./)
|
|
169
|
+
if (!match) return "none"
|
|
170
|
+
return parseInt(match[1], 10) === GIT_AI_COMPATIBLE_MAJOR ? "compatible" : "incompatible"
|
|
171
|
+
} catch {
|
|
172
|
+
return "none"
|
|
173
|
+
}
|
|
174
|
+
}
|
|
129
175
|
|
|
130
176
|
function setupGitAi() {
|
|
131
177
|
// Allow users to opt-out of automatic git-ai installation
|
|
132
178
|
if (process.env.CUBIC_DISABLE_GIT_AI === "true") {
|
|
133
|
-
console.log("Skipping git-ai installation (CUBIC_DISABLE_GIT_AI=true)")
|
|
134
|
-
console.log("You can install it later with: cubic stats enable")
|
|
135
179
|
return
|
|
136
180
|
}
|
|
137
181
|
|
|
138
|
-
|
|
182
|
+
const status = checkGitAiVersion()
|
|
183
|
+
|
|
184
|
+
// Already have a compatible version — nothing to do
|
|
185
|
+
if (status === "compatible") return
|
|
139
186
|
|
|
187
|
+
// Incompatible version — warn and skip
|
|
188
|
+
if (status === "incompatible") {
|
|
189
|
+
console.warn(
|
|
190
|
+
"git-ai is already installed, but this version is incompatible with cubic AI stats. " +
|
|
191
|
+
"Please uninstall git-ai and run `cubic stats enable` to install a compatible version. " +
|
|
192
|
+
GIT_AI_REPO_URL,
|
|
193
|
+
)
|
|
194
|
+
return
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Not installed — install silently
|
|
140
198
|
try {
|
|
141
199
|
if (os.platform() === "win32") {
|
|
142
|
-
// PowerShell installer for Windows
|
|
143
200
|
execSync(
|
|
144
201
|
`powershell -NoProfile -ExecutionPolicy Bypass -Command "$env:GIT_AI_RELEASE_TAG='${GIT_AI_VERSION}'; irm https://usegitai.com/install.ps1 | iex"`,
|
|
145
|
-
{ stdio: "
|
|
202
|
+
{ stdio: "ignore", shell: true, timeout: GIT_AI_INSTALL_TIMEOUT },
|
|
146
203
|
)
|
|
147
204
|
} else {
|
|
148
|
-
// Bash installer for macOS/Linux
|
|
149
205
|
execSync(`export GIT_AI_RELEASE_TAG="${GIT_AI_VERSION}" && curl -sSL https://usegitai.com/install.sh | bash`, {
|
|
150
|
-
stdio: "
|
|
206
|
+
stdio: "ignore",
|
|
151
207
|
shell: "/bin/bash",
|
|
152
208
|
timeout: GIT_AI_INSTALL_TIMEOUT,
|
|
153
209
|
})
|
|
154
210
|
}
|
|
155
211
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
// Configure git-ai to run in quiet mode (suppress chart output after commits)
|
|
159
|
-
const gitAiBinary = path.join(os.homedir(), ".git-ai", "bin", os.platform() === "win32" ? "git-ai.exe" : "git-ai")
|
|
212
|
+
// Configure git-ai to run in quiet mode
|
|
213
|
+
const binary = getGitAiBinary()
|
|
160
214
|
try {
|
|
161
|
-
execSync(`"${
|
|
215
|
+
execSync(`"${binary}" config set quiet true`, { stdio: "ignore", timeout: 5000 })
|
|
162
216
|
} catch {
|
|
163
217
|
// Ignore if config fails - git-ai will work without quiet mode
|
|
164
218
|
}
|
|
219
|
+
|
|
220
|
+
console.log("Close and reopen your IDE and terminal sessions in order to use AI attribution stats.")
|
|
165
221
|
} catch (error) {
|
|
166
|
-
console.warn(
|
|
167
|
-
|
|
222
|
+
console.warn(
|
|
223
|
+
"cubic AI stats use git-ai under the hood. git-ai failed to install. " +
|
|
224
|
+
"Make sure git-ai installation succeeds in order to use cubic AI stats. " +
|
|
225
|
+
GIT_AI_REPO_URL,
|
|
226
|
+
)
|
|
168
227
|
}
|
|
169
228
|
}
|
|
170
229
|
|
|
171
230
|
async function main() {
|
|
231
|
+
let binaryPath = ""
|
|
172
232
|
try {
|
|
173
233
|
if (os.platform() === "win32") {
|
|
174
234
|
// NPM eg format - npm/11.4.2 node/v24.4.1 win32 x64
|
|
@@ -178,29 +238,65 @@ async function main() {
|
|
|
178
238
|
} else {
|
|
179
239
|
console.log("Windows detected but not npm, skipping binary symlink")
|
|
180
240
|
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
241
|
+
} else {
|
|
242
|
+
try {
|
|
243
|
+
binaryPath = findBinary()
|
|
244
|
+
} catch (error) {
|
|
245
|
+
const message = error instanceof Error ? error.message : String(error)
|
|
246
|
+
console.log(
|
|
247
|
+
`cubic: setup skipped (${message}) - run \`npm i -g @cubic-plugin/cli-manila-test\` again in a minute`,
|
|
248
|
+
)
|
|
249
|
+
return
|
|
250
|
+
}
|
|
251
|
+
const binScript = path.join(__dirname, "bin", "cubic")
|
|
252
|
+
const wrapperPath = path.join(__dirname, "bin", "cubic.wrapper")
|
|
185
253
|
|
|
186
|
-
|
|
187
|
-
|
|
254
|
+
if (CUBIC_WRAPPER_MODE && fs.existsSync(wrapperPath)) {
|
|
255
|
+
if (fs.existsSync(binScript)) {
|
|
256
|
+
fs.unlinkSync(binScript)
|
|
257
|
+
}
|
|
258
|
+
fs.copyFileSync(wrapperPath, binScript)
|
|
259
|
+
fs.chmodSync(binScript, 0o755)
|
|
260
|
+
process.env.CUBIC_BIN_PATH = binaryPath
|
|
261
|
+
console.log(`cubic wrapper configured: ${binScript} -> ${binaryPath}`)
|
|
262
|
+
} else {
|
|
263
|
+
// Remove existing bin script if it exists
|
|
264
|
+
if (fs.existsSync(binScript)) {
|
|
265
|
+
fs.unlinkSync(binScript)
|
|
266
|
+
}
|
|
188
267
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
268
|
+
// Create symlink to the actual binary
|
|
269
|
+
fs.symlinkSync(binaryPath, binScript)
|
|
270
|
+
console.log(`cubic binary symlinked: ${binScript} -> ${binaryPath}`)
|
|
271
|
+
}
|
|
192
272
|
}
|
|
193
273
|
|
|
194
|
-
//
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
274
|
+
// Install-time wizard (opt-in)
|
|
275
|
+
if (shouldRunInstallWizard()) {
|
|
276
|
+
console.log("\n◆ Optional: connect cubic to your coding agent")
|
|
277
|
+
try {
|
|
278
|
+
execFileSync(binaryPath, ["setup", "--mode", "install-time"], {
|
|
279
|
+
stdio: "inherit",
|
|
280
|
+
timeout: 60000,
|
|
281
|
+
env: {
|
|
282
|
+
...process.env,
|
|
283
|
+
CUBIC_INSTALL_TTY: "0",
|
|
284
|
+
},
|
|
285
|
+
})
|
|
286
|
+
} catch (error) {
|
|
287
|
+
const m = error instanceof Error ? error.message : String(error)
|
|
288
|
+
console.log(`cubic: setup skipped (${m}) - run \`cubic setup\` later`)
|
|
289
|
+
}
|
|
290
|
+
} else {
|
|
291
|
+
console.log("cubic: Run `cubic setup` to connect your coding agent")
|
|
292
|
+
}
|
|
200
293
|
} catch (error) {
|
|
201
294
|
console.error("Failed to create cubic binary symlink:", error.message)
|
|
202
295
|
process.exit(1)
|
|
203
296
|
}
|
|
297
|
+
|
|
298
|
+
// Only install git-ai after cubic binary is confirmed working
|
|
299
|
+
setupGitAi()
|
|
204
300
|
}
|
|
205
301
|
|
|
206
302
|
try {
|