opencode-dev-runner 0.1.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/setup.js +138 -0
- package/package.json +21 -0
- package/templates/dev-runner.md +105 -0
package/bin/setup.js
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const { execSync } = require('child_process');
|
|
3
|
+
const { existsSync, mkdirSync, copyFileSync, writeFileSync } = require('fs');
|
|
4
|
+
const { join } = require('path');
|
|
5
|
+
const os = require('os');
|
|
6
|
+
|
|
7
|
+
const PLATFORM = os.platform(); // 'win32' | 'darwin' | 'linux'
|
|
8
|
+
const HOME = os.homedir();
|
|
9
|
+
const AGENTS_DIR = join(process.cwd(), '.opencode', 'agents');
|
|
10
|
+
const TEMPLATE = join(__dirname, '..', 'templates', 'dev-runner.md');
|
|
11
|
+
const MAP_FILE = join(AGENTS_DIR, 'tool-map.json');
|
|
12
|
+
|
|
13
|
+
// ── tools to discover ─────────────────────────────────────────────────
|
|
14
|
+
const TOOLS = [
|
|
15
|
+
'adb', 'flutter', 'dart', 'git', 'node', 'npm', 'npx',
|
|
16
|
+
'gh', 'code', 'supabase', 'sqlite3', 'java', 'javac', 'gradle',
|
|
17
|
+
'python', 'python3', 'pip', 'pip3', 'docker', 'make',
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
const CATEGORIES = {
|
|
21
|
+
adb: 'android', emulator: 'android', sdkmanager: 'android',
|
|
22
|
+
flutter: 'flutter', dart: 'flutter',
|
|
23
|
+
git: 'vcs', gh: 'vcs',
|
|
24
|
+
node: 'node', npm: 'node', npx: 'node', yarn: 'node', pnpm: 'node',
|
|
25
|
+
supabase: 'database', psql: 'database', sqlite3: 'database',
|
|
26
|
+
code: 'editor', nvim: 'editor', vim: 'editor',
|
|
27
|
+
java: 'java', javac: 'java', gradle: 'java', mvn: 'java',
|
|
28
|
+
python: 'python', python3: 'python', pip: 'python', pip3: 'python',
|
|
29
|
+
docker: 'container', make: 'build',
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
// ── cross-platform helpers ────────────────────────────────────────────
|
|
33
|
+
|
|
34
|
+
function sh(cmd) {
|
|
35
|
+
try { return execSync(cmd, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] }).trim().split(/[\r\n]+/)[0]; }
|
|
36
|
+
catch { return null; }
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function which(tool) {
|
|
40
|
+
if (PLATFORM === 'win32') return sh(`where.exe ${tool}`);
|
|
41
|
+
return sh(`which ${tool}`) || sh(`command -v ${tool}`);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function classify(path) {
|
|
45
|
+
if (!path) return '';
|
|
46
|
+
if (path.includes('scoop')) return 'scoop';
|
|
47
|
+
if (path.includes('Android') || path.includes('android')) return 'android-sdk';
|
|
48
|
+
if (path.includes('homebrew') || path.includes('/opt/homebrew')) return 'brew';
|
|
49
|
+
if (path.includes('/usr/bin') || path.includes('System32')) return 'system';
|
|
50
|
+
if (path.includes('/usr/local')) return 'local';
|
|
51
|
+
return 'path';
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// ── platform-specific discovery ───────────────────────────────────────
|
|
55
|
+
|
|
56
|
+
function discoverWin(tool) {
|
|
57
|
+
// 1. PATH
|
|
58
|
+
let p = which(tool);
|
|
59
|
+
if (p) return { path: p, source: classify(p) };
|
|
60
|
+
|
|
61
|
+
// 2. Scoop shims
|
|
62
|
+
p = sh(`powershell -NoProfile -Command "Get-ChildItem -LiteralPath '${join(HOME, 'scoop', 'shims')}' -Filter '${tool}*' -ErrorAction SilentlyContinue | Select-Object -ExpandProperty FullName -First 1"`);
|
|
63
|
+
if (p) return { path: p, source: 'scoop' };
|
|
64
|
+
|
|
65
|
+
// 3. Scoop apps deep
|
|
66
|
+
p = sh(`powershell -NoProfile -Command "Get-ChildItem -LiteralPath '${join(HOME, 'scoop', 'apps')}' -Filter '${tool}.exe' -Recurse -Depth 3 -ErrorAction SilentlyContinue | Select-Object -ExpandProperty FullName -First 1"`);
|
|
67
|
+
if (p) return { path: p, source: 'scoop' };
|
|
68
|
+
|
|
69
|
+
// 4. Android SDK
|
|
70
|
+
for (const base of [join(HOME, 'Android', 'Sdk'), join(HOME, 'AppData', 'Local', 'Android', 'Sdk')]) {
|
|
71
|
+
p = sh(`powershell -NoProfile -Command "Get-ChildItem -LiteralPath '${base}' -Filter '${tool}.exe' -Recurse -Depth 4 -ErrorAction SilentlyContinue | Select-Object -ExpandProperty FullName -First 1"`);
|
|
72
|
+
if (p) return { path: p, source: 'android-sdk' };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function discoverUnix(tool) {
|
|
79
|
+
// 1. PATH
|
|
80
|
+
let p = which(tool);
|
|
81
|
+
if (p) return { path: p, source: classify(p) };
|
|
82
|
+
|
|
83
|
+
// 2. Brew (macOS)
|
|
84
|
+
if (PLATFORM === 'darwin') {
|
|
85
|
+
for (const prefix of ['/opt/homebrew/bin', '/usr/local/bin']) {
|
|
86
|
+
const candidate = join(prefix, tool);
|
|
87
|
+
if (existsSync(candidate)) return { path: candidate, source: 'brew' };
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// 3. Common unix paths
|
|
92
|
+
for (const prefix of ['/usr/bin', '/usr/local/bin', join(HOME, '.local', 'bin')]) {
|
|
93
|
+
const candidate = join(prefix, tool);
|
|
94
|
+
if (existsSync(candidate)) return { path: candidate, source: classify(candidate) };
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// 4. Android SDK (Linux/Mac)
|
|
98
|
+
for (const base of [join(HOME, 'Android', 'Sdk'), join(HOME, 'Library', 'Android', 'sdk')]) {
|
|
99
|
+
p = sh(`find "${base}" -name "${tool}" -type f 2>/dev/null | head -1`);
|
|
100
|
+
if (p) return { path: p, source: 'android-sdk' };
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function discover(tool) {
|
|
107
|
+
if (PLATFORM === 'win32') return discoverWin(tool);
|
|
108
|
+
return discoverUnix(tool);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// ── main ──────────────────────────────────────────────────────────────
|
|
112
|
+
console.log(`🔍 dev-runner-setup (${PLATFORM}) — discovering tools...\n`);
|
|
113
|
+
|
|
114
|
+
if (!existsSync(AGENTS_DIR)) mkdirSync(AGENTS_DIR, { recursive: true });
|
|
115
|
+
|
|
116
|
+
copyFileSync(TEMPLATE, join(AGENTS_DIR, 'dev-runner.md'));
|
|
117
|
+
console.log(' ✓ Agent installed');
|
|
118
|
+
|
|
119
|
+
const map = {};
|
|
120
|
+
let found = 0;
|
|
121
|
+
for (const tool of TOOLS) {
|
|
122
|
+
const r = discover(tool);
|
|
123
|
+
if (r && r.path) {
|
|
124
|
+
map[tool] = {
|
|
125
|
+
path: r.path.replace(/\\/g, '/'),
|
|
126
|
+
source: r.source,
|
|
127
|
+
category: CATEGORIES[tool] || 'other',
|
|
128
|
+
};
|
|
129
|
+
found++;
|
|
130
|
+
console.log(` ✓ ${tool}`);
|
|
131
|
+
} else {
|
|
132
|
+
console.log(` ✗ ${tool}`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
writeFileSync(MAP_FILE, JSON.stringify(map, null, 2));
|
|
137
|
+
console.log(`\n📦 ${found}/${TOOLS.length} tools found → ${MAP_FILE}`);
|
|
138
|
+
console.log(' Restart opencode to load the agent.\n');
|
package/package.json
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "opencode-dev-runner",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Auto-discovers dev tools on your machine and installs a dev-runner subagent for opencode",
|
|
5
|
+
"bin": {
|
|
6
|
+
"dev-runner-setup": "bin/setup.js"
|
|
7
|
+
},
|
|
8
|
+
"files": [
|
|
9
|
+
"bin/",
|
|
10
|
+
"templates/"
|
|
11
|
+
],
|
|
12
|
+
"keywords": [
|
|
13
|
+
"opencode",
|
|
14
|
+
"agent",
|
|
15
|
+
"dev-tools",
|
|
16
|
+
"flutter",
|
|
17
|
+
"adb",
|
|
18
|
+
"tool-discovery"
|
|
19
|
+
],
|
|
20
|
+
"license": "MIT"
|
|
21
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Knows how to find and run any dev tool. Learns new tools by searching the system and saving them to tool-map.json. Use when you need a tool path, or to run flutter/dart/adb/git/npm/node/python/docker commands. Use before guessing any path or command.
|
|
3
|
+
mode: subagent
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
You are the dev-runner agent. Your job: find and run any development tool on this machine. You maintain a tool registry in `tool-map.json` and learn new tools by searching the system.
|
|
7
|
+
|
|
8
|
+
## Architecture
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
.opencode/agents/
|
|
12
|
+
dev-runner.md ← you (this file)
|
|
13
|
+
tool-map.json ← { "toolname": { "path", "source", "category" } }
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
**Rule**: tool-map.json is the source of truth. Read it first. Never guess paths.
|
|
17
|
+
|
|
18
|
+
## How to resolve a tool
|
|
19
|
+
|
|
20
|
+
### 1. Check the map
|
|
21
|
+
|
|
22
|
+
Read `.opencode/agents/tool-map.json`. Return `path` if found.
|
|
23
|
+
|
|
24
|
+
### 2. Search the system
|
|
25
|
+
|
|
26
|
+
Stop on first hit. Platform-specific:
|
|
27
|
+
|
|
28
|
+
**Linux / macOS (bash/zsh):**
|
|
29
|
+
```bash
|
|
30
|
+
# PATH
|
|
31
|
+
which <tool> 2>/dev/null || command -v <tool>
|
|
32
|
+
|
|
33
|
+
# Brew (macOS)
|
|
34
|
+
ls /opt/homebrew/bin/<tool> /usr/local/bin/<tool> 2>/dev/null
|
|
35
|
+
|
|
36
|
+
# Common locations
|
|
37
|
+
ls /usr/bin/<tool> /usr/local/bin/<tool> ~/.local/bin/<tool> 2>/dev/null
|
|
38
|
+
|
|
39
|
+
# Android SDK
|
|
40
|
+
find ~/Android/Sdk -name "<tool>" -type f 2>/dev/null | head -1
|
|
41
|
+
find ~/Library/Android/sdk -name "<tool>" -type f 2>/dev/null | head -1
|
|
42
|
+
|
|
43
|
+
# Deep search (slow, last resort)
|
|
44
|
+
find /usr -name "<tool>" -type f 2>/dev/null | head -3
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**Windows (PowerShell):**
|
|
48
|
+
```powershell
|
|
49
|
+
# PATH
|
|
50
|
+
where.exe <tool> 2>$null | Select-Object -First 1
|
|
51
|
+
|
|
52
|
+
# Scoop shims
|
|
53
|
+
Get-ChildItem "$env:USERPROFILE\scoop\shims" -Filter "<tool>*" -ErrorAction SilentlyContinue | % FullName
|
|
54
|
+
|
|
55
|
+
# Scoop apps (deep)
|
|
56
|
+
Get-ChildItem "$env:USERPROFILE\scoop\apps" -Filter "<tool>.exe" -Recurse -Depth 3 -ErrorAction SilentlyContinue | % FullName
|
|
57
|
+
|
|
58
|
+
# Android SDK
|
|
59
|
+
Get-ChildItem "$env:LOCALAPPDATA\Android\Sdk" -Filter "<tool>.exe" -Recurse -Depth 4 -ErrorAction SilentlyContinue | % FullName
|
|
60
|
+
Get-ChildItem "$env:USERPROFILE\Android\Sdk" -Filter "<tool>.exe" -Recurse -Depth 4 -ErrorAction SilentlyContinue | % FullName
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### 3. Save learned tool
|
|
64
|
+
|
|
65
|
+
When discovered, add to `tool-map.json` using the Edit tool. Format:
|
|
66
|
+
|
|
67
|
+
```json
|
|
68
|
+
"toolname": {
|
|
69
|
+
"path": "/absolute/path/to/tool",
|
|
70
|
+
"source": "scoop|brew|android-sdk|system|path|discovered",
|
|
71
|
+
"category": "one-of-below"
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### 4. Report not found
|
|
76
|
+
|
|
77
|
+
"Tool `<tool>` not found. Searched: PATH, system bins, package manager dirs, Android SDK."
|
|
78
|
+
|
|
79
|
+
## Categories
|
|
80
|
+
|
|
81
|
+
| Category | Tools |
|
|
82
|
+
|----------|-------|
|
|
83
|
+
| `android` | adb, emulator, sdkmanager |
|
|
84
|
+
| `flutter` | flutter, dart |
|
|
85
|
+
| `vcs` | git, gh |
|
|
86
|
+
| `node` | node, npm, npx, yarn, pnpm |
|
|
87
|
+
| `python` | python, python3, pip, pip3 |
|
|
88
|
+
| `java` | java, javac, gradle, mvn |
|
|
89
|
+
| `database` | supabase, psql, sqlite3 |
|
|
90
|
+
| `container` | docker, podman |
|
|
91
|
+
| `editor` | code, nvim, vim |
|
|
92
|
+
| `package-manager` | scoop, choco, brew, apt, winget |
|
|
93
|
+
| `build` | make, cmake |
|
|
94
|
+
| `other` | anything else |
|
|
95
|
+
|
|
96
|
+
## Response format
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
tool: <name>
|
|
100
|
+
path: <resolved>
|
|
101
|
+
command: <exact command>
|
|
102
|
+
workdir: <dir or none>
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
If just learned: append "→ saved to tool-map.json".
|