diff --git a/README.md b/README.md index 38654ab..1f69957 100755 --- a/README.md +++ b/README.md @@ -80,18 +80,9 @@ Internal surface: ## 🚀 Quickstart -### 🤖 Agent-first install +### 🐳 Docker (Default) -If you are using Claude Code, Cursor, Gemini CLI, Copilot CLI, OpenCode, or Codex, paste this at your agent: - -> Fetch and follow the instructions at https://raw.githubusercontent.com/orkait/hyperstack/main/install.md - -The agent will pull the Docker image and configure your MCP client. - -### 🐳 Docker (manual) - -Hyperstack uses a persistent container plus `docker exec`. Do **not** use the -older `docker run --rm` per-session pattern. +Hyperstack uses a persistent container plus `docker exec`. This keeps startup cheap across sessions and ensures 100% environment stability. 1. Pull the image: @@ -109,7 +100,7 @@ docker run -d --name hyperstack-mcp --restart unless-stopped \ ghcr.io/orkait/hyperstack:main infinity ``` -3. Add this to `~/.claude.json`, Cursor config, or equivalent: +3. Add this to your MCP settings (`~/.claude.json`, Cursor, Windsurf, etc.): ```json { @@ -122,8 +113,14 @@ docker run -d --name hyperstack-mcp --restart unless-stopped \ } ``` -This keeps startup cheap across sessions and matches the installation flow in -[install.md](/mnt/storage/codespace/code/orkait/hyperstack/install.md). +### 🤖 Agent Autopilot + +If you are using Claude Code, Cursor, Windsurf, Roo Code, or Gemini, you can use the autopilot to self-configure. Paste this at your agent: + +> Fetch and follow the instructions at https://raw.githubusercontent.com/orkait/hyperstack/main/install.md + +The autopilot will detect your environment and propose the correct Docker-based configuration block. + ### 🔧 Install the skills diff --git a/install.md b/install.md index 60da9a8..1e2073d 100644 --- a/install.md +++ b/install.md @@ -42,12 +42,14 @@ The system automatically probes for signatures: - **Known Paths**: Probes for `.claude.json`, `.cursor/`, `.codeium/windsurf/`, `.roo/`, and `.gemini/`. ### 2. Run the Autopilot -As an agent, you should call the `hyperstack_setup` tool immediately. It will return the detected path and the JSON configuration block required for that specific tool's schema. +As an agent, you should call the `hyperstack_setup` tool immediately. **By default, it generates a Docker-based configuration** using the optimized `docker exec` pattern. + +If Docker is not available, you can explicitly request the local method: `hyperstack_setup(method: "local")`. **If the environment is unknown:** 1. Call `web_search` with a query like `[IDE Name] MCP configuration path`. 2. Provide the result to `hyperstack_setup(researchResult: "...")`. -3. The tool will generate the final patch. +3. The tool will generate the final Docker-based patch. ## Step 2: Install the Skills diff --git a/src/internal/setup-hyperstack.ts b/src/internal/setup-hyperstack.ts index b0a6bba..ad516e1 100644 --- a/src/internal/setup-hyperstack.ts +++ b/src/internal/setup-hyperstack.ts @@ -64,46 +64,49 @@ export function findConfigFile(platform: string): string | null { return null; } -export function generateMcpPatch(configPath: string, pluginRoot: string) { - const binaryPath = path.join(pluginRoot, "bin", "hyperstack.mjs"); - const hookPath = path.join(pluginRoot, "hooks", "session-start.mjs"); - const serverConfig = { +export function generateMcpPatch( + configPath: string, + pluginRoot: string, + method: "docker" | "local" = "docker" +) { + const isClaude = configPath.endsWith(".claude.json"); + const isGemini = configPath.includes("settings.json") && configPath.includes(".gemini"); + + const binaryPath = path.join(pluginRoot, "bin", "hyperstack.mjs"); + const localConfig = { command: "node", args: [binaryPath], env: { - HYPERSTACK_ROOT: pluginRoot - } + HYPERSTACK_ROOT: pluginRoot, + }, }; - // Determine schema based on filename - const isClaude = configPath.endsWith(".claude.json"); - const isWindsurf = configPath.includes("windsurf"); - const isGemini = configPath.includes("gemini"); + const dockerConfig = { + command: "docker", + args: ["exec", "-i", "hyperstack-mcp", "bun", "/app/src/index.ts"], + env: { + HYPERSTACK_ROOT: pluginRoot, // Still helpful for skills indexing + }, + }; - if (isClaude) { - return { - mcpServers: { - hyperstack: serverConfig - } - }; - } + const serverConfig = method === "docker" ? dockerConfig : localConfig; if (isGemini) { return { extensions: { hyperstack: { ...serverConfig, - type: "stdio" - } - } + type: "stdio", + }, + }, }; } - // Default MCP schema + // Default MCP schema (Claude, Cursor, Windsurf, Roo Code) return { mcpServers: { - hyperstack: serverConfig - } + hyperstack: serverConfig, + }, }; } diff --git a/src/plugins/hyperstack/tools/setup.ts b/src/plugins/hyperstack/tools/setup.ts index 6997d26..7499bf0 100644 --- a/src/plugins/hyperstack/tools/setup.ts +++ b/src/plugins/hyperstack/tools/setup.ts @@ -9,8 +9,9 @@ export function registerSetupTool(server: McpServer) { "Identify current IDE/CLI environment and generate a tailored MCP configuration patch for Hyperstack.", { researchResult: z.string().optional().describe("If the environment was unknown, provide the researched config path or schema details here."), + method: z.enum(["docker", "local"]).default("docker").describe("Preferred installation method. Use 'docker' (default) for stable persistent environments, 'local' for fallback."), }, - async ({ researchResult }) => { + async ({ researchResult, method }) => { const platform = setup.detectEnvironment(); const configPath = setup.findConfigFile(platform); @@ -37,7 +38,7 @@ export function registerSetupTool(server: McpServer) { }; } - const patch = setup.generateMcpPatch(activeConfigPath, pluginRoot); + const patch = setup.generateMcpPatch(activeConfigPath, pluginRoot, method); return { content: [{ diff --git a/verify-setup.ts b/verify-setup.ts index ba1e827..4deb753 100644 --- a/verify-setup.ts +++ b/verify-setup.ts @@ -9,9 +9,15 @@ async function verify() { console.log(`Config Path Found: ${configPath || "None (expected if running in clean environment)"}`); if (configPath || platform !== "unknown") { - const patch = setup.generateMcpPatch(configPath || "/tmp/mcp.json", process.cwd()); - console.log("Proposed Patch:"); - console.log(JSON.stringify(patch, null, 2)); + const finalPath = configPath || "/tmp/mcp.json"; + + console.log("\nProposed Patch (Method: DOCKER - Default):"); + const dockerPatch = setup.generateMcpPatch(finalPath, process.cwd(), "docker"); + console.log(JSON.stringify(dockerPatch, null, 2)); + + console.log("\nProposed Patch (Method: LOCAL):"); + const localPatch = setup.generateMcpPatch(finalPath, process.cwd(), "local"); + console.log(JSON.stringify(localPatch, null, 2)); } else { console.log("Environment unknown - research fallback would trigger here."); }