Skip to content
Open
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
35 changes: 3 additions & 32 deletions packages/squad-cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,6 @@
"types": "./dist/cli/copilot-install.d.ts",
"import": "./dist/cli/copilot-install.js"
},
"./shell/sessions": {
"types": "./dist/cli/shell/sessions.d.ts",
"import": "./dist/cli/shell/sessions.js"
},
"./shell/spawn": {
"types": "./dist/cli/shell/spawn.d.ts",
"import": "./dist/cli/shell/spawn.js"
},
"./shell/coordinator": {
"types": "./dist/cli/shell/coordinator.d.ts",
"import": "./dist/cli/shell/coordinator.js"
Expand Down Expand Up @@ -124,18 +116,6 @@
"types": "./dist/cli/commands/watch/index.d.ts",
"import": "./dist/cli/commands/watch/index.js"
},
"./commands/start": {
"types": "./dist/cli/commands/start.d.ts",
"import": "./dist/cli/commands/start.js"
},
"./commands/rc-tunnel": {
"types": "./dist/cli/commands/rc-tunnel.d.ts",
"import": "./dist/cli/commands/rc-tunnel.js"
},
"./commands/rc": {
"types": "./dist/cli/commands/rc.d.ts",
"import": "./dist/cli/commands/rc.js"
},
"./commands/extract": {
"types": "./dist/cli/commands/extract.d.ts",
"import": "./dist/cli/commands/extract.js"
Expand All @@ -148,10 +128,6 @@
"types": "./dist/cli/commands/cost.d.ts",
"import": "./dist/cli/commands/cost.js"
},
"./commands/copilot-bridge": {
"types": "./dist/cli/commands/copilot-bridge.d.ts",
"import": "./dist/cli/commands/copilot-bridge.js"
},
"./commands/personal": {
"types": "./dist/cli/commands/personal.d.ts",
"import": "./dist/cli/commands/personal.js"
Expand All @@ -168,26 +144,21 @@
"README.md"
],
"scripts": {
"postinstall": "node scripts/patch-esm-imports.mjs && node scripts/patch-ink-rendering.mjs",
"postinstall": "node scripts/patch-esm-imports.mjs",
"prepublishOnly": "npm run build",
"build": "tsc -p tsconfig.json && npm run postbuild",
"postbuild": "node -e \"require('fs').cpSync('src/remote-ui', 'dist/remote-ui', {recursive: true})\""
"build": "tsc -p tsconfig.json"
},
"engines": {
"node": ">=22.5.0"
},
"dependencies": {
"@bradygaster/squad-sdk": ">=0.9.0",
"ink": "^6.8.0",
"react": "^19.2.4",
"vscode-jsonrpc": "^8.2.1"
},
"devDependencies": {
"@types/node": "^22.0.0",
"@types/react": "^19.2.14",
"esbuild": "^0.25.0",
"typescript": "^5.7.0",
"ink-testing-library": "^4.0.0"
"typescript": "^5.7.0"
},
"keywords": [
"copilot",
Expand Down
115 changes: 0 additions & 115 deletions packages/squad-cli/scripts/patch-ink-rendering.mjs

This file was deleted.

80 changes: 15 additions & 65 deletions packages/squad-cli/src/cli-entry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ Module._resolveFilename = function (request: string, parent: unknown, isMain: bo

// ---------------------------------------------------------------------------
// Top-level signal handlers — safety net for clean exit on Ctrl+C / SIGTERM.
// Individual commands (shell, watch, aspire, rc) register their own handlers
// Individual commands (watch, aspire) register their own handlers
// that run first; these ensure the process never hangs if a command doesn't.
// ---------------------------------------------------------------------------
let _exitingOnSignal = false;
Expand Down Expand Up @@ -101,7 +101,7 @@ import { getPackageVersion } from './cli/core/version.js';
// Lazy-load squad-sdk to avoid triggering @github/copilot-sdk import on Node 24+
// (Issue: copilot-sdk has broken ESM imports - vscode-jsonrpc/node without .js extension)
const lazySquadSdk = () => import('@bradygaster/squad-sdk');
const lazyRunShell = () => import('./cli/shell/index.js');


// Use local version resolver instead of importing VERSION from squad-sdk
const VERSION = getPackageVersion();
Expand Down Expand Up @@ -137,8 +137,7 @@ async function main(): Promise<void> {
console.log(`\n${BOLD}squad${RESET} v${VERSION} — Add an AI agent team to any project\n`);
console.log(`Usage: squad [command] [options]\n`);
console.log(`Commands:`);
console.log(` ${BOLD}(default)${RESET} Launch interactive shell (no args)`);
console.log(` Flags: --global (init in personal squad directory)`);

console.log(` ${BOLD}init${RESET} Initialize Squad (markdown-only, default)`);
console.log(` Flags: --sdk (SDK builder syntax)`);
console.log(` --roles (use base roles)`);
Expand Down Expand Up @@ -192,12 +191,6 @@ async function main(): Promise<void> {
console.log(` Usage: import <file> [--force]`);
console.log(` ${BOLD}scrub-emails${RESET} Remove email addresses from Squad state files`);
console.log(` Usage: scrub-emails [directory] (default: .ai-team/)`);
console.log(` ${BOLD}start${RESET} Start Copilot with remote access from phone/browser`);
console.log(` Usage: start [--tunnel] [--port <n>] [--command <cmd>]`);
console.log(` [copilot flags...]`);
console.log(` Examples: start --tunnel --yolo`);
console.log(` start --tunnel --model claude-sonnet-4`);
console.log(` start --tunnel --command "gh copilot"`);
console.log(` ${BOLD}nap${RESET} Context hygiene (compress, prune, archive .squad/ state)`);
console.log(` Usage: nap [--deep] [--dry-run]`);
console.log(` Flags: --deep (thorough cleanup), --dry-run (preview only)`);
Expand All @@ -222,12 +215,8 @@ async function main(): Promise<void> {
console.log(` Usage: personal init | list | add <name>`);
console.log(` --role <role> | remove <name>`);
console.log(` ${BOLD}cast${RESET} Show current session cast (project + personal agents)`);
console.log(` ${BOLD}rc${RESET} Start Remote Control bridge (phone/browser → Copilot)`);
console.log(` Usage: rc [--tunnel] [--port <n>] [--path <dir>]`);
console.log(` ${BOLD}copilot-bridge${RESET} Check Copilot ACP stdio compatibility`);
console.log(` ${BOLD}init-remote${RESET} Link project to remote team root (shorthand)`);
console.log(` Usage: init-remote <team-repo-path>`);
console.log(` ${BOLD}rc-tunnel${RESET} Check devtunnel CLI availability`);
console.log(` ${BOLD}discover${RESET} List known squads and their capabilities`);
console.log(` ${BOLD}delegate${RESET} Create work in another squad`);
console.log(` Usage: delegate <squad-name> <description>`);
Expand All @@ -254,12 +243,19 @@ async function main(): Promise<void> {
return;
}

// No args → launch interactive shell; whitespace-only arg → show help
// No args → show deprecation notice for removed interactive REPL
if (rawCmd === undefined) {
// Fire-and-forget update check — non-blocking, never delays shell startup
import('./cli/self-update.js').then(m => m.notifyIfUpdateAvailable(VERSION)).catch(() => {});
const { runShell } = await lazyRunShell();
await runShell();
console.log(`\n${YELLOW}${BOLD}⚠ The interactive REPL has been deprecated and removed.${RESET}\n`);
console.log(`${DIM}The built-in interactive shell had persistent rendering issues (scrollback`);
console.log(`corruption, Ink viewport collisions, terminal incompatibility) and has been`);
console.log(`removed in favour of a better experience.${RESET}\n`);
console.log(`${BOLD}Recommended replacement: GitHub Copilot CLI${RESET}`);
console.log(` Install: ${BOLD}gh extension install github/gh-copilot${RESET}`);
console.log(` Then run ${BOLD}gh copilot suggest${RESET} or ${BOLD}gh copilot explain${RESET} from your repo root.\n`);
console.log(`${DIM}Tip: running from a repo root that contains squad.agent.md means Copilot`);
console.log(`picks up your Squad context automatically.${RESET}\n`);
console.log(`${DIM}More info: https://github.com/bradygaster/squad/issues/665${RESET}\n`);
process.exitCode = 0;
return;
}
Comment on lines +246 to 260
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR changes the CLI’s default behavior substantially (no-args now prints a deprecation notice and exits). There should be a focused test that asserts (1) exit code is 0 and (2) output contains the key guidance (Copilot CLI install command + link to #665). This helps prevent regressions where squad accidentally becomes a no-op or exits non-zero.

Copilot uses AI. Check for mistakes.
if (!cmd) {
Expand Down Expand Up @@ -544,20 +540,6 @@ async function main(): Promise<void> {
return;
}

if (cmd === 'start') {
const { runStart } = await import('./cli/commands/start.js');
const hasTunnel = args.includes('--tunnel');
const portIdx = args.indexOf('--port');
const port = (portIdx !== -1 && args[portIdx + 1]) ? parseInt(args[portIdx + 1]!, 10) : 0;
// Collect all remaining args to pass through to copilot
const cmdIdx = args.indexOf('--command');
const customCmd = (cmdIdx !== -1 && args[cmdIdx + 1]) ? args[cmdIdx + 1] : undefined;
const squadFlags = ['start', '--tunnel', '--port', port.toString(), '--command', customCmd || ''].filter(Boolean);
const copilotArgs = args.slice(1).filter(a => !squadFlags.includes(a));
await runStart(process.cwd(), { tunnel: hasTunnel, port, copilotArgs, command: customCmd });
return;
}

if (cmd === 'nap') {
const { runNap, formatNapReport } = await import('./cli/core/nap.js');
const sdk = await lazySquadSdk();
Expand Down Expand Up @@ -610,28 +592,6 @@ async function main(): Promise<void> {
return;
}

if (cmd === 'rc' || cmd === 'remote-control') {
const { runRC } = await import('./cli/commands/rc.js');
const hasTunnel = args.includes('--tunnel');
const portIdx = args.indexOf('--port');
const port = (portIdx !== -1 && args[portIdx + 1]) ? parseInt(args[portIdx + 1]!, 10) : 0;
const pathIdx = args.indexOf('--path');
const rcPath = (pathIdx !== -1 && args[pathIdx + 1]) ? args[pathIdx + 1] : undefined;
await runRC(rcPath || process.cwd(), { tunnel: hasTunnel, port });
return;
}

if (cmd === 'copilot-bridge') {
const { CopilotBridge } = await import('./cli/commands/copilot-bridge.js');
const result = await CopilotBridge.checkCompatibility();
if (result.compatible) {
console.log(`${GREEN}✓${RESET} ${result.message}`);
} else {
console.log(`${YELLOW}⚠${RESET} ${result.message}`);
}
return;
}

if (cmd === 'init-remote') {
const { writeRemoteConfig } = await import('./cli/commands/init-remote.js');
const teamPath = args[1];
Expand All @@ -644,16 +604,6 @@ async function main(): Promise<void> {
return;
}

if (cmd === 'rc-tunnel') {
const { isDevtunnelAvailable } = await import('./cli/commands/rc-tunnel.js');
if (isDevtunnelAvailable()) {
console.log(`${GREEN}✓${RESET} devtunnel CLI is available`);
} else {
console.log(`${YELLOW}⚠${RESET} devtunnel CLI not found. Install with: winget install Microsoft.devtunnel`);
}
return;
}

if (cmd === 'schedule') {
const { runSchedule } = await import('./cli/commands/schedule.js');
const subcommand = args[1] || 'list';
Expand Down
Loading
Loading