nexus-dev-toolkit 3.1.1__tar.gz → 3.1.2__tar.gz
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.
- {nexus_dev_toolkit-3.1.1/nexus_dev_toolkit.egg-info → nexus_dev_toolkit-3.1.2}/PKG-INFO +30 -15
- {nexus_dev_toolkit-3.1.1 → nexus_dev_toolkit-3.1.2}/README.md +29 -14
- {nexus_dev_toolkit-3.1.1 → nexus_dev_toolkit-3.1.2}/nexus_cli.py +167 -15
- {nexus_dev_toolkit-3.1.1 → nexus_dev_toolkit-3.1.2/nexus_dev_toolkit.egg-info}/PKG-INFO +30 -15
- {nexus_dev_toolkit-3.1.1 → nexus_dev_toolkit-3.1.2}/pyproject.toml +1 -1
- {nexus_dev_toolkit-3.1.1 → nexus_dev_toolkit-3.1.2}/tests/test_cli.py +47 -0
- {nexus_dev_toolkit-3.1.1 → nexus_dev_toolkit-3.1.2}/LICENSE +0 -0
- {nexus_dev_toolkit-3.1.1 → nexus_dev_toolkit-3.1.2}/nexus_dev_toolkit.egg-info/SOURCES.txt +0 -0
- {nexus_dev_toolkit-3.1.1 → nexus_dev_toolkit-3.1.2}/nexus_dev_toolkit.egg-info/dependency_links.txt +0 -0
- {nexus_dev_toolkit-3.1.1 → nexus_dev_toolkit-3.1.2}/nexus_dev_toolkit.egg-info/entry_points.txt +0 -0
- {nexus_dev_toolkit-3.1.1 → nexus_dev_toolkit-3.1.2}/nexus_dev_toolkit.egg-info/requires.txt +0 -0
- {nexus_dev_toolkit-3.1.1 → nexus_dev_toolkit-3.1.2}/nexus_dev_toolkit.egg-info/top_level.txt +0 -0
- {nexus_dev_toolkit-3.1.1 → nexus_dev_toolkit-3.1.2}/nexus_server.py +0 -0
- {nexus_dev_toolkit-3.1.1 → nexus_dev_toolkit-3.1.2}/setup.cfg +0 -0
- {nexus_dev_toolkit-3.1.1 → nexus_dev_toolkit-3.1.2}/tests/test_server.py +0 -0
- {nexus_dev_toolkit-3.1.1 → nexus_dev_toolkit-3.1.2}/tools/__init__.py +0 -0
- {nexus_dev_toolkit-3.1.1 → nexus_dev_toolkit-3.1.2}/tools/agents/__init__.py +0 -0
- {nexus_dev_toolkit-3.1.1 → nexus_dev_toolkit-3.1.2}/tools/agents/code-reviewer.md +0 -0
- {nexus_dev_toolkit-3.1.1 → nexus_dev_toolkit-3.1.2}/tools/agents/database-reviewer.md +0 -0
- {nexus_dev_toolkit-3.1.1 → nexus_dev_toolkit-3.1.2}/tools/agents/deployment-reviewer.md +0 -0
- {nexus_dev_toolkit-3.1.1 → nexus_dev_toolkit-3.1.2}/tools/agents/monitoring-reviewer.md +0 -0
- {nexus_dev_toolkit-3.1.1 → nexus_dev_toolkit-3.1.2}/tools/agents/performance-reviewer.md +0 -0
- {nexus_dev_toolkit-3.1.1 → nexus_dev_toolkit-3.1.2}/tools/epav/__init__.py +0 -0
- {nexus_dev_toolkit-3.1.1 → nexus_dev_toolkit-3.1.2}/tools/epav/arch_ingest.py +0 -0
- {nexus_dev_toolkit-3.1.1 → nexus_dev_toolkit-3.1.2}/tools/epav/package_resolver.py +0 -0
- {nexus_dev_toolkit-3.1.1 → nexus_dev_toolkit-3.1.2}/tools/epav/project_rules.py +0 -0
- {nexus_dev_toolkit-3.1.1 → nexus_dev_toolkit-3.1.2}/tools/epav/skills/__init__.py +0 -0
- {nexus_dev_toolkit-3.1.1 → nexus_dev_toolkit-3.1.2}/tools/epav/skills/apply.md +0 -0
- {nexus_dev_toolkit-3.1.1 → nexus_dev_toolkit-3.1.2}/tools/epav/skills/code-review.md +0 -0
- {nexus_dev_toolkit-3.1.1 → nexus_dev_toolkit-3.1.2}/tools/epav/skills/database-review.md +0 -0
- {nexus_dev_toolkit-3.1.1 → nexus_dev_toolkit-3.1.2}/tools/epav/skills/deployment-review.md +0 -0
- {nexus_dev_toolkit-3.1.1 → nexus_dev_toolkit-3.1.2}/tools/epav/skills/epav.md +0 -0
- {nexus_dev_toolkit-3.1.1 → nexus_dev_toolkit-3.1.2}/tools/epav/skills/evaluate.md +0 -0
- {nexus_dev_toolkit-3.1.1 → nexus_dev_toolkit-3.1.2}/tools/epav/skills/monitoring-review.md +0 -0
- {nexus_dev_toolkit-3.1.1 → nexus_dev_toolkit-3.1.2}/tools/epav/skills/performance-review.md +0 -0
- {nexus_dev_toolkit-3.1.1 → nexus_dev_toolkit-3.1.2}/tools/epav/skills/plan.md +0 -0
- {nexus_dev_toolkit-3.1.1 → nexus_dev_toolkit-3.1.2}/tools/epav/skills/scaffold.md +0 -0
- {nexus_dev_toolkit-3.1.1 → nexus_dev_toolkit-3.1.2}/tools/epav/skills/validate.md +0 -0
- {nexus_dev_toolkit-3.1.1 → nexus_dev_toolkit-3.1.2}/tools/epav/task_loader.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nexus-dev-toolkit
|
|
3
|
-
Version: 3.1.
|
|
3
|
+
Version: 3.1.2
|
|
4
4
|
Summary: Developer workflow toolkit for Claude Code — Day 0 scaffold + Day 1 EPAV
|
|
5
5
|
Author-email: Ronald dela Cruz <rcdelacruz@users.noreply.github.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -80,7 +80,8 @@ uv tool install nexus-dev-toolkit
|
|
|
80
80
|
|
|
81
81
|
```bash
|
|
82
82
|
cd my-project
|
|
83
|
-
nexus init .
|
|
83
|
+
nexus init . # Claude Code (default)
|
|
84
|
+
nexus init . --tool opencode # OpenCode
|
|
84
85
|
```
|
|
85
86
|
|
|
86
87
|
### 4. Place your reference docs
|
|
@@ -137,15 +138,11 @@ Each step is a built-in skill in `.claude/commands/`. Every task starts from the
|
|
|
137
138
|
|
|
138
139
|
## What `nexus init` Creates
|
|
139
140
|
|
|
141
|
+
**Claude Code** (`nexus init .`):
|
|
140
142
|
```
|
|
141
143
|
.claude/
|
|
142
|
-
├── commands/
|
|
143
|
-
|
|
144
|
-
│ ├── evaluate.md ← /evaluate — orient on a task
|
|
145
|
-
│ ├── plan.md ← /plan — blueprint, no code
|
|
146
|
-
│ ├── apply.md ← /apply — implement the plan
|
|
147
|
-
│ ├── validate.md ← /validate — verify acceptance criteria
|
|
148
|
-
│ └── epav.md ← /epav — full cycle guide
|
|
144
|
+
├── commands/ ← EPAV skills + 5 reviewer skills (/code-review, etc.)
|
|
145
|
+
├── agents/ ← 5 reviewer subagents (code-reviewer, database-reviewer, etc.)
|
|
149
146
|
└── settings.json ← PostToolUse: graphify auto-updates after every file edit
|
|
150
147
|
knowledge/
|
|
151
148
|
├── rules/ ← coding standards, arch decisions
|
|
@@ -155,17 +152,35 @@ knowledge/
|
|
|
155
152
|
.mcp.json ← MCP server config
|
|
156
153
|
```
|
|
157
154
|
|
|
155
|
+
**OpenCode** (`nexus init . --tool opencode`):
|
|
156
|
+
```
|
|
157
|
+
.opencode/
|
|
158
|
+
├── commands/ ← same EPAV skills + reviewer skills
|
|
159
|
+
├── agents/ ← same reviewer subagents (adapted for OpenCode)
|
|
160
|
+
└── plugins/
|
|
161
|
+
└── graphify.js ← tool.execute.after: graphify auto-update
|
|
162
|
+
knowledge/ ← same structure
|
|
163
|
+
opencode.json ← MCP server config
|
|
164
|
+
```
|
|
165
|
+
|
|
158
166
|
---
|
|
159
167
|
|
|
160
168
|
## Commands
|
|
161
169
|
|
|
162
170
|
```bash
|
|
163
|
-
nexus init .
|
|
164
|
-
nexus
|
|
165
|
-
nexus
|
|
166
|
-
nexus
|
|
167
|
-
|
|
168
|
-
nexus
|
|
171
|
+
nexus init . # Claude Code — set up .claude/ + knowledge/ + .mcp.json
|
|
172
|
+
nexus init . --tool opencode # OpenCode — set up .opencode/ + knowledge/ + opencode.json
|
|
173
|
+
nexus --version # show installed version
|
|
174
|
+
nexus update # update to latest version
|
|
175
|
+
|
|
176
|
+
nexus skill list # list all skills in .claude/commands/
|
|
177
|
+
nexus skill add my-review # create a custom skill
|
|
178
|
+
|
|
179
|
+
nexus agent list # list all subagents in .claude/agents/
|
|
180
|
+
nexus agent add my-agent # create a custom subagent
|
|
181
|
+
|
|
182
|
+
nexus rule list # list all rules in knowledge/rules/
|
|
183
|
+
nexus rule add api-standards # create a project rule
|
|
169
184
|
```
|
|
170
185
|
|
|
171
186
|
---
|
|
@@ -59,7 +59,8 @@ uv tool install nexus-dev-toolkit
|
|
|
59
59
|
|
|
60
60
|
```bash
|
|
61
61
|
cd my-project
|
|
62
|
-
nexus init .
|
|
62
|
+
nexus init . # Claude Code (default)
|
|
63
|
+
nexus init . --tool opencode # OpenCode
|
|
63
64
|
```
|
|
64
65
|
|
|
65
66
|
### 4. Place your reference docs
|
|
@@ -116,15 +117,11 @@ Each step is a built-in skill in `.claude/commands/`. Every task starts from the
|
|
|
116
117
|
|
|
117
118
|
## What `nexus init` Creates
|
|
118
119
|
|
|
120
|
+
**Claude Code** (`nexus init .`):
|
|
119
121
|
```
|
|
120
122
|
.claude/
|
|
121
|
-
├── commands/
|
|
122
|
-
|
|
123
|
-
│ ├── evaluate.md ← /evaluate — orient on a task
|
|
124
|
-
│ ├── plan.md ← /plan — blueprint, no code
|
|
125
|
-
│ ├── apply.md ← /apply — implement the plan
|
|
126
|
-
│ ├── validate.md ← /validate — verify acceptance criteria
|
|
127
|
-
│ └── epav.md ← /epav — full cycle guide
|
|
123
|
+
├── commands/ ← EPAV skills + 5 reviewer skills (/code-review, etc.)
|
|
124
|
+
├── agents/ ← 5 reviewer subagents (code-reviewer, database-reviewer, etc.)
|
|
128
125
|
└── settings.json ← PostToolUse: graphify auto-updates after every file edit
|
|
129
126
|
knowledge/
|
|
130
127
|
├── rules/ ← coding standards, arch decisions
|
|
@@ -134,17 +131,35 @@ knowledge/
|
|
|
134
131
|
.mcp.json ← MCP server config
|
|
135
132
|
```
|
|
136
133
|
|
|
134
|
+
**OpenCode** (`nexus init . --tool opencode`):
|
|
135
|
+
```
|
|
136
|
+
.opencode/
|
|
137
|
+
├── commands/ ← same EPAV skills + reviewer skills
|
|
138
|
+
├── agents/ ← same reviewer subagents (adapted for OpenCode)
|
|
139
|
+
└── plugins/
|
|
140
|
+
└── graphify.js ← tool.execute.after: graphify auto-update
|
|
141
|
+
knowledge/ ← same structure
|
|
142
|
+
opencode.json ← MCP server config
|
|
143
|
+
```
|
|
144
|
+
|
|
137
145
|
---
|
|
138
146
|
|
|
139
147
|
## Commands
|
|
140
148
|
|
|
141
149
|
```bash
|
|
142
|
-
nexus init .
|
|
143
|
-
nexus
|
|
144
|
-
nexus
|
|
145
|
-
nexus
|
|
146
|
-
|
|
147
|
-
nexus
|
|
150
|
+
nexus init . # Claude Code — set up .claude/ + knowledge/ + .mcp.json
|
|
151
|
+
nexus init . --tool opencode # OpenCode — set up .opencode/ + knowledge/ + opencode.json
|
|
152
|
+
nexus --version # show installed version
|
|
153
|
+
nexus update # update to latest version
|
|
154
|
+
|
|
155
|
+
nexus skill list # list all skills in .claude/commands/
|
|
156
|
+
nexus skill add my-review # create a custom skill
|
|
157
|
+
|
|
158
|
+
nexus agent list # list all subagents in .claude/agents/
|
|
159
|
+
nexus agent add my-agent # create a custom subagent
|
|
160
|
+
|
|
161
|
+
nexus rule list # list all rules in knowledge/rules/
|
|
162
|
+
nexus rule add api-standards # create a project rule
|
|
148
163
|
```
|
|
149
164
|
|
|
150
165
|
---
|
|
@@ -18,7 +18,7 @@ app.add_typer(agent_app, name="agent")
|
|
|
18
18
|
|
|
19
19
|
console = Console()
|
|
20
20
|
|
|
21
|
-
_VERSION = "3.1.
|
|
21
|
+
_VERSION = "3.1.2"
|
|
22
22
|
|
|
23
23
|
_LOGO = """\
|
|
24
24
|
[cyan]███╗ ██╗███████╗██╗ ██╗██╗ ██╗███████╗[/cyan]
|
|
@@ -117,6 +117,29 @@ _MCP_BLOCK = {
|
|
|
117
117
|
}
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
+
_OPENCODE_MCP_BLOCK = {
|
|
121
|
+
"nexus-mcp": {
|
|
122
|
+
"type": "local",
|
|
123
|
+
"command": ["uvx", "--refresh", "--from", "nexus-dev-toolkit", "nexus-mcp"],
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
_OPENCODE_GRAPHIFY_PLUGIN = """\
|
|
128
|
+
// .opencode/plugins/graphify.js
|
|
129
|
+
// Auto-updates the graphify knowledge graph after every tool execution.
|
|
130
|
+
import { execSync } from "node:child_process"
|
|
131
|
+
|
|
132
|
+
export const GraphifyPlugin = async ({ directory }) => {
|
|
133
|
+
return {
|
|
134
|
+
"tool.execute.after": async () => {
|
|
135
|
+
try {
|
|
136
|
+
execSync("graphify update . --force", { cwd: directory, stdio: "ignore" })
|
|
137
|
+
} catch (_) {}
|
|
138
|
+
},
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
"""
|
|
142
|
+
|
|
120
143
|
|
|
121
144
|
def _init_project(project_dir: Path) -> list[str]:
|
|
122
145
|
"""
|
|
@@ -164,6 +187,81 @@ def _init_project(project_dir: Path) -> list[str]:
|
|
|
164
187
|
return created
|
|
165
188
|
|
|
166
189
|
|
|
190
|
+
def _strip_claude_frontmatter(content: str) -> str:
|
|
191
|
+
"""Remove Claude Code-only frontmatter fields (tools, model) for OpenCode compatibility."""
|
|
192
|
+
if not content.startswith("---"):
|
|
193
|
+
return content
|
|
194
|
+
parts = content.split("---", 2)
|
|
195
|
+
if len(parts) < 3:
|
|
196
|
+
return content
|
|
197
|
+
lines = [
|
|
198
|
+
line for line in parts[1].splitlines()
|
|
199
|
+
if not line.startswith("tools:") and not line.startswith("model:")
|
|
200
|
+
]
|
|
201
|
+
return "---" + "\n".join(lines) + "---" + parts[2]
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def _init_opencode(project_dir: Path) -> list[str]:
|
|
205
|
+
"""
|
|
206
|
+
nexus init --tool opencode — sets up:
|
|
207
|
+
.opencode/commands/ ← built-in skills
|
|
208
|
+
.opencode/agents/ ← built-in subagents
|
|
209
|
+
.opencode/plugins/ ← graphify PostToolUse hook
|
|
210
|
+
opencode.json ← MCP server config
|
|
211
|
+
knowledge/ ← empty scaffold
|
|
212
|
+
"""
|
|
213
|
+
created = []
|
|
214
|
+
|
|
215
|
+
# .opencode/commands/ — copy built-in skills
|
|
216
|
+
commands_dir = project_dir / ".opencode" / "commands"
|
|
217
|
+
commands_dir.mkdir(parents=True, exist_ok=True)
|
|
218
|
+
for skill_name in _BUILTIN_SKILLS:
|
|
219
|
+
src = _SKILLS_SRC / skill_name
|
|
220
|
+
dest = commands_dir / skill_name
|
|
221
|
+
if src.exists() and not dest.exists():
|
|
222
|
+
shutil.copy2(src, dest)
|
|
223
|
+
created.append(f".opencode/commands/{skill_name}")
|
|
224
|
+
|
|
225
|
+
# .opencode/agents/ — copy built-in subagents, stripping Claude Code-only frontmatter
|
|
226
|
+
agents_dir = project_dir / ".opencode" / "agents"
|
|
227
|
+
agents_dir.mkdir(parents=True, exist_ok=True)
|
|
228
|
+
for agent_name in _BUILTIN_AGENTS:
|
|
229
|
+
src = _AGENTS_SRC / agent_name
|
|
230
|
+
dest = agents_dir / agent_name
|
|
231
|
+
if src.exists() and not dest.exists():
|
|
232
|
+
dest.write_text(_strip_claude_frontmatter(src.read_text()), encoding="utf-8")
|
|
233
|
+
created.append(f".opencode/agents/{agent_name}")
|
|
234
|
+
|
|
235
|
+
# .opencode/plugins/graphify.js — PostToolUse hook
|
|
236
|
+
plugins_dir = project_dir / ".opencode" / "plugins"
|
|
237
|
+
plugins_dir.mkdir(parents=True, exist_ok=True)
|
|
238
|
+
plugin_path = plugins_dir / "graphify.js"
|
|
239
|
+
if not plugin_path.exists():
|
|
240
|
+
plugin_path.write_text(_OPENCODE_GRAPHIFY_PLUGIN, encoding="utf-8")
|
|
241
|
+
created.append(".opencode/plugins/graphify.js")
|
|
242
|
+
|
|
243
|
+
# opencode.json — MCP server config
|
|
244
|
+
opencode_json = project_dir / "opencode.json"
|
|
245
|
+
existing: dict = {}
|
|
246
|
+
if opencode_json.exists():
|
|
247
|
+
try:
|
|
248
|
+
existing = json.loads(opencode_json.read_text())
|
|
249
|
+
except Exception:
|
|
250
|
+
pass
|
|
251
|
+
already_has_mcp = "nexus-mcp" in existing.get("mcp", {})
|
|
252
|
+
existing.setdefault("$schema", "https://opencode.ai/config.json")
|
|
253
|
+
existing.setdefault("mcp", {}).update(_OPENCODE_MCP_BLOCK)
|
|
254
|
+
opencode_json.write_text(json.dumps(existing, indent=2))
|
|
255
|
+
if not already_has_mcp:
|
|
256
|
+
created.append("opencode.json")
|
|
257
|
+
|
|
258
|
+
# knowledge/ scaffold
|
|
259
|
+
for d in _KNOWLEDGE_DIRS:
|
|
260
|
+
(project_dir / d).mkdir(parents=True, exist_ok=True)
|
|
261
|
+
|
|
262
|
+
return created
|
|
263
|
+
|
|
264
|
+
|
|
167
265
|
def _write_mcp_config(project_dir: Path) -> str:
|
|
168
266
|
mcp_path = project_dir / ".mcp.json"
|
|
169
267
|
existing: dict = {}
|
|
@@ -179,26 +277,80 @@ def _write_mcp_config(project_dir: Path) -> str:
|
|
|
179
277
|
|
|
180
278
|
# ── Commands ──────────────────────────────────────────────────────────────────
|
|
181
279
|
|
|
280
|
+
_SUPPORTED_TOOLS = ["claude", "opencode"]
|
|
281
|
+
|
|
282
|
+
_TOOL_CHECK = {
|
|
283
|
+
"claude": {
|
|
284
|
+
"bin": "claude",
|
|
285
|
+
"name": "Claude Code",
|
|
286
|
+
"install": "npm install -g @anthropic-ai/claude-code && claude login",
|
|
287
|
+
"install_cmd": ["npm", "install", "-g", "@anthropic-ai/claude-code"],
|
|
288
|
+
},
|
|
289
|
+
"opencode": {
|
|
290
|
+
"bin": "opencode",
|
|
291
|
+
"name": "OpenCode",
|
|
292
|
+
"install": "curl -fsSL https://opencode.ai/install | bash",
|
|
293
|
+
"install_cmd": None, # pipe install — run via shell
|
|
294
|
+
},
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
def _check_and_offer_install(tool: str) -> None:
|
|
299
|
+
info = _TOOL_CHECK[tool]
|
|
300
|
+
if shutil.which(info["bin"]):
|
|
301
|
+
return
|
|
302
|
+
|
|
303
|
+
console.print(f" [yellow]⚠[/yellow] {info['name']} not found — you need it to use nexus.\n")
|
|
304
|
+
answer = console.input(f" Install {info['name']} now? [y/N] ").strip().lower()
|
|
305
|
+
if answer != "y":
|
|
306
|
+
console.print(f" [dim]Skipping. Install manually: {info['install']}[/dim]\n")
|
|
307
|
+
return
|
|
308
|
+
|
|
309
|
+
console.print(f" [cyan]▶[/cyan] Installing {info['name']}…\n")
|
|
310
|
+
if info["install_cmd"]:
|
|
311
|
+
result = subprocess.run(info["install_cmd"])
|
|
312
|
+
else:
|
|
313
|
+
result = subprocess.run(info["install"], shell=True)
|
|
314
|
+
|
|
315
|
+
if result.returncode == 0:
|
|
316
|
+
console.print(f" [green]✓[/green] {info['name']} installed.\n")
|
|
317
|
+
else:
|
|
318
|
+
console.print(f" [red]✗[/red] Install failed. Run manually: {info['install']}\n")
|
|
319
|
+
|
|
320
|
+
|
|
182
321
|
@app.command()
|
|
183
322
|
def init(
|
|
184
323
|
project_dir: str = typer.Argument(".", help="Project directory to initialize"),
|
|
324
|
+
tool: str = typer.Option("claude", "--tool", "-t", help=f"AI coding tool to set up for ({', '.join(_SUPPORTED_TOOLS)})"),
|
|
185
325
|
) -> None:
|
|
186
|
-
"""Initialize
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
created = _init_project(root)
|
|
191
|
-
for f in created:
|
|
192
|
-
console.print(f" [green]✓[/green] {f}")
|
|
193
|
-
|
|
194
|
-
if not created:
|
|
195
|
-
console.print(" [yellow]·[/yellow] Already initialized — nothing to do")
|
|
196
|
-
return
|
|
326
|
+
"""Initialize nexus in a project directory. Defaults to Claude Code."""
|
|
327
|
+
if tool not in _SUPPORTED_TOOLS:
|
|
328
|
+
console.print(f" [red]✗[/red] Unknown tool '{tool}'. Supported: {', '.join(_SUPPORTED_TOOLS)}")
|
|
329
|
+
raise typer.Exit(1)
|
|
197
330
|
|
|
198
|
-
|
|
199
|
-
console.print(f" [green]✓[/green] {mcp}")
|
|
331
|
+
_check_and_offer_install(tool)
|
|
200
332
|
|
|
201
|
-
|
|
333
|
+
root = Path(project_dir).resolve()
|
|
334
|
+
console.print(f" [cyan]▶[/cyan] Initializing nexus for [bold]{tool}[/bold] in [bold]{root}[/bold]\n")
|
|
335
|
+
|
|
336
|
+
if tool == "opencode":
|
|
337
|
+
created = _init_opencode(root)
|
|
338
|
+
for f in created:
|
|
339
|
+
console.print(f" [green]✓[/green] {f}")
|
|
340
|
+
if not created:
|
|
341
|
+
console.print(" [yellow]·[/yellow] Already initialized — nothing to do")
|
|
342
|
+
return
|
|
343
|
+
console.print(f"\n [bold green]Done.[/bold green] Open [bold]{root}[/bold] in OpenCode and type [cyan]/scaffold[/cyan]\n")
|
|
344
|
+
else:
|
|
345
|
+
created = _init_project(root)
|
|
346
|
+
for f in created:
|
|
347
|
+
console.print(f" [green]✓[/green] {f}")
|
|
348
|
+
if not created:
|
|
349
|
+
console.print(" [yellow]·[/yellow] Already initialized — nothing to do")
|
|
350
|
+
return
|
|
351
|
+
mcp = _write_mcp_config(root)
|
|
352
|
+
console.print(f" [green]✓[/green] {mcp}")
|
|
353
|
+
console.print(f"\n [bold green]Done.[/bold green] Open [bold]{root}[/bold] in Claude Code and type [cyan]/scaffold[/cyan]\n")
|
|
202
354
|
|
|
203
355
|
|
|
204
356
|
@app.command()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nexus-dev-toolkit
|
|
3
|
-
Version: 3.1.
|
|
3
|
+
Version: 3.1.2
|
|
4
4
|
Summary: Developer workflow toolkit for Claude Code — Day 0 scaffold + Day 1 EPAV
|
|
5
5
|
Author-email: Ronald dela Cruz <rcdelacruz@users.noreply.github.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -80,7 +80,8 @@ uv tool install nexus-dev-toolkit
|
|
|
80
80
|
|
|
81
81
|
```bash
|
|
82
82
|
cd my-project
|
|
83
|
-
nexus init .
|
|
83
|
+
nexus init . # Claude Code (default)
|
|
84
|
+
nexus init . --tool opencode # OpenCode
|
|
84
85
|
```
|
|
85
86
|
|
|
86
87
|
### 4. Place your reference docs
|
|
@@ -137,15 +138,11 @@ Each step is a built-in skill in `.claude/commands/`. Every task starts from the
|
|
|
137
138
|
|
|
138
139
|
## What `nexus init` Creates
|
|
139
140
|
|
|
141
|
+
**Claude Code** (`nexus init .`):
|
|
140
142
|
```
|
|
141
143
|
.claude/
|
|
142
|
-
├── commands/
|
|
143
|
-
|
|
144
|
-
│ ├── evaluate.md ← /evaluate — orient on a task
|
|
145
|
-
│ ├── plan.md ← /plan — blueprint, no code
|
|
146
|
-
│ ├── apply.md ← /apply — implement the plan
|
|
147
|
-
│ ├── validate.md ← /validate — verify acceptance criteria
|
|
148
|
-
│ └── epav.md ← /epav — full cycle guide
|
|
144
|
+
├── commands/ ← EPAV skills + 5 reviewer skills (/code-review, etc.)
|
|
145
|
+
├── agents/ ← 5 reviewer subagents (code-reviewer, database-reviewer, etc.)
|
|
149
146
|
└── settings.json ← PostToolUse: graphify auto-updates after every file edit
|
|
150
147
|
knowledge/
|
|
151
148
|
├── rules/ ← coding standards, arch decisions
|
|
@@ -155,17 +152,35 @@ knowledge/
|
|
|
155
152
|
.mcp.json ← MCP server config
|
|
156
153
|
```
|
|
157
154
|
|
|
155
|
+
**OpenCode** (`nexus init . --tool opencode`):
|
|
156
|
+
```
|
|
157
|
+
.opencode/
|
|
158
|
+
├── commands/ ← same EPAV skills + reviewer skills
|
|
159
|
+
├── agents/ ← same reviewer subagents (adapted for OpenCode)
|
|
160
|
+
└── plugins/
|
|
161
|
+
└── graphify.js ← tool.execute.after: graphify auto-update
|
|
162
|
+
knowledge/ ← same structure
|
|
163
|
+
opencode.json ← MCP server config
|
|
164
|
+
```
|
|
165
|
+
|
|
158
166
|
---
|
|
159
167
|
|
|
160
168
|
## Commands
|
|
161
169
|
|
|
162
170
|
```bash
|
|
163
|
-
nexus init .
|
|
164
|
-
nexus
|
|
165
|
-
nexus
|
|
166
|
-
nexus
|
|
167
|
-
|
|
168
|
-
nexus
|
|
171
|
+
nexus init . # Claude Code — set up .claude/ + knowledge/ + .mcp.json
|
|
172
|
+
nexus init . --tool opencode # OpenCode — set up .opencode/ + knowledge/ + opencode.json
|
|
173
|
+
nexus --version # show installed version
|
|
174
|
+
nexus update # update to latest version
|
|
175
|
+
|
|
176
|
+
nexus skill list # list all skills in .claude/commands/
|
|
177
|
+
nexus skill add my-review # create a custom skill
|
|
178
|
+
|
|
179
|
+
nexus agent list # list all subagents in .claude/agents/
|
|
180
|
+
nexus agent add my-agent # create a custom subagent
|
|
181
|
+
|
|
182
|
+
nexus rule list # list all rules in knowledge/rules/
|
|
183
|
+
nexus rule add api-standards # create a project rule
|
|
169
184
|
```
|
|
170
185
|
|
|
171
186
|
---
|
|
@@ -103,3 +103,50 @@ def test_rule_list(tmp_project):
|
|
|
103
103
|
result = runner.invoke(app, ["rule", "list", "--dir", str(tmp_project)])
|
|
104
104
|
assert result.exit_code == 0
|
|
105
105
|
assert "api-standards" in result.output
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def test_init_opencode_creates_commands(tmp_project):
|
|
109
|
+
result = runner.invoke(app, ["init", str(tmp_project), "--tool", "opencode"])
|
|
110
|
+
assert result.exit_code == 0
|
|
111
|
+
commands_dir = tmp_project / ".opencode" / "commands"
|
|
112
|
+
assert commands_dir.exists()
|
|
113
|
+
for skill in _BUILTIN_SKILLS:
|
|
114
|
+
assert (commands_dir / skill).exists(), f"Missing skill: {skill}"
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def test_init_opencode_creates_agents(tmp_project):
|
|
118
|
+
result = runner.invoke(app, ["init", str(tmp_project), "--tool", "opencode"])
|
|
119
|
+
assert result.exit_code == 0
|
|
120
|
+
agents_dir = tmp_project / ".opencode" / "agents"
|
|
121
|
+
assert agents_dir.exists()
|
|
122
|
+
for agent in _BUILTIN_AGENTS:
|
|
123
|
+
assert (agents_dir / agent).exists(), f"Missing agent: {agent}"
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def test_init_opencode_creates_plugin(tmp_project):
|
|
127
|
+
runner.invoke(app, ["init", str(tmp_project), "--tool", "opencode"])
|
|
128
|
+
plugin = tmp_project / ".opencode" / "plugins" / "graphify.js"
|
|
129
|
+
assert plugin.exists()
|
|
130
|
+
assert "tool.execute.after" in plugin.read_text()
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def test_init_opencode_creates_opencode_json(tmp_project):
|
|
134
|
+
runner.invoke(app, ["init", str(tmp_project), "--tool", "opencode"])
|
|
135
|
+
config = tmp_project / "opencode.json"
|
|
136
|
+
assert config.exists()
|
|
137
|
+
data = json.loads(config.read_text())
|
|
138
|
+
assert "nexus-mcp" in data["mcp"]
|
|
139
|
+
assert data["mcp"]["nexus-mcp"]["type"] == "local"
|
|
140
|
+
assert data["mcp"]["nexus-mcp"]["command"][0] == "uvx"
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def test_init_opencode_idempotent(tmp_project):
|
|
144
|
+
runner.invoke(app, ["init", str(tmp_project), "--tool", "opencode"])
|
|
145
|
+
result = runner.invoke(app, ["init", str(tmp_project), "--tool", "opencode"])
|
|
146
|
+
assert result.exit_code == 0
|
|
147
|
+
assert "Already initialized" in result.output
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def test_init_unknown_tool(tmp_project):
|
|
151
|
+
result = runner.invoke(app, ["init", str(tmp_project), "--tool", "cursor"])
|
|
152
|
+
assert result.exit_code == 1
|
|
File without changes
|
|
File without changes
|
{nexus_dev_toolkit-3.1.1 → nexus_dev_toolkit-3.1.2}/nexus_dev_toolkit.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{nexus_dev_toolkit-3.1.1 → nexus_dev_toolkit-3.1.2}/nexus_dev_toolkit.egg-info/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|
{nexus_dev_toolkit-3.1.1 → nexus_dev_toolkit-3.1.2}/nexus_dev_toolkit.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|