@detent/cli 0.0.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 ADDED
@@ -0,0 +1,45 @@
1
+ # Detent CLI - npm Distribution
2
+
3
+ Run GitHub Actions locally with intelligent error troubleshooting. Detent executes workflows, parses errors, categorizes them intelligently, and leverages Claude AI with parallel iterations to troubleshoot issues automatically.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g @detent/cli
9
+ ```
10
+
11
+ After installation, the `dt` command will be available globally.
12
+
13
+ ## Usage
14
+
15
+ ```bash
16
+ dt --help
17
+ dt --version
18
+ ```
19
+
20
+ ## How It Works
21
+
22
+ Detent streamlines your CI/CD development workflow:
23
+
24
+ 1. **Local Execution**: Runs GitHub Actions workflows on your local machine
25
+ 2. **Error Detection**: Automatically parses and extracts errors from workflow outputs
26
+ 3. **Smart Categorization**: Intelligently groups and categorizes error types
27
+ 4. **AI Troubleshooting**: Prompts Claude in parallel with multiple iterations to diagnose and suggest fixes
28
+ 5. **Iterative Refinement**: Continues troubleshooting across multiple rounds until issues are resolved
29
+
30
+ ### Binary Distribution
31
+
32
+ This npm package automatically downloads the appropriate pre-built Go binary for your platform during installation:
33
+
34
+ - Linux: amd64, arm64
35
+ - macOS: amd64 (Intel), arm64 (Apple Silicon)
36
+ - Windows: amd64
37
+
38
+ ## Troubleshooting
39
+
40
+ If the installation fails, you can manually download the binary from:
41
+ https://github.com/handleui/detent/releases
42
+
43
+ ## License
44
+
45
+ MIT
package/bin.js ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { spawn } = require("node:child_process");
4
+ const { join } = require("node:path");
5
+
6
+ const binPath = join(__dirname, "bin", "dt");
7
+
8
+ const child = spawn(binPath, process.argv.slice(2), { stdio: "inherit" });
9
+
10
+ child.on("exit", (code) => {
11
+ process.exit(code);
12
+ });
package/install.js ADDED
@@ -0,0 +1,124 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { existsSync, mkdirSync, chmodSync } = require("node:fs");
4
+ const { join } = require("node:path");
5
+ const { pipeline } = require("node:stream");
6
+ const { promisify } = require("node:util");
7
+ const https = require("node:https");
8
+ const { createGunzip } = require("node:zlib");
9
+ const tar = require("tar-fs");
10
+
11
+ const streamPipeline = promisify(pipeline);
12
+
13
+ const PACKAGE_JSON = require("./package.json");
14
+
15
+ const getPlatform = () => {
16
+ const platform = process.platform;
17
+ if (platform === "win32") {
18
+ return "windows";
19
+ }
20
+ if (platform === "darwin") {
21
+ return "darwin";
22
+ }
23
+ if (platform === "linux") {
24
+ return "linux";
25
+ }
26
+ throw new Error(`Unsupported platform: ${platform}`);
27
+ };
28
+
29
+ const getArch = () => {
30
+ const arch = process.arch;
31
+ if (arch === "x64") {
32
+ return "amd64";
33
+ }
34
+ if (arch === "arm64") {
35
+ return "arm64";
36
+ }
37
+ throw new Error(`Unsupported architecture: ${arch}`);
38
+ };
39
+
40
+ const getExtension = () => (process.platform === "win32" ? "zip" : "tar.gz");
41
+
42
+ const getBinaryName = () => (process.platform === "win32" ? "dt.exe" : "dt");
43
+
44
+ const download = (url) =>
45
+ new Promise((resolve, reject) => {
46
+ https
47
+ .get(url, (response) => {
48
+ if (response.statusCode === 302 || response.statusCode === 301) {
49
+ return download(response.headers.location).then(resolve, reject);
50
+ }
51
+ if (response.statusCode !== 200) {
52
+ reject(new Error(`Failed to download: ${response.statusCode}`));
53
+ return;
54
+ }
55
+ resolve(response);
56
+ })
57
+ .on("error", reject);
58
+ });
59
+
60
+ const install = async () => {
61
+ try {
62
+ const platform = getPlatform();
63
+ const arch = getArch();
64
+ const ext = getExtension();
65
+ const version = PACKAGE_JSON.version;
66
+
67
+ const url = PACKAGE_JSON.goBinary.url
68
+ .replace("{{version}}", version)
69
+ .replace("{{platform}}", platform)
70
+ .replace("{{arch}}", arch)
71
+ .replace("{{ext}}", ext);
72
+
73
+ const binDir = join(__dirname, PACKAGE_JSON.goBinary.path);
74
+ const binaryName = getBinaryName();
75
+ const binaryPath = join(binDir, binaryName);
76
+
77
+ if (!existsSync(binDir)) {
78
+ mkdirSync(binDir, { recursive: true });
79
+ }
80
+
81
+ console.log(`Downloading binary from ${url}...`);
82
+
83
+ const response = await download(url);
84
+
85
+ if (process.platform === "win32") {
86
+ const AdmZip = require("adm-zip");
87
+ const chunks = [];
88
+
89
+ await new Promise((resolve, reject) => {
90
+ response.on("data", (chunk) => chunks.push(chunk));
91
+ response.on("end", resolve);
92
+ response.on("error", reject);
93
+ });
94
+
95
+ const buffer = Buffer.concat(chunks);
96
+ const zip = new AdmZip(buffer);
97
+ zip.extractAllTo(binDir, true);
98
+ } else {
99
+ await streamPipeline(response, createGunzip(), tar.extract(binDir));
100
+ }
101
+
102
+ if (process.platform !== "win32") {
103
+ chmodSync(binaryPath, 0o755);
104
+ }
105
+
106
+ console.log(`Binary installed successfully at ${binaryPath}`);
107
+ } catch (error) {
108
+ console.error("Failed to install binary:", error.message);
109
+ console.error("\nYou can manually download the binary from:");
110
+ console.error(
111
+ `https://github.com/handleui/detent/releases/tag/v${PACKAGE_JSON.version}`
112
+ );
113
+
114
+ // Exit gracefully in CI or during development (version 0.0.0)
115
+ if (process.env.CI || PACKAGE_JSON.version === "0.0.0") {
116
+ console.log("Skipping binary installation in CI/development mode");
117
+ process.exit(0);
118
+ }
119
+
120
+ process.exit(1);
121
+ }
122
+ };
123
+
124
+ install();
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@detent/cli",
3
+ "version": "0.0.0",
4
+ "description": "Run GitHub Actions locally, intelligently parse errors, and troubleshoot with parallel Claude iterations",
5
+ "author": "handleui",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/handleui/detent.git",
9
+ "directory": "apps/cli"
10
+ },
11
+ "bugs": {
12
+ "url": "https://github.com/handleui/detent/issues"
13
+ },
14
+ "homepage": "https://github.com/handleui/detent#readme",
15
+ "keywords": [
16
+ "cli",
17
+ "github-actions",
18
+ "local-runner",
19
+ "error-parsing",
20
+ "ai-troubleshooting",
21
+ "claude",
22
+ "detent"
23
+ ],
24
+ "license": "MIT",
25
+ "engines": {
26
+ "node": ">=20.0.0"
27
+ },
28
+ "bin": {
29
+ "dt": "bin.js"
30
+ },
31
+ "files": [
32
+ "bin.js",
33
+ "install.js",
34
+ "uninstall.js",
35
+ "bin/",
36
+ "README.md"
37
+ ],
38
+ "scripts": {
39
+ "build": "sh -c 'VERSION=$(node -p \"require(\\\"./package.json\\\").version\") && go build -ldflags \"-X github.com/detent/cli/cmd.Version=$VERSION\" -o dist/dt'",
40
+ "clean": "rm -rf dist bin",
41
+ "prepare-release": "npm run clean && mkdir -p bin",
42
+ "postinstall": "node ./install.js",
43
+ "preuninstall": "node ./uninstall.js"
44
+ },
45
+ "dependencies": {
46
+ "tar-fs": "^3.0.6",
47
+ "adm-zip": "^0.5.16"
48
+ },
49
+ "publishConfig": {
50
+ "access": "public",
51
+ "registry": "https://registry.npmjs.org/"
52
+ },
53
+ "goBinary": {
54
+ "name": "dt",
55
+ "path": "./bin",
56
+ "url": "https://github.com/handleui/detent/releases/download/v{{version}}/dt-{{platform}}-{{arch}}.{{ext}}"
57
+ }
58
+ }
package/uninstall.js ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { existsSync, rmSync } = require("node:fs");
4
+ const { join } = require("node:path");
5
+
6
+ const PACKAGE_JSON = require("./package.json");
7
+
8
+ const uninstall = () => {
9
+ const binDir = join(__dirname, PACKAGE_JSON.goBinary.path);
10
+
11
+ if (existsSync(binDir)) {
12
+ rmSync(binDir, { recursive: true, force: true });
13
+ console.log("Binary uninstalled successfully");
14
+ }
15
+ };
16
+
17
+ uninstall();