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
2 changes: 2 additions & 0 deletions core/config/profile/doLoadConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { getControlPlaneEnv } from "../../control-plane/env.js";
import { PolicySingleton } from "../../control-plane/PolicySingleton";
import { TeamAnalytics } from "../../control-plane/TeamAnalytics.js";
import ContinueProxy from "../../llm/llms/stubs/ContinueProxy";
import { guideSlashCommand } from "../../promptFiles/guidePrompt";
import { initSlashCommand } from "../../promptFiles/initPrompt";
import { getConfigDependentToolDefinitions } from "../../tools";
import { encodeMCPToolUri } from "../../tools/callTool";
Expand Down Expand Up @@ -189,6 +190,7 @@ export default async function doLoadConfig(options: {
}

newConfig.slashCommands.push(initSlashCommand);
newConfig.slashCommands.push(guideSlashCommand);
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot Apr 3, 2026

Choose a reason for hiding this comment

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

P2: Built-in /guide is appended without duplicate-name guarding, allowing silent collisions with user-defined /guide slash commands.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At core/config/profile/doLoadConfig.ts, line 193:

<comment>Built-in `/guide` is appended without duplicate-name guarding, allowing silent collisions with user-defined `/guide` slash commands.</comment>

<file context>
@@ -189,6 +190,7 @@ export default async function doLoadConfig(options: {
   }
 
   newConfig.slashCommands.push(initSlashCommand);
+  newConfig.slashCommands.push(guideSlashCommand);
 
   const proxyContextProvider = newConfig.contextProviders?.find(
</file context>
Suggested change
newConfig.slashCommands.push(guideSlashCommand);
if (!newConfig.slashCommands.some((cmd) => cmd.name === guideSlashCommand.name)) {
newConfig.slashCommands.push(guideSlashCommand);
}
Fix with Cubic


const proxyContextProvider = newConfig.contextProviders?.find(
(cp) => cp.description.title === "continue-proxy",
Expand Down
50 changes: 33 additions & 17 deletions core/config/profile/doLoadConfig.vitest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ vi.mock("../../control-plane/TeamAnalytics", () => ({
vi.mock("../../promptFiles/initPrompt", () => ({
initSlashCommand: { name: "init", description: "init" },
}));
vi.mock("../../promptFiles/guidePrompt", () => ({
guideSlashCommand: { name: "guide", description: "guide" },
}));

// Mock fs.existsSync to simulate missing file on disk
vi.mock("fs", async (importOriginal) => {
Expand Down Expand Up @@ -133,26 +136,29 @@ const mockControlPlaneClient = {

const mockLlmLogger = {} as any;

function createPackageIdentifier(withContent = true): PackageIdentifier {
return {
uriType: "file",
fileUri: "vscode-remote://wsl+Ubuntu/home/user/.continue/agents/test.yaml",
...(withContent
? { content: "name: Test\nversion: 1.0.0\nschema: v1\n" }
: {}),
};
}

describe("doLoadConfig pre-read content bypass", () => {
it("should use YAML loading when packageIdentifier has pre-read content, even if file does not exist on disk", async () => {
mockLoadYaml.mockClear();
mockLoadJson.mockClear();

const packageIdentifier: PackageIdentifier = {
uriType: "file",
fileUri:
"vscode-remote://wsl+Ubuntu/home/user/.continue/agents/test.yaml",
content: "name: Test\nversion: 1.0.0\nschema: v1\n",
};

await doLoadConfig({
ide: mockIde,
controlPlaneClient: mockControlPlaneClient,
llmLogger: mockLlmLogger,
profileId: "test-profile",
overrideConfigYamlByPath: packageIdentifier.fileUri,
overrideConfigYamlByPath: createPackageIdentifier(true).fileUri,
orgScopeId: null,
packageIdentifier,
packageIdentifier: createPackageIdentifier(true),
});

expect(mockLoadYaml).toHaveBeenCalled();
Expand All @@ -163,23 +169,33 @@ describe("doLoadConfig pre-read content bypass", () => {
mockLoadYaml.mockClear();
mockLoadJson.mockClear();

const packageIdentifier: PackageIdentifier = {
uriType: "file",
fileUri:
"vscode-remote://wsl+Ubuntu/home/user/.continue/agents/test.yaml",
};

await doLoadConfig({
ide: mockIde,
controlPlaneClient: mockControlPlaneClient,
llmLogger: mockLlmLogger,
profileId: "test-profile",
overrideConfigYamlByPath: packageIdentifier.fileUri,
overrideConfigYamlByPath: createPackageIdentifier(false).fileUri,
orgScopeId: null,
packageIdentifier,
packageIdentifier: createPackageIdentifier(false),
});

expect(mockLoadYaml).not.toHaveBeenCalled();
expect(mockLoadJson).toHaveBeenCalled();
});

it("should always include built-in init and guide slash commands", async () => {
const result = await doLoadConfig({
ide: mockIde,
controlPlaneClient: mockControlPlaneClient,
llmLogger: mockLlmLogger,
profileId: "test-profile",
overrideConfigYamlByPath: createPackageIdentifier(true).fileUri,
orgScopeId: null,
packageIdentifier: createPackageIdentifier(true),
});

const commandNames = result.config?.slashCommands.map((cmd) => cmd.name);
expect(commandNames).toContain("init");
expect(commandNames).toContain("guide");
});
});
52 changes: 52 additions & 0 deletions core/promptFiles/guidePrompt.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { SlashCommandWithSource } from "..";

export const GUIDE_PROMPT_CONTENT = `
You are Continue Guide Mode, an interactive mentor for developers who need help turning a rough idea into a concrete implementation plan.

Your job is not to jump straight into coding. First, help the user clarify what they are trying to build, then turn that into a strong implementation brief they can use with Continue.

## Goals
- Help beginners describe their project clearly.
- Ask discovery questions that improve the next coding step.
- Teach the user what information helps AI produce better results.
- End with a concrete, structured specification and a suggested next prompt.

## How to behave
- Be encouraging, practical, and concise.
- Ask only for information that materially improves the plan.
- Prefer plain language over jargon.
- If the user already answered some questions, do not ask them again.
- If the user gives a vague idea, ask targeted follow-up questions.
- Ask at most 2 questions per response so the interaction stays lightweight.

## Discovery Areas
Collect enough detail to cover these five areas:
1. What they want to build.
2. Who it is for.
3. What problem it solves.
4. Their experience level.
5. Requirements, constraints, or preferred technologies.

## Response strategy
- If key information is missing, ask the next most important question or two.
- Once you have enough information, stop asking questions and produce a structured specification.
- If the user asks for direct help before the discovery is complete, give a short answer and then continue the discovery flow.

## When you have enough information
Produce these sections in order:
1. **Project Summary**: one short paragraph.
2. **Structured Specification**: clear bullets for users, problem, features, constraints, and technical preferences.
3. **Implementation Plan**: 3-6 concrete build steps.
4. **Starter Prompt**: a polished prompt the user can paste into Continue to begin implementation.
5. **What To Clarify Next**: optional, only if meaningful gaps remain.

## If the user has not provided any project idea yet
Start by asking: "What are you trying to build? Describe your idea in your own words."
`.trim();

export const guideSlashCommand: SlashCommandWithSource = {
name: "guide",
description: "Turn a rough idea into a structured build plan",
source: "built-in",
prompt: GUIDE_PROMPT_CONTENT,
};
6 changes: 3 additions & 3 deletions docs/guides/cli.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ sidebarTitle: "Continue CLI (cn)"
description: "Learn how to use Continue's command-line interface for context engineering, automated coding tasks, and headless development workflows with customizable models, rules, and tools"
---

import { OSAutoDetect } from '/snippets/OSAutoDetect.jsx'
import CLIInstall from '/snippets/cli-install.mdx'
import { OSAutoDetect } from "/snippets/OSAutoDetect.jsx";
import CLIInstall from "/snippets/cli-install.mdx";

<OSAutoDetect />

Expand Down Expand Up @@ -39,7 +39,7 @@ Out of the box, `cn` comes with tools that let it understand your codebase, edit
- Write a new feature
- And a lot more

Use '@' to give it file context, or '/' to run slash commands.
Use '@' to give it file context, or '/' to run slash commands. For example, `/guide build a habit tracker for families` will help turn a rough idea into a clearer implementation brief before you start coding.

If you want to resume a previous conversation, run `cn --resume`.

Expand Down
23 changes: 19 additions & 4 deletions docs/reference/json-reference.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,25 @@ config.json
}
```

### `/guide`

The guide slash command helps a user turn a rough idea into a more actionable build plan. It asks discovery questions, clarifies the audience and constraints, and then produces a structured specification plus a starter prompt for implementation.

config.json

```json
{
"slashCommands": [
{
"name": "guide",
"description": "Turn a rough idea into a structured build plan"
}
]
}
```

Example: `/guide build a portfolio site for junior developers`

Example:

config.json
Expand Down Expand Up @@ -480,7 +499,6 @@ Several experimental config parameters are available, as described below:
- `defaultContext`: Defines the default context for the LLM. Uses the same format as `contextProviders` but includes an additional `query` property to specify custom query parameters.=

- `modelRoles`:

- `inlineEdit`: Model title for inline edits.
- `applyCodeBlock`: Model title for applying code blocks.
- `repoMapFileSelection`: Model title for repo map selections.
Expand Down Expand Up @@ -521,18 +539,15 @@ Some deprecated `config.json` settings are no longer stored in config and have b
- `disableSessionTitles`/`ui.getChatTitles`: This value will be migrated to the safest merged value (`true` if either are `true`). `getChatTitles` takes precedence if set to false

- `tabAutocompleteOptions`

- `useCache`: This value will override during migration.
- `disableInFiles`: This value will be migrated to the safest merged value (arrays of file matches merged/deduplicated)
- `multilineCompletions`: This value will override during migration.

- `experimental`

- `useChromiumForDocsCrawling`: This value will override during migration.
- `readResponseTTS`: This value will override during migration.

- `ui` - all will override during migration

- `codeBlockToolbarPosition`
- `fontSize`
- `codeWrap`
Expand Down
2 changes: 2 additions & 0 deletions extensions/cli/src/commands/commands.integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ describe("Slash Commands Integration", () => {
expect(commandNames).toContain("login");
expect(commandNames).toContain("logout");
expect(commandNames).toContain("whoami");
expect(commandNames).toContain("guide");

expect(commandNames).toContain("model");
expect(commandNames).toContain("config");
Expand All @@ -50,6 +51,7 @@ describe("Slash Commands Integration", () => {
"login",
"logout",
"whoami",
"guide",
"model",
"config",
].includes(cmd.name),
Expand Down
5 changes: 5 additions & 0 deletions extensions/cli/src/commands/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ export const SYSTEM_SLASH_COMMANDS: SystemCommand[] = [
description: "Create an AGENTS.md file",
category: "system",
},
{
name: "guide",
description: "Turn a rough idea into a structured build plan",
category: "system",
},
{
name: "compact",
description: "Summarize chat history into a compact form",
Expand Down
14 changes: 14 additions & 0 deletions extensions/cli/src/slashCommands.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,20 @@ describe("slashCommands", () => {
expect(result?.exit).toBeUndefined();
});

it("should handle /guide command", async () => {
const result = await handleSlashCommands(
"/guide Build a portfolio site for junior developers",
mockAssistant,
);

expect(result).toBeDefined();
expect(result?.newInput).toContain("Continue Guide Mode");
expect(result?.newInput).toContain(
"Build a portfolio site for junior developers",
);
expect(result?.output).toBeUndefined();
});

it("should handle /info command when not authenticated", async () => {
const { isAuthenticated } = await import("./auth/workos.js");
const { services } = await import("./services/index.js");
Expand Down
56 changes: 56 additions & 0 deletions extensions/cli/src/slashCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,50 @@ import {
loadMarkdownSkills,
} from "./util/loadMarkdownSkills.js";

const GUIDE_PROMPT = `
You are Continue Guide Mode, an interactive mentor for developers who need help turning a rough idea into a concrete implementation plan.

Your job is not to jump straight into coding. First, help the user clarify what they are trying to build, then turn that into a strong implementation brief they can use with Continue.

## Goals
- Help beginners describe their project clearly.
- Ask discovery questions that improve the next coding step.
- Teach the user what information helps AI produce better results.
- End with a concrete, structured specification and a suggested next prompt.

## How to behave
- Be encouraging, practical, and concise.
- Ask only for information that materially improves the plan.
- Prefer plain language over jargon.
- If the user already answered some questions, do not ask them again.
- If the user gives a vague idea, ask targeted follow-up questions.
- Ask at most 2 questions per response so the interaction stays lightweight.

## Discovery Areas
Collect enough detail to cover these five areas:
1. What they want to build.
2. Who it is for.
3. What problem it solves.
4. Their experience level.
5. Requirements, constraints, or preferred technologies.

## Response strategy
- If key information is missing, ask the next most important question or two.
- Once you have enough information, stop asking questions and produce a structured specification.
- If the user asks for direct help before the discovery is complete, give a short answer and then continue the discovery flow.

## When you have enough information
Produce these sections in order:
1. **Project Summary**: one short paragraph.
2. **Structured Specification**: clear bullets for users, problem, features, constraints, and technical preferences.
3. **Implementation Plan**: 3-6 concrete build steps.
4. **Starter Prompt**: a polished prompt the user can paste into Continue to begin implementation.
5. **What To Clarify Next**: optional, only if meaningful gaps remain.

## If the user has not provided any project idea yet
Start by asking: "What are you trying to build? Describe your idea in your own words."
`.trim();

type CommandHandler = (
args: string[],
assistant: AssistantConfig,
Expand Down Expand Up @@ -63,6 +107,17 @@ async function handleHelp(_args: string[], _assistant: AssistantConfig) {
return { output: helpMessage };
}

async function handleGuide(args: string[]): Promise<SlashCommandResult> {
const idea = args.join(" ").trim();
return {
newInput: idea
? `${GUIDE_PROMPT}

${idea}`
: GUIDE_PROMPT,
};
}

async function handleLogin() {
try {
const newAuthState = await services.auth.login();
Expand Down Expand Up @@ -361,6 +416,7 @@ const commandHandlers: Record<string, CommandHandler> = {
init: (args, assistant) => {
return handleInit(args, assistant);
},
guide: (args) => handleGuide(args),
update: () => {
return { openUpdateSelector: true };
},
Expand Down
Loading