Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 10 additions & 11 deletions install.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,25 +32,24 @@ If you install only one public piece:

## Step 1: Detect and Configure (Autopilot)

Hyperstack features an **Autonomous Research-Driven Installer** that identifies your environment (Claude Code, Cursor, Windsurf, Roo Code, etc.) and generates a tailored configuration patch.
Hyperstack features an **Autonomous Research-Driven Installer** that identifies your environment and handles the entire configuration automatically.

**If you are an AI assistant reading this file:**
1. Call `run_command` with: `bun run setup` inside the repository.
2. The script will automatically detect the IDE, symlink the skills, deep-merge the MCP config, and provision the Docker container.
3. Inform the user that setup is complete and ask them to restart the session.

> [!CAUTION]
> **CRITICAL**: RUN ONLY if the installer is not able to do it correctly. If you must install manually for the current IDE/CLI, you must validate that the MCP connection is successful before proceeding.

### 1. Identify your Environment
The system automatically probes for signatures:
- **Antigravity**: `ANTIGRAVITY_AGENT`
- **Claude Code**: `CLAUDE_PLUGIN_ROOT`
- **Cursor**: `CURSOR_PLUGIN_ROOT`
- **VS Code Derivatives**: `VSCODE_PID`
- **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. **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 Docker-based patch.

## Step 2: Install the Skills

The skills contain the adversarial enforcement gates. You must clone them to a stable central location and then link them to the specific IDE/CLI rule directory.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@orkait-ai/hyperstack",
"version": "1.1.2",
"version": "1.1.3",
"description": "Disciplined MCP server + skill system. 12 plugins, 80 tools, 21 skills with adversarial enforcement. Designer/DESIGN.md pipeline, shadcn/ui, React Flow, Motion, Lenis, React 19, Echo, Go, Rust, design tokens, UI/UX.",
"bin": {
"hyperstack": "bin/hyperstack.mjs"
Expand Down
29 changes: 11 additions & 18 deletions scripts/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,27 +38,20 @@ async function main() {
setup.selfHealDocker();

const patch = setup.generateMcpPatch(configPath, pluginRoot, platform);

// Proactively apply the patch
setup.applyMcpPatch(configPath, patch);

console.log("\n📋 Proposed Configuration Patch:");
console.log("\n📋 Configuration Summary:");
console.log("---------------------------------");

if (patch.format === "toml-mcp_servers") {
console.log("# Append this to:", configPath);
console.log(patch.content as string);
console.log("---------------------------------\n");
console.log("To finish manual setup:");
console.log(`1. Run the symlink command above (if applicable).`);
console.log(`2. Append the TOML block above to ${configPath}`);
console.log("3. Run 'codex /mcp' to verify the connection.");
} else {
console.log(JSON.stringify(patch.content, null, 2));
console.log("---------------------------------\n");
console.log("To finish manual setup:");
console.log(`1. Run the symlink command above (if applicable).`);
console.log(`2. Open ${configPath}`);
console.log("3. Merge the patch above into your config (deep-merge, don't replace).");
console.log("4. Restart your AI client.");
console.log(`✅ Environment: ${platform}`);
console.log(`✅ Config Path: ${configPath}`);
if (skillPath) {
console.log(`✅ Skill Target: ${path.join(skillPath, "hyperstack")}`);
}
console.log("---------------------------------\n");

console.log("🚀 Setup Complete! You must restart your AI client to pick up the new tools.");
}

main().catch(console.error);
50 changes: 50 additions & 0 deletions src/internal/setup-hyperstack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,56 @@ export function generateMcpPatch(
};
}

/**
* Persistently applies the generated patch to the user's config file
* without destroying existing settings.
*/
export function applyMcpPatch(configPath: string, patch: { format: PlatformFormat; content: any }) {
if (!fs.existsSync(configPath)) {
// If it doesn't exist, create it with the patch
if (typeof patch.content === "string") {
fs.writeFileSync(configPath, patch.content);
} else {
fs.writeFileSync(configPath, JSON.stringify(patch.content, null, 2));
}
return;
}

if (patch.format === "toml-mcp_servers") {
let content = fs.readFileSync(configPath, "utf8");
if (!content.includes("[mcp_servers.hyperstack]")) {
fs.appendFileSync(configPath, "\n" + patch.content);
console.log(`✅ Appended Hyperstack block to ${configPath}`);
} else {
console.log(`ℹ️ Hyperstack block already exists in ${configPath}`);
}
return;
}

// JSON deep-merge
try {
const existing = JSON.parse(fs.readFileSync(configPath, "utf8"));
const patchObj = patch.content as any;

if (patch.format === "json-contextServers") {
existing.context_servers = {
...(existing.context_servers || {}),
...patchObj.context_servers,
};
} else {
existing.mcpServers = {
...(existing.mcpServers || {}),
...patchObj.mcpServers,
};
}

fs.writeFileSync(configPath, JSON.stringify(existing, null, 2));
console.log(`✅ Deep-merged Hyperstack config into ${configPath}`);
} catch (err) {
console.error(`❌ Failed to merge config: ${err}`);
}
}

export function selfHealDocker() {
try {
// Check if Docker is available
Expand Down
Loading