tachibot-mcp 2.24.0 → 2.26.1

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.
Files changed (44) hide show
  1. package/README.md +55 -48
  2. package/dist/src/cli/init.js +218 -0
  3. package/dist/src/orchestrators/collaborative/services/visualization/VisualizationService.js +32 -59
  4. package/dist/src/profiles/balanced.js +4 -1
  5. package/dist/src/profiles/code_focus.js +4 -1
  6. package/dist/src/profiles/full.js +4 -1
  7. package/dist/src/profiles/heavy_coding.js +4 -1
  8. package/dist/src/profiles/minimal.js +3 -0
  9. package/dist/src/profiles/research_power.js +3 -0
  10. package/dist/src/server-main.js +760 -0
  11. package/dist/src/server.js +11 -758
  12. package/dist/src/tools/debug-triage-tool.js +59 -0
  13. package/dist/src/tools/prompt-technique-tools.js +128 -33
  14. package/dist/src/tools/provider-catalog.js +10 -0
  15. package/dist/src/tools/refine-prompt-tool.js +57 -0
  16. package/dist/src/tools/registry.js +9 -0
  17. package/dist/src/tools/spec-writer-tool.js +64 -0
  18. package/dist/src/tools/tachi-tool.js +22 -0
  19. package/docs/TOOLS_REFERENCE.md +1183 -1068
  20. package/docs/TOOL_PARAMETERS.md +95 -424
  21. package/docs/TOOL_PROFILES.md +139 -140
  22. package/docs/plans/infra-plan-2026-07-research.json +194 -0
  23. package/docs/plans/infra-plan-2026-07.html +292 -0
  24. package/docs/superpowers/plans/2026-07-02-debug-triage-spec-writer.md +417 -0
  25. package/docs/superpowers/plans/2026-07-02-install-wave.md +412 -0
  26. package/docs/superpowers/plans/2026-07-03-refine-prompt.md +197 -0
  27. package/package.json +3 -2
  28. package/profiles/balanced.json +4 -1
  29. package/profiles/code_focus.json +4 -1
  30. package/profiles/full.json +4 -1
  31. package/profiles/heavy_coding.json +4 -1
  32. package/profiles/minimal.json +3 -0
  33. package/profiles/research_power.json +3 -0
  34. package/skills/audit/SKILL.md +19 -0
  35. package/skills/judge/SKILL.md +1 -1
  36. package/skills/prompt/SKILL.md +40 -124
  37. package/skills/redteam/SKILL.md +1 -1
  38. package/skills/review/SKILL.md +1 -1
  39. package/skills/setup/SKILL.md +13 -0
  40. package/skills/spec/SKILL.md +15 -0
  41. package/skills/tachi/SKILL.md +1 -1
  42. package/skills/test/SKILL.md +19 -0
  43. package/skills/triage/SKILL.md +15 -0
  44. package/tools.config.json +2 -1
package/README.md CHANGED
@@ -4,18 +4,18 @@
4
4
 
5
5
  ### Multi-Model AI Orchestration Platform
6
6
 
7
- [![Version](https://img.shields.io/badge/version-2.24.0-blue.svg)](https://www.npmjs.com/package/tachibot-mcp)
8
- [![Tools](https://img.shields.io/badge/tools-61_active-brightgreen.svg)](#-tool-ecosystem-61-tools)
7
+ [![Version](https://img.shields.io/badge/version-2.26.1-blue.svg)](https://www.npmjs.com/package/tachibot-mcp)
8
+ [![Tools](https://img.shields.io/badge/tools-64_active-brightgreen.svg)](#-tool-ecosystem-64-tools)
9
9
  [![License](https://img.shields.io/badge/license-AGPL--3.0-green.svg)](LICENSE)
10
10
  [![Node](https://img.shields.io/badge/node-%3E%3D22.0.0-brightgreen.svg)](https://nodejs.org)
11
11
  [![MCP](https://img.shields.io/badge/MCP-Compatible-purple.svg)](https://modelcontextprotocol.io)
12
12
 
13
- **61 AI tools. 12 providers. One protocol.**
13
+ **64 AI tools. 12 providers. One protocol.**
14
14
 
15
15
  Orchestrate Perplexity, Grok, GPT-5.5, Gemini, Qwen, Kimi K2.7-Code, and MiniMax M3
16
16
  from Claude Code, Claude Desktop, Cursor, or any MCP client.
17
17
 
18
- [Get Started](#-quick-start) · [View Tools](#-tool-ecosystem-61-tools) · [Documentation](https://tachibot.com/docs)
18
+ [Get Started](#-quick-start) · [View Tools](#-tool-ecosystem-64-tools) · [Documentation](https://tachibot.com/docs)
19
19
 
20
20
  <br>
21
21
 
@@ -28,52 +28,46 @@ from Claude Code, Claude Desktop, Cursor, or any MCP client.
28
28
 
29
29
  ---
30
30
 
31
- ## What's New in v2.15.0
31
+ ## What's New
32
32
 
33
- ### `/blueprint` Skill &mdash; Multi-Model Implementation Planning
34
- New skill that creates bite-sized TDD implementation plans using a 7-step multi-model council:
35
- ```
36
- /blueprint add OAuth with refresh tokens
37
- ```
38
- Pipeline: Grok search → Qwen+Kimi analysis → Kimi decompose → GPT pre-mortem critique → Gemini final judgment → **bite-sized TDD output** (exact files, test-first steps, commit points).
39
-
40
- Bridges `planner_maker`'s multi-model intelligence with the `writing-plans` execution format.
33
+ ### v2.26.1
34
+ - **`/test` and `/audit` skills** (19 skills total) `/test` generates runnable tests via `testgen`; `/audit` runs an OWASP/CWE security review via `security_review`.
35
+ - **Skill install in the wizard** — `tachibot init` now offers to install Claude Code skills with a per-skill skip choice (`[Enter]`=all · `[s]`=choose which to skip · `[n]`=none). Skills are opt-in — `postinstall` no longer writes to `~/.claude` silently (`npm run install-skills` still installs all non-interactively).
36
+ - **Fixes** — the one-click `.mcpb` extension now points at a valid entry point (was broken) and tracks the package version; `tachibot init` exits cleanly on non-interactive/CI stdin instead of hanging.
41
37
 
42
- ### 31 Prompt Engineering Techniques (was 22)
43
- Added 9 research-backed techniques for coding and decision-making:
38
+ ### v2.26.0
44
39
 
45
- | Technique | Source | Category |
46
- |-----------|--------|----------|
47
- | `reflexion` | Shinn et al. 2023 | Engineering |
48
- | `react` (ReAct) | Yao et al. 2022 | Engineering |
49
- | `rubber_duck` | Hunt & Thomas 2008 | Engineering |
50
- | `test_driven` | Beck 2003 | Engineering |
51
- | `scot` (Structured CoT) | Li et al. 2025 (+13.79% HumanEval) | Structured Coding |
52
- | `pre_post` (Contracts) | Empirical SE 2025 | Structured Coding |
53
- | `bdd_spec` (Given/When/Then) | BDD 2025 | Structured Coding |
54
- | `least_to_most` | Zhou et al. 2022 | Research |
55
- | `pre_mortem` | Klein 2007 | Decision |
40
+ #### Prompt stack, modernized
41
+ - **`refine_prompt`** (new tool) &mdash; opt-in prompt improver on a cheap/fast model: raw query → goal-first brief + **what changed** + **open questions**. Never auto-fires, never executes anything — you review, then use the brief. In Claude Code, `/prompt refine` presents the open questions as clickable choices and merges your answers into a final brief.
42
+ - **Curated technique list** &mdash; `list_prompt_techniques` now defaults to the ~9 core techniques that still help 2026 reasoning models (output contracts like `scot`, `pre_mortem`, `bdd_spec`); `all=true` for the full 31.
43
+ - **`technique="auto"`** &mdash; `preview_prompt_technique` recommends the right technique for your task, with reasons. Ask `tachi` "improve my prompt" for the symptom-based menu.
56
44
 
57
- Techniques are embedded directly in tool system prompts for automatic application.
45
+ #### Setup, de-mystified
46
+ - **`tachibot init`** (new CLI wizard) &mdash; detects your API keys and clients, prints the exact config for Claude Code and Claude Desktop. Never writes or echoes keys.
47
+ - **One-click Claude Desktop install** &mdash; download the `.mcpb` from the latest release and double-click. No JSON editing.
48
+ - **`doctor`** &mdash; shows which keys are set, which tools are visible vs hidden and why, and what to try first.
58
49
 
59
- ### MiniMax M2.5 Upgrade
60
- - `minimax_code` &mdash; SWE-Bench **80.2%**, per-task TECHNIQUE tags (SCoT, reflexion, rubber_duck), per-task temperatures
61
- - `minimax_agent` &mdash; ReAct + least-to-most decomposition protocol, HALT criteria
50
+ #### New tools & skills (64 tools · 19 skills)
51
+ - `debug_triage` &mdash; ranked root-cause hypotheses with the cheapest discriminating check for each (Grok 4.3)
52
+ - `spec_writer` &mdash; loose request → reviewable spec: user stories, Given/When/Then, out-of-scope, open questions (GPT-5.5)
53
+ - `diff_review` / `plan_critique` / `testgen` / `security_review` &mdash; multi-model diff review, adversarial plan red-team, test generation, OWASP/CWE audit
54
+ - Skills: `/review`, `/redteam`, `/spec`, `/triage`, `/setup`
62
55
 
63
- ### Enhanced Skills
64
- - `/breakdown` &mdash; now uses `least_to_most` ordering + `pre_mortem` failure analysis
65
- - `/judge` &mdash; first judge now runs pre-mortem ("assume this FAILED")
66
- - `/decompose` &mdash; deep-dives include pre/post contracts per sub-problem
67
- - `/prompt` &mdash; auto-recommend flow with 30-intent matching guide, 13 categories
56
+ #### Fixes
57
+ - `focus` orchestration screen: 37 lines of repeated scaffolding 10 focused lines
58
+ - `npm test` exits 0 again (uncancelled race timers leaked past Jest teardown)
59
+ - GPT-5.5 high-effort reasoning no longer cut off at 3 minutes (timeout 180s → 600s)
68
60
 
69
61
  ---
70
62
 
71
63
  ## Skills (Claude Code)
72
64
 
73
- TachiBot ships with 14 slash commands for Claude Code. These orchestrate the tools into powerful workflows:
65
+ TachiBot ships with 19 slash commands for Claude Code. These orchestrate the tools into powerful workflows:
74
66
 
75
67
  | Skill | What it does | Example |
76
68
  |-------|-------------|---------|
69
+ | `/setup` | Guided configuration — runs doctor, walks through keys/profiles | `/setup` |
70
+ | `/spec` | Request → reviewable spec before planning | `/spec add OAuth somehow` |
77
71
  | `/blueprint` | Multi-model planning → bite-sized TDD steps | `/blueprint add OAuth with refresh tokens` |
78
72
  | `/judge` | Multi-model council - parallel analysis with synthesis | `/judge how to implement rate limiting` |
79
73
  | `/think` | Sequential reasoning chain with any model | `/think grok,gemini design a cache layer` |
@@ -87,6 +81,9 @@ TachiBot ships with 14 slash commands for Claude Code. These orchestrate the too
87
81
  | `/tot` | Tree-of-Thought: branch → jury-prune → synthesize | `/tot design a rate limiter` |
88
82
  | `/review` | Multi-model diff review — panel + Gemini judge verdict | `/review` (or paste a diff) |
89
83
  | `/redteam` | Adversarial plan red-team — pre-mortem, risks, plan edits | `/redteam <paste plan>` |
84
+ | `/triage` | Ranked root-cause bug triage | `/triage <paste stack trace>` |
85
+ | `/test` | Generate runnable tests (edge cases first) | `/test src/auth.ts` |
86
+ | `/audit` | Security review — OWASP/CWE findings + fixes | `/audit the login handler` |
90
87
  | `/tachi` | Help - see available skills, tools, key status | `/tachi` |
91
88
 
92
89
  Skills automatically adapt to your configured API keys. Even with just 1-2 providers, all skills work.
@@ -98,7 +95,7 @@ Skills automatically adapt to your configured API keys. Even with just 1-2 provi
98
95
  ## Key Features
99
96
 
100
97
  ### Multi-Model Intelligence
101
- - **61 AI Tools** across 12 providers &mdash; Perplexity, Grok, GPT-5, Gemini, Qwen, Kimi, MiniMax, DeepSeek, GLM (Zhipu), StepFun, ERNIE (Baidu), plus free local models (Ollama / LM Studio / llama.cpp / vLLM)
98
+ - **64 AI Tools** across 12 providers &mdash; Perplexity, Grok, GPT-5, Gemini, Qwen, Kimi, MiniMax, DeepSeek, GLM (Zhipu), StepFun, ERNIE (Baidu), plus free local models (Ollama / LM Studio / llama.cpp / vLLM)
102
99
  - **Gemini 3.5 Flash** (`gemini-3.5-flash`, GA May 19 2026) &mdash; Flash/search tier; reasoning default stays `gemini-3.1-pro-preview`
103
100
  - **Multi-Model Council** &mdash; planner_maker synthesizes plans from 5+ models into bite-sized TDD steps
104
101
  - **Smart Routing** &mdash; Automatic model selection for optimal results
@@ -115,10 +112,10 @@ Skills automatically adapt to your configured API keys. Even with just 1-2 provi
115
112
  |---------|-------|----------|
116
113
  | **Minimal** | 13 | Quick tasks, low token budget |
117
114
  | **Research Power** | 35 | Deep investigation, multi-source |
118
- | **Code Focus** | 39 | Software development, SWE tasks |
119
- | **Balanced** | 50 | General-purpose, mixed workflows |
120
- | **Heavy Coding** | 54 | Max code tools + agentic workflows |
121
- | **Full** (default) | 61 | Everything enabled |
115
+ | **Code Focus** | 42 | Software development, SWE tasks |
116
+ | **Balanced** | 53 | General-purpose, mixed workflows |
117
+ | **Heavy Coding** | 57 | Max code tools + agentic workflows |
118
+ | **Full** (default) | 64 | Everything enabled |
122
119
 
123
120
  ### Developer Experience
124
121
  - **Claude Code** &mdash; First-class support
@@ -136,6 +133,14 @@ Skills automatically adapt to your configured API keys. Even with just 1-2 provi
136
133
  npm install -g tachibot-mcp
137
134
  ```
138
135
 
136
+ ### Setup wizard
137
+
138
+ ```bash
139
+ npx -y -p tachibot-mcp tachibot init
140
+ ```
141
+
142
+ Detects your keys and clients, then prints the exact config for Claude Code and Claude Desktop.
143
+
139
144
  ### Claude Code (one-liner)
140
145
 
141
146
  ```bash
@@ -146,6 +151,8 @@ Then verify with `/mcp`. Add API keys with `--env`, e.g. `--env OPENROUTER_API_K
146
151
 
147
152
  ### Setup (Claude Desktop)
148
153
 
154
+ **One-click (easiest):** download [`tachibot-mcp.mcpb`](https://github.com/byPawel/tachibot-mcp/releases/latest) from the latest release and double-click it — Claude Desktop installs the extension with no JSON editing. Add your API keys when prompted (or later via the extension settings).
155
+
149
156
  **Gateway Mode (Recommended)** &mdash; 2 keys, all providers:
150
157
 
151
158
  ```json
@@ -188,16 +195,16 @@ See [Installation Guide](docs/INSTALLATION_BOTH.md) for detailed instructions.
188
195
 
189
196
  ---
190
197
 
191
- ## Tool Ecosystem (61 Tools)
198
+ ## Tool Ecosystem (64 Tools)
192
199
 
193
200
  ### Research & Search (5)
194
201
  `perplexity_ask` &#183; `perplexity_reason` &#183; `grok_search` &#183; `openai_search` &#183; `gemini_search`
195
202
 
196
- ### Reasoning & Planning (13)
197
- `grok_reason` &#183; `openai_reason` &#183; `qwen_reason` &#183; `qwq_reason` &#183; `kimi_thinking` &#183; `kimi_decompose` &#183; `deepseek_reason` &#183; `glm_reason` &#183; `stepfun_reason` &#183; `ernie_reason` &#183; `planner_maker` &#183; `planner_runner` &#183; `list_plans`
203
+ ### Reasoning & Planning (14)
204
+ `grok_reason` &#183; `openai_reason` &#183; `qwen_reason` &#183; `qwq_reason` &#183; `kimi_thinking` &#183; `kimi_decompose` &#183; `deepseek_reason` &#183; `glm_reason` &#183; `stepfun_reason` &#183; `ernie_reason` &#183; `planner_maker` &#183; `planner_runner` &#183; `list_plans` &#183; `spec_writer`
198
205
 
199
- ### Code Intelligence (10)
200
- `kimi_code` &#183; `grok_code` &#183; `grok_debug` &#183; `qwen_coder` &#183; `qwen_algo` &#183; `qwen_competitive` &#183; `deepseek_algo` &#183; `minimax_code` &#183; `minimax_agent` &#183; `testgen`
206
+ ### Code Intelligence (11)
207
+ `kimi_code` &#183; `grok_code` &#183; `grok_debug` &#183; `qwen_coder` &#183; `qwen_algo` &#183; `qwen_competitive` &#183; `deepseek_algo` &#183; `minimax_code` &#183; `minimax_agent` &#183; `testgen` &#183; `debug_triage`
201
208
 
202
209
  ### Analysis & Judgment (14)
203
210
  `gemini_analyze_text` &#183; `gemini_analyze_code` &#183; `gemini_judge` &#183; `jury` &#183; `diff_review` &#183; `plan_critique` &#183; `gemini_brainstorm` &#183; `openai_brainstorm` &#183; `openai_code_review` &#183; `openai_explain` &#183; `grok_brainstorm` &#183; `grok_architect` &#183; `security_review` &#183; `kimi_long_context`
@@ -208,8 +215,8 @@ See [Installation Guide](docs/INSTALLATION_BOTH.md) for detailed instructions.
208
215
  ### Workflows (9)
209
216
  `workflow` &#183; `workflow_start` &#183; `continue_workflow` &#183; `list_workflows` &#183; `create_workflow` &#183; `visualize_workflow` &#183; `workflow_status` &#183; `validate_workflow` &#183; `validate_workflow_file`
210
217
 
211
- ### Prompt Engineering (3)
212
- `list_prompt_techniques` &#183; `preview_prompt_technique` &#183; `execute_prompt_technique`
218
+ ### Prompt Engineering (4)
219
+ `list_prompt_techniques` &#183; `preview_prompt_technique` &#183; `execute_prompt_technique` &#183; `refine_prompt`
213
220
 
214
221
  ### Local Models (1)
215
222
  `local_query` &mdash; any OpenAI-compatible local server (Ollama / LM Studio / llama.cpp / vLLM). Zero-cost, offline, private; also available as the `local` jury juror (`hermes` is accepted as a legacy alias). Runs whatever `LOCAL_LLM_MODEL` points at &mdash; e.g. a Nous Hermes build (`ollama pull hermes3`). Note the [Hermes agent](https://hermes-agent.nousresearch.com) itself is model-agnostic &mdash; it runs on 300+ backends (GPT, Claude, Gemini, DeepSeek, or self-hosted Ollama/vLLM) &mdash; so "Hermes" was never a guarantee of distinct weights.
@@ -0,0 +1,218 @@
1
+ /**
2
+ * `tachibot init` — setup wizard. Detection + emission first: pure functions
3
+ * detect keys/clients and emit EXACT per-client instructions; a thin
4
+ * readline layer only picks the client. Keys are never written to disk by
5
+ * default and never echoed (masked to 6 chars). Node built-ins only.
6
+ */
7
+ import * as fs from "node:fs";
8
+ import * as os from "node:os";
9
+ import * as path from "node:path";
10
+ import * as readline from "node:readline/promises";
11
+ import { fileURLToPath } from "node:url";
12
+ const KEYS = [
13
+ { name: "OpenRouter", envVar: "OPENROUTER_API_KEY", unlocks: "DeepSeek/GLM/Kimi/Qwen/MiniMax/StepFun/ERNIE + planner (~30 tools)" },
14
+ { name: "Perplexity", envVar: "PERPLEXITY_API_KEY", unlocks: "web research tools" },
15
+ { name: "Gemini / Google", envVar: "GOOGLE_API_KEY", unlocks: "Gemini tools + jury judge + diff_review/plan_critique" },
16
+ { name: "OpenAI", envVar: "OPENAI_API_KEY", unlocks: "GPT-5.5 tools + spec_writer" },
17
+ { name: "Grok / xAI", envVar: "GROK_API_KEY", unlocks: "Grok tools + debug_triage" },
18
+ ];
19
+ function defaultProbe() {
20
+ return {
21
+ // PATH lookup done via fs, not a subprocess: no shell involved, no injection surface.
22
+ which: (bin) => {
23
+ const dirs = (process.env.PATH || "").split(path.delimiter).filter(Boolean);
24
+ const exts = process.platform === "win32" ? [".exe", ".cmd", ".bat", ""] : [""];
25
+ return dirs.some((dir) => exts.some((ext) => {
26
+ try {
27
+ return fs.statSync(path.join(dir, bin + ext)).isFile();
28
+ }
29
+ catch {
30
+ return false;
31
+ }
32
+ }));
33
+ },
34
+ exists: (p) => fs.existsSync(p),
35
+ };
36
+ }
37
+ function desktopConfigPath() {
38
+ if (process.platform === "darwin") {
39
+ return path.join(os.homedir(), "Library", "Application Support", "Claude", "claude_desktop_config.json");
40
+ }
41
+ if (process.platform === "win32") {
42
+ return path.join(process.env.APPDATA || "", "Claude", "claude_desktop_config.json");
43
+ }
44
+ return path.join(os.homedir(), ".config", "Claude", "claude_desktop_config.json");
45
+ }
46
+ export function detectSetup(env = process.env, probe = defaultProbe()) {
47
+ const keys = KEYS.map((k) => ({
48
+ name: k.name,
49
+ envVar: k.envVar,
50
+ present: Boolean(env[k.envVar]?.trim()),
51
+ unlocks: k.unlocks,
52
+ }));
53
+ // Gemini/Grok alternates count as present
54
+ const alt = (primary, alternate) => {
55
+ const row = keys.find((k) => k.envVar === primary);
56
+ if (!row.present && env[alternate]?.trim())
57
+ row.present = true;
58
+ };
59
+ alt("GOOGLE_API_KEY", "GEMINI_API_KEY");
60
+ alt("GROK_API_KEY", "XAI_API_KEY");
61
+ const dcp = desktopConfigPath();
62
+ return {
63
+ keys,
64
+ clients: {
65
+ claudeCode: probe.which("claude"),
66
+ claudeDesktop: probe.exists(dcp),
67
+ desktopConfigPath: probe.exists(dcp) ? dcp : null,
68
+ },
69
+ };
70
+ }
71
+ export function buildClaudeCodeCommand(setup) {
72
+ const envFlags = setup.keys
73
+ .filter((k) => k.present)
74
+ .map((k) => `--env ${k.envVar}=<your-${k.name.toLowerCase().replace(/[^a-z]+/g, "-")}-key>`)
75
+ .join(" \\\n ");
76
+ return [
77
+ "claude mcp add tachibot \\",
78
+ envFlags ? ` ${envFlags} \\` : null,
79
+ " -- npx -y -p tachibot-mcp tachibot",
80
+ ].filter(Boolean).join("\n");
81
+ }
82
+ export function buildDesktopSnippet(setup, profile) {
83
+ const env = {};
84
+ for (const k of setup.keys.filter((k) => k.present))
85
+ env[k.envVar] = `<your-${k.envVar}>`;
86
+ env.TACHIBOT_PROFILE = profile;
87
+ return JSON.stringify({ mcpServers: { tachibot: { command: "tachibot", env } } }, null, 2);
88
+ }
89
+ const mask = (v) => (v ? `${v.slice(0, 6)}…` : "");
90
+ /** The package's bundled skills dir. dist/src/cli/init.js → up 3 → pkg root. */
91
+ export function resolveSkillsDir() {
92
+ const here = path.dirname(fileURLToPath(import.meta.url));
93
+ return path.resolve(here, "..", "..", "..", "skills");
94
+ }
95
+ /** Read `skills/<name>/SKILL.md`, pulling the frontmatter `description`. */
96
+ export function listAvailableSkills(skillsDir) {
97
+ let entries;
98
+ try {
99
+ entries = fs.readdirSync(skillsDir).sort();
100
+ }
101
+ catch {
102
+ return [];
103
+ }
104
+ const skills = [];
105
+ for (const name of entries) {
106
+ let text;
107
+ try {
108
+ text = fs.readFileSync(path.join(skillsDir, name, "SKILL.md"), "utf8");
109
+ }
110
+ catch {
111
+ continue;
112
+ } // not a skill dir
113
+ const m = text.match(/^description:\s*(.+)$/m);
114
+ skills.push({ name, description: m ? m[1].trim() : "" });
115
+ }
116
+ return skills;
117
+ }
118
+ /**
119
+ * Parse a "skip which" answer ("1,3, 5") into a set of 0-based indices over a
120
+ * list of `count`. Blanks, non-numbers, and out-of-range tokens are ignored so
121
+ * a fat-fingered entry never throws or skips the wrong skill.
122
+ */
123
+ export function parseSkipSelection(input, count) {
124
+ const skip = new Set();
125
+ for (const tok of input.split(/[\s,]+/).filter(Boolean)) {
126
+ const n = Number(tok);
127
+ if (Number.isInteger(n) && n >= 1 && n <= count)
128
+ skip.add(n - 1);
129
+ }
130
+ return skip;
131
+ }
132
+ /** Copy the chosen skills' SKILL.md into `targetDir/<name>/`. Returns installed names. */
133
+ export function installSkills(names, skillsDir, targetDir) {
134
+ const installed = [];
135
+ for (const name of names) {
136
+ const src = path.join(skillsDir, name, "SKILL.md");
137
+ if (!fs.existsSync(src))
138
+ continue;
139
+ const dest = path.join(targetDir, name);
140
+ fs.mkdirSync(dest, { recursive: true });
141
+ fs.copyFileSync(src, path.join(dest, "SKILL.md"));
142
+ installed.push(name);
143
+ }
144
+ return installed;
145
+ }
146
+ export async function runInitWizard() {
147
+ const setup = detectSetup();
148
+ const out = (s) => process.stdout.write(s + "\n");
149
+ out("\nTACHIBOT INIT\n=============");
150
+ out("\nAPI keys detected in this shell:");
151
+ for (const k of setup.keys) {
152
+ out(` ${k.present ? "✓" : "✗"} ${k.name} (${k.envVar})${k.present ? ` ${mask(process.env[k.envVar])}` : ""} — ${k.unlocks}`);
153
+ }
154
+ if (!setup.keys.some((k) => k.present)) {
155
+ out("\nNo keys found. Get ONE key to start — OPENROUTER_API_KEY unlocks the most tools (openrouter.ai).");
156
+ }
157
+ out("\nClients detected:");
158
+ out(` ${setup.clients.claudeCode ? "✓" : "✗"} Claude Code (claude on PATH)`);
159
+ out(` ${setup.clients.claudeDesktop ? "✓" : "✗"} Claude Desktop${setup.clients.desktopConfigPath ? ` (${setup.clients.desktopConfigPath})` : ""}`);
160
+ // Non-interactive (piped stdin / CI): prompting would hang on EOF with an
161
+ // "unsettled top-level await". Print the config for both clients with sane
162
+ // defaults and how to install skills, then exit cleanly.
163
+ if (!process.stdin.isTTY) {
164
+ out("\n(non-interactive: printing full config — run in a terminal to choose options)\n");
165
+ out("— Claude Code —\n");
166
+ out(buildClaudeCodeCommand(setup));
167
+ out("\n— Claude Desktop — double-click the .mcpb from GitHub releases, or merge into");
168
+ out((setup.clients.desktopConfigPath ?? desktopConfigPath()) + ":\n");
169
+ out(buildDesktopSnippet(setup, "full"));
170
+ const n = listAvailableSkills(resolveSkillsDir()).length;
171
+ out(`\nClaude Code skills (${n}): install with npm run install-skills (or re-run this wizard in a terminal to choose which).`);
172
+ out("\nOnce connected, run the `doctor` tool to see which tools your keys unlock.");
173
+ return;
174
+ }
175
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
176
+ try {
177
+ const choice = (await rl.question("\nSet up for: [1] Claude Code [2] Claude Desktop [3] both [q] quit > ")).trim();
178
+ if (choice === "q")
179
+ return;
180
+ const profile = (await rl.question("Profile [full=all 64 tools | balanced | code_focus] (default: full) > ")).trim() || "full";
181
+ if (choice === "1" || choice === "3") {
182
+ out("\n— Claude Code — run this (fill in your real keys):\n");
183
+ out(buildClaudeCodeCommand(setup));
184
+ out("\nThen verify with /mcp inside Claude Code.");
185
+ }
186
+ if (choice === "2" || choice === "3") {
187
+ out("\n— Claude Desktop — easiest: double-click the tachibot-mcp.mcpb extension package (see GitHub releases).");
188
+ out("Or merge this into " + (setup.clients.desktopConfigPath ?? desktopConfigPath()) + ":\n");
189
+ out(buildDesktopSnippet(setup, profile));
190
+ out("\nThen restart Claude Desktop.");
191
+ }
192
+ // Skills — Claude Code slash commands, opt-in with per-skill skip.
193
+ const skillsDir = resolveSkillsDir();
194
+ const available = listAvailableSkills(skillsDir);
195
+ if (available.length > 0 && choice !== "2") {
196
+ const target = path.join(os.homedir(), ".claude", "skills");
197
+ const ans = (await rl.question(`\nInstall ${available.length} Claude Code skills to ${target}? [Enter]=all · [s]=choose which to skip · [n]=none > `)).trim().toLowerCase();
198
+ if (ans !== "n") {
199
+ let chosen = available.map((s) => s.name);
200
+ if (ans === "s") {
201
+ out("");
202
+ available.forEach((s, i) => out(` ${String(i + 1).padStart(2)}. /${s.name} — ${s.description}`));
203
+ const skip = parseSkipSelection((await rl.question("\nSkip which? (comma-separated numbers, blank = skip none) > ")).trim(), available.length);
204
+ chosen = available.filter((_, i) => !skip.has(i)).map((s) => s.name);
205
+ }
206
+ const installed = installSkills(chosen, skillsDir, target);
207
+ out(`\n✓ Installed ${installed.length} skill${installed.length === 1 ? "" : "s"}: ${installed.map((n) => "/" + n).join(", ")}`);
208
+ const skipped = available.filter((s) => !installed.includes(s.name));
209
+ if (skipped.length)
210
+ out(` Skipped: ${skipped.map((s) => "/" + s.name).join(", ")}`);
211
+ }
212
+ }
213
+ out("\nFirst thing to run once connected: the `doctor` tool — it shows which tools your keys unlock.");
214
+ }
215
+ finally {
216
+ rl.close();
217
+ }
218
+ }
@@ -1,14 +1,18 @@
1
- import { ReasoningMode, REASONING_TEMPLATES, MODEL_PERSONAS } from "../../../../reasoning-chain.js";
2
- const renderWorkflowCascade = (steps, title) => {
3
- const lines = [`## ${title}`];
4
- steps.forEach((s, i) => lines.push(`${i + 1}. [${s.status}] ${s.name} (${s.model})`));
5
- return lines.join('\n');
6
- };
7
- const renderProgressReel = (phases, title) => {
8
- const lines = [`## ${title}`];
9
- phases.forEach(p => lines.push(`- [${p.status}] ${p.name}`));
10
- return lines.join('\n');
11
- };
1
+ import { ReasoningMode, REASONING_TEMPLATES } from "../../../../reasoning-chain.js";
2
+ // import {
3
+ // renderWorkflowCascade,
4
+ // renderProgressReel,
5
+ // renderThinkingChainArbor,
6
+ // renderGradientDivider,
7
+ // renderGradientBorderBox,
8
+ // renderTable,
9
+ // renderKeyValueTable,
10
+ // renderQuickFlow,
11
+ // icons,
12
+ // WorkflowStep,
13
+ // ProgressPhase,
14
+ // } from "../../../../utils/ink-renderer.js";
15
+ // Ink disabled — MCP clients render markdown, so these emit plain markdown.
12
16
  const renderThinkingChainArbor = (thoughts, title) => {
13
17
  const lines = [`## ${title}`];
14
18
  thoughts.forEach((t, i) => lines.push(`${i + 1}. (${t.model}) ${t.thought}`));
@@ -30,9 +34,6 @@ const renderTable = (data) => {
30
34
  const renderKeyValueTable = (data) => {
31
35
  return Object.entries(data).map(([k, v]) => `${k}: ${v}`).join('\n');
32
36
  };
33
- const renderQuickFlow = (steps, title) => {
34
- return `## ${title}\n${steps.join(' -> ')}`;
35
- };
36
37
  const icons = {
37
38
  brain: '*',
38
39
  sparkle: '*',
@@ -52,54 +53,26 @@ export class VisualizationService {
52
53
  */
53
54
  generateOrchestrationPlan(session) {
54
55
  const steps = session.chain.steps;
56
+ const done = session.currentStep;
57
+ // One clean header line + a per-step table. The old layout rendered the
58
+ // same step list four times (cascade, flow, progress reel, table) plus a
59
+ // metadata block and faux "gradient" boxes — a wall of duplicated scaffold.
60
+ // MCP clients render markdown, so a single table IS the visualization.
55
61
  const lines = [];
56
- // Header with gradient border box
57
- lines.push(renderGradientBorderBox(`${icons.brain} Collaborative Reasoning\n\n${session.objective}\n\nDomain: ${session.domain} | Session: ${session.id.slice(0, 8)}`, { width: 60, gradient: 'cristal' }));
58
- lines.push('');
59
- // Workflow cascade showing model flow
60
- const cascadeSteps = steps.map((step, idx) => ({
61
- name: `${this.getModeIcon(step.mode)} ${step.mode}`,
62
- model: step.model,
63
- status: idx < session.currentStep ? 'completed' :
64
- idx === session.currentStep ? 'running' : 'pending',
65
- duration: idx < session.currentStep ? 1000 + Math.random() * 2000 : undefined,
66
- }));
67
- lines.push(renderWorkflowCascade(cascadeSteps, 'Reasoning Chain'));
62
+ lines.push(`**Collaborative Reasoning** · ${session.objective}`);
63
+ lines.push(`${session.domain} · ${this.modelTurnTaking ? 'sequential' : 'parallel'} · ` +
64
+ `step ${Math.min(done + 1, steps.length)}/${steps.length} · \`${session.id.slice(0, 8)}\``);
68
65
  lines.push('');
69
- // Quick flow diagram
70
- const flowSteps = steps.map(s => `${s.model}: ${s.mode}`);
71
- lines.push(renderQuickFlow(flowSteps, 'Execution Flow'));
72
- lines.push('');
73
- // Progress reel
74
- const progressSteps = steps.map((step, idx) => ({
75
- name: `${step.model} - ${step.mode}`,
76
- status: idx < session.currentStep ? 'completed' :
77
- idx === session.currentStep ? 'active' : 'pending',
66
+ // One table: status · mode · model, in order. The mode already conveys each
67
+ // step's job, so no "Role" column (its half-filled "AI" fallback is the bit
68
+ // that read as generic). Status marks done (✓) / current (▸) / pending (·).
69
+ const tableData = steps.map((step, idx) => ({
70
+ '#': String(idx + 1),
71
+ '': idx < done ? '✓' : idx === done ? '▸' : '·',
72
+ Step: `${this.getModeIcon(step.mode)} ${step.mode}`,
73
+ Model: step.model,
78
74
  }));
79
- lines.push(renderProgressReel(progressSteps, 'Step Progress'));
80
- lines.push('');
81
- // Detailed steps table
82
- const tableData = steps.map((step, idx) => {
83
- const persona = Object.values(MODEL_PERSONAS).find(p => p.model === step.model);
84
- return {
85
- '#': String(idx + 1),
86
- Mode: `${this.getModeIcon(step.mode)} ${step.mode}`,
87
- Model: step.model,
88
- Role: persona?.role || 'AI',
89
- Status: idx < session.currentStep ? '✓' : idx === session.currentStep ? '⟳' : '○',
90
- };
91
- });
92
75
  lines.push(renderTable(tableData));
93
- lines.push('');
94
- // Session info
95
- lines.push(renderKeyValueTable({
96
- 'Session ID': session.id,
97
- 'Total Steps': String(steps.length),
98
- 'Current Step': String(session.currentStep + 1),
99
- 'Turn Taking': this.modelTurnTaking ? 'Sequential' : 'Parallel',
100
- }));
101
- lines.push('');
102
- lines.push(renderGradientDivider(60, 'rainbow'));
103
76
  return lines.join('\n');
104
77
  }
105
78
  /**
@@ -112,7 +85,7 @@ export class VisualizationService {
112
85
  const currentMode = currentStep?.mode || ReasoningMode.BRAINSTORM;
113
86
  const lines = [];
114
87
  // Thinking chain visualization
115
- const thoughts = session.chain.steps.slice(0, stage + 1).map((step, idx) => ({
88
+ const thoughts = session.chain.steps.slice(0, stage + 1).map((step) => ({
116
89
  thought: `${step.mode}: ${step.prompt.slice(0, 50)}...`,
117
90
  model: step.model,
118
91
  isRevision: step.mode === ReasoningMode.CRITIQUE,
@@ -1,5 +1,5 @@
1
1
  export const balancedProfile = {
2
- description: "Balanced set for general use (50 tools)",
2
+ description: "Balanced set for general use (53 tools)",
3
3
  tools: {
4
4
  think: true,
5
5
  focus: true,
@@ -12,6 +12,7 @@ export const balancedProfile = {
12
12
  grok_reason: true,
13
13
  grok_code: true,
14
14
  grok_debug: false,
15
+ debug_triage: true,
15
16
  grok_architect: false,
16
17
  grok_brainstorm: false,
17
18
  grok_search: true,
@@ -20,6 +21,8 @@ export const balancedProfile = {
20
21
  openai_code_review: false,
21
22
  openai_explain: false,
22
23
  openai_search: true,
24
+ spec_writer: true,
25
+ refine_prompt: true,
23
26
  gemini_brainstorm: true,
24
27
  gemini_analyze_code: true,
25
28
  gemini_analyze_text: true,
@@ -1,5 +1,5 @@
1
1
  export const codeFocusProfile = {
2
- description: "Code-heavy work with debugging and analysis (39 tools)",
2
+ description: "Code-heavy work with debugging and analysis (42 tools)",
3
3
  tools: {
4
4
  think: true,
5
5
  focus: true,
@@ -12,6 +12,7 @@ export const codeFocusProfile = {
12
12
  grok_reason: true,
13
13
  grok_code: true,
14
14
  grok_debug: true,
15
+ debug_triage: true,
15
16
  grok_architect: false,
16
17
  grok_brainstorm: false,
17
18
  grok_search: false,
@@ -20,6 +21,8 @@ export const codeFocusProfile = {
20
21
  openai_code_review: true,
21
22
  openai_explain: false,
22
23
  openai_search: false,
24
+ spec_writer: true,
25
+ refine_prompt: true,
23
26
  gemini_brainstorm: true,
24
27
  gemini_analyze_code: true,
25
28
  gemini_analyze_text: false,
@@ -1,5 +1,5 @@
1
1
  export const fullProfile = {
2
- description: "Default profile — all tools enabled for maximum capability (61 tools)",
2
+ description: "Default profile — all tools enabled for maximum capability (64 tools)",
3
3
  tools: {
4
4
  think: true,
5
5
  focus: true,
@@ -12,6 +12,7 @@ export const fullProfile = {
12
12
  grok_reason: true,
13
13
  grok_code: true,
14
14
  grok_debug: true,
15
+ debug_triage: true,
15
16
  grok_architect: true,
16
17
  grok_brainstorm: true,
17
18
  grok_search: true,
@@ -20,6 +21,8 @@ export const fullProfile = {
20
21
  openai_code_review: true,
21
22
  openai_explain: true,
22
23
  openai_search: true,
24
+ spec_writer: true,
25
+ refine_prompt: true,
23
26
  gemini_brainstorm: true,
24
27
  gemini_analyze_code: true,
25
28
  gemini_analyze_text: true,
@@ -1,5 +1,5 @@
1
1
  export const heavyCodingProfile = {
2
- description: "Heavy coding with all reasoning & code tools (54 tools)",
2
+ description: "Heavy coding with all reasoning & code tools (57 tools)",
3
3
  tools: {
4
4
  // Core reasoning - all enabled
5
5
  think: true,
@@ -15,6 +15,7 @@ export const heavyCodingProfile = {
15
15
  grok_reason: true,
16
16
  grok_code: true,
17
17
  grok_debug: true,
18
+ debug_triage: true,
18
19
  grok_architect: true,
19
20
  grok_brainstorm: true,
20
21
  grok_search: true,
@@ -24,6 +25,8 @@ export const heavyCodingProfile = {
24
25
  openai_code_review: true,
25
26
  openai_explain: true,
26
27
  openai_search: true,
28
+ spec_writer: true,
29
+ refine_prompt: true,
27
30
  // Gemini - all enabled
28
31
  gemini_brainstorm: true,
29
32
  gemini_analyze_code: true,
@@ -12,6 +12,7 @@ export const minimalProfile = {
12
12
  grok_reason: true,
13
13
  grok_code: false,
14
14
  grok_debug: false,
15
+ debug_triage: false,
15
16
  grok_architect: false,
16
17
  grok_brainstorm: false,
17
18
  grok_search: false,
@@ -20,6 +21,8 @@ export const minimalProfile = {
20
21
  openai_code_review: false,
21
22
  openai_explain: false,
22
23
  openai_search: false,
24
+ spec_writer: false,
25
+ refine_prompt: false,
23
26
  gemini_brainstorm: true,
24
27
  gemini_analyze_code: false,
25
28
  gemini_analyze_text: false,