Add --no-extensions flag to disable extension discovery

Similar to --no-skills, this flag disables extension discovery and loading.
Useful for debugging or when extensions are causing issues.
This commit is contained in:
Carlos Villela 2026-01-06 23:53:01 -08:00
parent fcb3b4aa72
commit 48f524c554
No known key found for this signature in database
4 changed files with 37 additions and 7 deletions

View file

@ -2,6 +2,10 @@
## [Unreleased] ## [Unreleased]
### Added
- `--no-extensions` flag to disable extension discovery and loading
## [0.37.8] - 2026-01-07 ## [0.37.8] - 2026-01-07
## [0.37.7] - 2026-01-07 ## [0.37.7] - 2026-01-07

View file

@ -27,6 +27,7 @@ export interface Args {
models?: string[]; models?: string[];
tools?: ToolName[]; tools?: ToolName[];
extensions?: string[]; extensions?: string[];
noExtensions?: boolean;
print?: boolean; print?: boolean;
export?: string; export?: string;
noSkills?: boolean; noSkills?: boolean;
@ -116,6 +117,8 @@ export function parseArgs(args: string[], extensionFlags?: Map<string, { type: "
} else if ((arg === "--extension" || arg === "-e") && i + 1 < args.length) { } else if ((arg === "--extension" || arg === "-e") && i + 1 < args.length) {
result.extensions = result.extensions ?? []; result.extensions = result.extensions ?? [];
result.extensions.push(args[++i]); result.extensions.push(args[++i]);
} else if (arg === "--no-extensions") {
result.noExtensions = true;
} else if (arg === "--no-skills") { } else if (arg === "--no-skills") {
result.noSkills = true; result.noSkills = true;
} else if (arg === "--skills" && i + 1 < args.length) { } else if (arg === "--skills" && i + 1 < args.length) {
@ -175,6 +178,7 @@ ${chalk.bold("Options:")}
Available: read, bash, edit, write, grep, find, ls Available: read, bash, edit, write, grep, find, ls
--thinking <level> Set thinking level: off, minimal, low, medium, high, xhigh --thinking <level> Set thinking level: off, minimal, low, medium, high, xhigh
--extension, -e <path> Load an extension file (can be used multiple times) --extension, -e <path> Load an extension file (can be used multiple times)
--no-extensions Disable extensions discovery and loading
--no-skills Disable skills discovery and loading --no-skills Disable skills discovery and loading
--skills <patterns> Comma-separated glob patterns to filter skills (e.g., git-*,docker) --skills <patterns> Comma-separated glob patterns to filter skills (e.g., git-*,docker)
--export <file> Export session file to HTML and exit --export <file> Export session file to HTML and exit

View file

@ -294,8 +294,11 @@ function buildSessionOptions(
options.skills = []; options.skills = [];
} }
// Extensions
if (parsed.noExtensions) {
options.extensions = [];
} else if (preloadedExtensions && preloadedExtensions.length > 0) {
// Pre-loaded extensions (from early CLI flag discovery) // Pre-loaded extensions (from early CLI flag discovery)
if (preloadedExtensions && preloadedExtensions.length > 0) {
options.preloadedExtensions = preloadedExtensions; options.preloadedExtensions = preloadedExtensions;
} }
@ -317,16 +320,21 @@ export async function main(args: string[]) {
const firstPass = parseArgs(args); const firstPass = parseArgs(args);
time("parseArgs-firstPass"); time("parseArgs-firstPass");
// Early load extensions to discover their CLI flags // Early load extensions to discover their CLI flags (unless --no-extensions)
const cwd = process.cwd(); const cwd = process.cwd();
const agentDir = getAgentDir(); const agentDir = getAgentDir();
const eventBus = createEventBus(); const eventBus = createEventBus();
const settingsManager = SettingsManager.create(cwd); const settingsManager = SettingsManager.create(cwd);
time("SettingsManager.create"); time("SettingsManager.create");
let loadedExtensions: LoadedExtension[] = [];
if (!firstPass.noExtensions) {
// Merge CLI --extension args with settings.json extensions // Merge CLI --extension args with settings.json extensions
const extensionPaths = [...settingsManager.getExtensionPaths(), ...(firstPass.extensions ?? [])]; const extensionPaths = [...settingsManager.getExtensionPaths(), ...(firstPass.extensions ?? [])];
const { extensions: loadedExtensions } = await discoverAndLoadExtensions(extensionPaths, cwd, agentDir, eventBus); const result = await discoverAndLoadExtensions(extensionPaths, cwd, agentDir, eventBus);
loadedExtensions = result.extensions;
time("discoverExtensionFlags"); time("discoverExtensionFlags");
}
// Collect all extension flags // Collect all extension flags
const extensionFlags = new Map<string, { type: "boolean" | "string" }>(); const extensionFlags = new Map<string, { type: "boolean" | "string" }>();

View file

@ -150,6 +150,20 @@ describe("parseArgs", () => {
}); });
}); });
describe("--no-extensions flag", () => {
test("parses --no-extensions flag", () => {
const result = parseArgs(["--no-extensions"]);
expect(result.noExtensions).toBe(true);
});
});
describe("--no-skills flag", () => {
test("parses --no-skills flag", () => {
const result = parseArgs(["--no-skills"]);
expect(result.noSkills).toBe(true);
});
});
describe("messages and file args", () => { describe("messages and file args", () => {
test("parses plain text messages", () => { test("parses plain text messages", () => {
const result = parseArgs(["hello", "world"]); const result = parseArgs(["hello", "world"]);