From bfb3fbb466f3694e7c19259691382374cd47cef5 Mon Sep 17 00:00:00 2001 From: Greg Jackson Date: Sat, 1 Aug 2026 19:03:52 +0100 Subject: [PATCH] fix(setup): accept --host cursor and --host slate (#2361) Fixes #2361. Co-Authored-By: Claude Opus 4.6 --- setup | 6 ++-- test/setup-host-validation.test.ts | 45 ++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 test/setup-host-validation.test.ts diff --git a/setup b/setup index 275236cd36..da06384e0f 100755 --- a/setup +++ b/setup @@ -85,7 +85,7 @@ NO_TEAM_MODE=0 PLAN_TUNE_HOOKS_MODE="" # "" = resolve from env/config/prompt; "yes"/"no" = explicit while [ $# -gt 0 ]; do case "$1" in - --host) [ -z "$2" ] && echo "Missing value for --host (expected claude, codex, kiro, factory, opencode, openclaw, hermes, gbrain, or auto)" >&2 && exit 1; HOST="$2"; shift 2 ;; + --host) [ -z "$2" ] && echo "Missing value for --host (expected claude, codex, kiro, factory, opencode, cursor, slate, openclaw, hermes, gbrain, or auto)" >&2 && exit 1; HOST="$2"; shift 2 ;; --host=*) HOST="${1#--host=}"; shift ;; --local) LOCAL_INSTALL=1; shift ;; --prefix) SKILL_PREFIX=1; SKILL_PREFIX_FLAG=1; shift ;; @@ -101,7 +101,7 @@ while [ $# -gt 0 ]; do done case "$HOST" in - claude|codex|kiro|factory|opencode|auto) ;; + claude|codex|kiro|factory|opencode|cursor|slate|auto) ;; openclaw) echo "" echo "OpenClaw integration uses a different model — OpenClaw spawns Claude Code" @@ -136,7 +136,7 @@ case "$HOST" in echo "GBrain setup and brain skills ship from the GBrain repo." echo "" exit 0 ;; - *) echo "Unknown --host value: $HOST (expected claude, codex, kiro, factory, opencode, openclaw, hermes, gbrain, or auto)" >&2; exit 1 ;; + *) echo "Unknown --host value: $HOST (expected claude, codex, kiro, factory, opencode, cursor, slate, openclaw, hermes, gbrain, or auto)" >&2; exit 1 ;; esac # ─── Resolve skill prefix preference ───────────────────────── diff --git a/test/setup-host-validation.test.ts b/test/setup-host-validation.test.ts new file mode 100644 index 0000000000..4e7c0a1fa3 --- /dev/null +++ b/test/setup-host-validation.test.ts @@ -0,0 +1,45 @@ +import { describe, test, expect } from 'bun:test'; +import { spawnSync } from 'child_process'; +import * as path from 'path'; +import * as os from 'os'; +import * as fs from 'fs'; + +const ROOT = path.resolve(import.meta.dir, '..'); +const SETUP_SCRIPT = path.join(ROOT, 'setup'); + +function runSetupHost(host: string): { stderr: string; status: number | null; timedOut: boolean } { + const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gstack-setup-host-')); + const r = spawnSync('bash', [SETUP_SCRIPT, '--host', host], { + cwd: ROOT, + encoding: 'utf-8', + input: '', + timeout: 3000, + env: { ...process.env, HOME: tmpDir }, + }); + fs.rmSync(tmpDir, { recursive: true, force: true }); + return { + stderr: r.stderr || '', + status: r.status, + timedOut: r.signal === 'SIGTERM', + }; +} + +describe('setup: --host validation accepts all registered hosts', () => { + test('--host cursor is accepted (not rejected as unknown)', () => { + const r = runSetupHost('cursor'); + expect(r.stderr).not.toContain('Unknown --host value'); + expect(r.status).not.toBe(1); + }); + + test('--host slate is accepted (not rejected as unknown)', () => { + const r = runSetupHost('slate'); + expect(r.stderr).not.toContain('Unknown --host value'); + expect(r.status).not.toBe(1); + }); + + test('--host nonexistent is still rejected', () => { + const r = runSetupHost('nonexistent'); + expect(r.stderr).toContain('Unknown --host value'); + expect(r.status).toBe(1); + }); +});