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
4 changes: 2 additions & 2 deletions install.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,9 @@ Pre-pulling is required. MCP servers have a short initialization timeout - if Do

Hyperstack enforces a **singleton container policy**. If a `hyperstack-mcp` container exists OR any container is running from the `hyperstack:main` image, it must be removed before starting a fresh one to ensure no stale state persists.

Run the provided singleton enforcement script:
Run the provided cross-platform singleton enforcement script (requires Bun):
```bash
bash scripts/ensure-singleton.sh
bun scripts/ensure-singleton.ts
```

Or run the hard check manually:
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"test": "bun test",
"start": "bun src/index.ts",
"dev": "bun --watch src/index.ts",
"docker:run": "bash scripts/ensure-singleton.sh"
"docker:run": "bun scripts/ensure-singleton.ts"
},
"author": "Orkait",
"license": "MIT",
Expand Down
34 changes: 0 additions & 34 deletions scripts/ensure-singleton.sh

This file was deleted.

44 changes: 44 additions & 0 deletions scripts/ensure-singleton.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { execSync } from "child_process";

const IMAGE = "ghcr.io/orkait/hyperstack:main";
const CONTAINER_NAME = "hyperstack-mcp";

function run() {
console.log("Checking for existing Hyperstack containers (cross-platform)...");

try {
// 1. Find containers by image and name
const byImage = execSync(`docker ps -aq --filter "ancestor=${IMAGE}"`).toString().trim().split(/\s+/).filter(Boolean);
const byName = execSync(`docker ps -aq --filter "name=${CONTAINER_NAME}"`).toString().trim().split(/\s+/).filter(Boolean);

// 2. Combine and uniq
const allStale = Array.from(new Set([...byImage, ...byName]));

if (allStale.length > 0) {
console.log(`Removing stale Hyperstack containers: ${allStale.join(", ")}`);
// We use a loop or join with space since 'docker rm -f' accepts multiple IDs
execSync(`docker rm -f ${allStale.join(" ")}`, { stdio: "inherit" });
} else {
console.log("No stale containers found.");
}

// 3. Start fresh container
console.log(`Starting fresh Hyperstack container: ${CONTAINER_NAME}`);
execSync(
`docker run -d --name ${CONTAINER_NAME} --restart unless-stopped \
--memory=512m --cpus=1 \
--entrypoint sleep \
${IMAGE} infinity`,
{ stdio: "inherit" }
);

console.log("\nVerification:");
execSync(`docker ps --filter name=${CONTAINER_NAME}`, { stdio: "inherit" });

} catch (error: any) {
console.error("Error ensuring singleton container:", error.message);
process.exit(1);
}
}

run();
Loading