@qrafty-ai/opencode-kanban 0.0.0-dev
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 +79 -0
- package/npm/bin/opencode-kanban.js +116 -0
- package/package.json +28 -0
package/README.md
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# opencode-kanban
|
|
2
|
+
|
|
3
|
+
A Rust terminal kanban board for managing Git worktrees and OpenCode tmux sessions.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- TUI task board for OpenCode session workflows
|
|
8
|
+
- Git worktree management from the board
|
|
9
|
+
- tmux-first workflow with quick session switching
|
|
10
|
+
- SQLite-backed state and task metadata
|
|
11
|
+
|
|
12
|
+
## Requirements
|
|
13
|
+
|
|
14
|
+
- Linux or macOS
|
|
15
|
+
- `tmux` installed and available on `PATH`
|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
### npm
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install -g opencode-kanban
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Build from source
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
cargo build --release
|
|
29
|
+
./target/release/opencode-kanban
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Run
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
opencode-kanban
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
If you run the CLI outside tmux, it creates or attaches to an `opencode-kanban` tmux session automatically.
|
|
39
|
+
|
|
40
|
+
## Local development
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
cargo test
|
|
44
|
+
cargo clippy -- -D warnings
|
|
45
|
+
cargo build --release
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## npm release process
|
|
49
|
+
|
|
50
|
+
Publishing is handled by `.github/workflows/publish-npm.yaml` and uses npm trusted publishing via GitHub OIDC.
|
|
51
|
+
|
|
52
|
+
1. Create and push a release tag:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
git tag -a v0.1.0 -m "Release v0.1.0"
|
|
56
|
+
git push origin v0.1.0
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
For prereleases, use `vX.Y.Z-alpha.N` tags.
|
|
60
|
+
|
|
61
|
+
The workflow derives the package version from the tag (or manual dispatch input) and updates `Cargo.toml` during CI before building.
|
|
62
|
+
|
|
63
|
+
The workflow builds platform binaries, packages npm tarballs, and publishes:
|
|
64
|
+
|
|
65
|
+
- `opencode-kanban` (main package)
|
|
66
|
+
- platform-tagged variants for Linux x64, macOS x64, and macOS arm64
|
|
67
|
+
|
|
68
|
+
## First-time npm setup
|
|
69
|
+
|
|
70
|
+
In npm package settings, configure a Trusted Publisher for this repository and workflow file:
|
|
71
|
+
|
|
72
|
+
- Repository: this GitHub repository
|
|
73
|
+
- Workflow: `.github/workflows/publish-npm.yaml`
|
|
74
|
+
|
|
75
|
+
No `NPM_TOKEN` secret is required when trusted publishing is configured.
|
|
76
|
+
|
|
77
|
+
## License
|
|
78
|
+
|
|
79
|
+
MIT
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { spawn } from "node:child_process";
|
|
4
|
+
import { existsSync } from "node:fs";
|
|
5
|
+
import { createRequire } from "node:module";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
8
|
+
|
|
9
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
+
const __dirname = path.dirname(__filename);
|
|
11
|
+
const require = createRequire(import.meta.url);
|
|
12
|
+
|
|
13
|
+
const PLATFORM_PACKAGE_BY_TARGET = {
|
|
14
|
+
"x86_64-unknown-linux-gnu": "opencode-kanban-linux-x64",
|
|
15
|
+
"x86_64-apple-darwin": "opencode-kanban-darwin-x64",
|
|
16
|
+
"aarch64-apple-darwin": "opencode-kanban-darwin-arm64",
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
function detectTargetTriple() {
|
|
20
|
+
const { platform, arch } = process;
|
|
21
|
+
|
|
22
|
+
if (platform === "linux" && arch === "x64") {
|
|
23
|
+
return "x86_64-unknown-linux-gnu";
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (platform === "darwin" && arch === "x64") {
|
|
27
|
+
return "x86_64-apple-darwin";
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (platform === "darwin" && arch === "arm64") {
|
|
31
|
+
return "aarch64-apple-darwin";
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
throw new Error(`Unsupported platform: ${platform} (${arch})`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function detectPackageManager() {
|
|
38
|
+
const userAgent = process.env.npm_config_user_agent || "";
|
|
39
|
+
if (/\bbun\//.test(userAgent)) {
|
|
40
|
+
return "bun";
|
|
41
|
+
}
|
|
42
|
+
return "npm";
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const targetTriple = detectTargetTriple();
|
|
46
|
+
const platformPackage = PLATFORM_PACKAGE_BY_TARGET[targetTriple];
|
|
47
|
+
const binaryName = process.platform === "win32" ? "opencode-kanban.exe" : "opencode-kanban";
|
|
48
|
+
const localVendorRoot = path.join(__dirname, "..", "vendor");
|
|
49
|
+
const localBinaryPath = path.join(
|
|
50
|
+
localVendorRoot,
|
|
51
|
+
targetTriple,
|
|
52
|
+
"opencode-kanban",
|
|
53
|
+
binaryName,
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
let vendorRoot;
|
|
57
|
+
try {
|
|
58
|
+
const packageJsonPath = require.resolve(`${platformPackage}/package.json`);
|
|
59
|
+
vendorRoot = path.join(path.dirname(packageJsonPath), "vendor");
|
|
60
|
+
} catch {
|
|
61
|
+
if (existsSync(localBinaryPath)) {
|
|
62
|
+
vendorRoot = localVendorRoot;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (!vendorRoot) {
|
|
67
|
+
const packageManager = detectPackageManager();
|
|
68
|
+
const updateCommand =
|
|
69
|
+
packageManager === "bun"
|
|
70
|
+
? "bun install -g opencode-kanban@latest"
|
|
71
|
+
: "npm install -g opencode-kanban@latest";
|
|
72
|
+
throw new Error(
|
|
73
|
+
`Missing optional dependency ${platformPackage}. Reinstall opencode-kanban: ${updateCommand}`,
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const binaryPath = path.join(vendorRoot, targetTriple, "opencode-kanban", binaryName);
|
|
78
|
+
const child = spawn(binaryPath, process.argv.slice(2), {
|
|
79
|
+
stdio: "inherit",
|
|
80
|
+
env: process.env,
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
child.on("error", (error) => {
|
|
84
|
+
console.error(error);
|
|
85
|
+
process.exit(1);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
const forwardSignal = (signal) => {
|
|
89
|
+
if (child.killed) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
try {
|
|
93
|
+
child.kill(signal);
|
|
94
|
+
} catch {
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
["SIGINT", "SIGTERM", "SIGHUP"].forEach((signal) => {
|
|
99
|
+
process.on(signal, () => forwardSignal(signal));
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
const childResult = await new Promise((resolve) => {
|
|
103
|
+
child.on("exit", (code, signal) => {
|
|
104
|
+
if (signal) {
|
|
105
|
+
resolve({ type: "signal", signal });
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
resolve({ type: "code", exitCode: code ?? 1 });
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
if (childResult.type === "signal") {
|
|
113
|
+
process.kill(process.pid, childResult.signal);
|
|
114
|
+
} else {
|
|
115
|
+
process.exit(childResult.exitCode);
|
|
116
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@qrafty-ai/opencode-kanban",
|
|
3
|
+
"version": "0.0.0-dev",
|
|
4
|
+
"description": "Terminal kanban board for managing OpenCode tmux sessions",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"opencode-kanban": "npm/bin/opencode-kanban.js"
|
|
9
|
+
},
|
|
10
|
+
"engines": {
|
|
11
|
+
"node": ">=18"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"npm/bin",
|
|
15
|
+
"vendor"
|
|
16
|
+
],
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "https://github.com/qrafty-ai/opencode-kanban.git"
|
|
20
|
+
},
|
|
21
|
+
"homepage": "https://github.com/qrafty-ai/opencode-kanban#readme",
|
|
22
|
+
"bugs": {
|
|
23
|
+
"url": "https://github.com/qrafty-ai/opencode-kanban/issues"
|
|
24
|
+
},
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public"
|
|
27
|
+
}
|
|
28
|
+
}
|