Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
f68bb0d
feat: make commit signature configurable
rossigee Oct 8, 2025
06cf12e
Add disableCommitSignature to ContinueConfig interface
rossigee Oct 8, 2025
906e56e
Add disableCommitSignature to config-yaml schema and unroll logic
rossigee Oct 8, 2025
9db775b
Fix TypeScript compilation error for disableCommitSignature property
rossigee Oct 9, 2025
9f05bd1
Add support for disableCommitSignature config
rossigee Oct 9, 2025
cdc3bb5
chore: bump VSCode extension version to 1.3.16 (#8147)
tingwai Oct 8, 2025
e6837f6
feat: notion cookbook (#8074)
BekahHW Oct 9, 2025
0e8b01b
feat: asciinema recordings setup (#8154)
sestinj Oct 9, 2025
180c161
Update runloop-blueprint-template.json (#8156)
sestinj Oct 9, 2025
b5107cf
Add banner announcing Continue CLI v1.4.49
sestinj Oct 9, 2025
fe3c17f
remove onboarding result from being returned
uinstinct Oct 8, 2025
d436a87
run normal initialization flow on parallel
uinstinct Oct 8, 2025
296578a
remove rule injection during onboarding
uinstinct Oct 9, 2025
64da1d7
fix tests
uinstinct Oct 9, 2025
41a9451
fix: handle corrupted VSCode auth cache with automatic cleanup and re…
tingwai Oct 7, 2025
2e7acf1
move corrupted cache cleanup from SecretStorage to WorkOsAuthProvider
tingwai Oct 8, 2025
efffe55
feat: go back in history
tomasz-stefaniak Oct 7, 2025
597e0e4
improv: message history ux
tomasz-stefaniak Oct 7, 2025
865fc38
improv: architecture
tomasz-stefaniak Oct 7, 2025
b785642
fix: message input
tomasz-stefaniak Oct 7, 2025
cec00b8
test: message history edits
tomasz-stefaniak Oct 7, 2025
47a965e
improv: tests
tomasz-stefaniak Oct 7, 2025
703880c
improv: tests
tomasz-stefaniak Oct 7, 2025
de0d5bf
fix: linter errors
tomasz-stefaniak Oct 7, 2025
fc05a7a
fix: linter errors
tomasz-stefaniak Oct 7, 2025
402bdcc
fix: linter errors
tomasz-stefaniak Oct 7, 2025
b69b644
improv: clean up code
tomasz-stefaniak Oct 7, 2025
22559c8
fix: failing tests
tomasz-stefaniak Oct 7, 2025
42827ea
fix: lint
tomasz-stefaniak Oct 7, 2025
668cc8a
fix: lint
tomasz-stefaniak Oct 7, 2025
2eaf1bc
improv: clean up tests, fix paste block behavior
tomasz-stefaniak Oct 8, 2025
a2e15ee
fix: linter errors
tomasz-stefaniak Oct 8, 2025
21041a4
fix: text buffer handling
tomasz-stefaniak Oct 8, 2025
3b33ce9
fix: lint
tomasz-stefaniak Oct 8, 2025
141861d
chore: remove chat history from redux persistent storage
uinstinct Sep 24, 2025
4e8de48
remove unused variables in load session
uinstinct Sep 25, 2025
8c52e4f
add loading to last session
uinstinct Sep 25, 2025
49b1067
Revert "add loading to last session"
uinstinct Sep 26, 2025
198ebcd
load last session on first load
uinstinct Sep 26, 2025
5c4be8e
revert logger and storing sessionid
uinstinct Oct 6, 2025
5a44757
comment out lastSessionResult
uinstinct Oct 6, 2025
3eec4f1
try catch loadLastSession
uinstinct Oct 7, 2025
f05fe82
load last session after initial config load
uinstinct Oct 9, 2025
a958df0
chore: add github actions to CLA allowlist
tingwai Oct 8, 2025
6babdcf
remove unused variables in load session
uinstinct Sep 25, 2025
6f85e2f
add loading to last session
uinstinct Sep 25, 2025
a72b568
Revert "add loading to last session"
uinstinct Sep 26, 2025
71c9ae9
feat: make disableCommitSignature user-configurable via /set command
rossigee Oct 9, 2025
ffad489
Merge branch 'main' into feature/disable-commit-signature-config
rossigee Oct 9, 2025
a81e9cf
Merge commit 'a5257e2b5' into feature/disable-commit-signature-config
rossigee Oct 16, 2025
318e10d
Unnecessary whitespace change reverted.
rossigee Oct 16, 2025
80ca166
Merge branch 'main' into feature/disable-commit-signature-config
rossigee Oct 18, 2025
7c7fa42
Merge branch 'main' into feature/disable-commit-signature-config
rossigee Oct 19, 2025
7ebac41
Fix lint errors: reorder imports and remove unused variable
rossigee Oct 19, 2025
ba7219e
Merge branch 'main' of https://github.com/continuedev/continue into r…
RomneyDa Oct 27, 2025
3524c92
fix: eslint
RomneyDa Oct 27, 2025
8cd6cbb
Merge branch 'continuedev:main' into feature/disable-commit-signature…
rossigee Oct 28, 2025
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
1 change: 1 addition & 0 deletions core/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1787,6 +1787,7 @@ export interface ContinueConfig {
modelsByRole: Record<ModelRole, ILLM[]>;
selectedModelByRole: Record<ModelRole, ILLM | null>;
data?: DataDestination[];
disableCommitSignature?: boolean;
}

export interface BrowserSerializedContinueConfig {
Expand Down
1 change: 1 addition & 0 deletions core/util/GlobalContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export type GlobalContextType = {
[profileId: string]: GlobalContextModelSelections;
};
cliSelectedModel?: string; // CLI-specific model selection for unauthenticated users
disableCommitSignature?: boolean; // CLI-specific setting to disable commit attribution

/**
* This is needed to handle the case where a JetBrains user has created
Expand Down
26 changes: 26 additions & 0 deletions docs/cli/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,32 @@ Store secure credentials for CLI workflows:
- Share configurations across team members
- Version control for your AI workflows

## CLI Settings

Continue CLI stores certain user preferences locally to customize your experience:

### Commit Message Attribution

By default, Continue CLI includes an attribution signature in generated commit messages:

```
Generated with [Continue](https://continue.dev)

Co-Authored-By: Continue <noreply@continue.dev>
```

If you prefer not to include this attribution, you can disable it using the `/set` command:

```bash
/set disableCommitSignature true
```

This setting is stored locally and applies to all CLI usage on your system. To re-enable attribution:

```bash
/set disableCommitSignature false
```

## Common Use Cases

### TUI Mode Examples
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 @@ -95,6 +95,11 @@ export const SYSTEM_SLASH_COMMANDS: SystemCommand[] = [
description: "Set the title for the current session",
category: "system",
},
{
name: "set",
description: "Set CLI preferences",
category: "system",
},
{
name: "exit",
description: "Exit the chat",
Expand Down
72 changes: 72 additions & 0 deletions extensions/cli/src/slashCommands.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,14 @@ vi.mock("path", () => ({
join: vi.fn((...parts) => parts.join("/")),
}));

// Mock GlobalContext
const mockGlobalContextUpdate = vi.fn();
vi.mock("core/util/GlobalContext.js", () => ({
GlobalContext: class {
update = mockGlobalContextUpdate;
},
}));

// Mock session functions
vi.mock("./session.js", () => ({
getSessionFilePath: vi.fn(
Expand Down Expand Up @@ -429,5 +437,69 @@ describe("slashCommands", () => {
"Analyze the following code for patterns: my code",
);
});

it("should handle /set disableCommitSignature true", async () => {
mockGlobalContextUpdate.mockClear();

const result = await handleSlashCommands(
"/set disableCommitSignature true",
mockAssistant,
);

expect(result).toBeDefined();
expect(result?.output).toContain(
"Preference updated: disableCommitSignature = true",
);
expect(result?.exit).toBe(false);
expect(mockGlobalContextUpdate).toHaveBeenCalledWith(
"disableCommitSignature",
true,
);
});

it("should handle /set disableCommitSignature false", async () => {
mockGlobalContextUpdate.mockClear();

const result = await handleSlashCommands(
"/set disableCommitSignature false",
mockAssistant,
);

expect(result).toBeDefined();
expect(result?.output).toContain(
"Preference updated: disableCommitSignature = false",
);
expect(result?.exit).toBe(false);
expect(mockGlobalContextUpdate).toHaveBeenCalledWith(
"disableCommitSignature",
false,
);
});

it("should handle /set with unknown preference", async () => {
const result = await handleSlashCommands(
"/set unknownPreference value",
mockAssistant,
);

expect(result).toBeDefined();
expect(result?.output).toContain("Unknown preference: unknownPreference");
expect(result?.output).toContain("Available preferences:");
expect(result?.output).toContain("disableCommitSignature");
expect(result?.exit).toBe(false);
});

it("should handle /set with insufficient arguments", async () => {
const result = await handleSlashCommands(
"/set disableCommitSignature",
mockAssistant,
);

expect(result).toBeDefined();
expect(result?.output).toContain("Usage: /set <preference> <value>");
expect(result?.output).toContain("Available preferences:");
expect(result?.output).toContain("disableCommitSignature");
expect(result?.exit).toBe(false);
});
});
});
46 changes: 46 additions & 0 deletions extensions/cli/src/slashCommands.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { type AssistantConfig } from "@continuedev/sdk";
import chalk from "chalk";
import { GlobalContext } from "core/util/GlobalContext.js";

import {
isAuthenticated,
Expand Down Expand Up @@ -168,6 +169,50 @@ function handleTitle(args: string[]) {
}
}

function handleSet(args: string[]) {
posthogService.capture("useSlashCommand", { name: "set" });

if (args.length < 2) {
return {
exit: false,
output: chalk.yellow(
"Usage: /set <preference> <value>\n\nAvailable preferences:\n disableCommitSignature <true|false> - Control commit message attribution",
),
};
}

const [preference, value] = args;

try {
const globalContext = new GlobalContext();

switch (preference) {
case "disableCommitSignature": {
const booleanValue = value.toLowerCase() === "true";
globalContext.update("disableCommitSignature", booleanValue);
return {
exit: false,
output: chalk.green(
`Preference updated: ${preference} = ${booleanValue}`,
),
};
}
default:
return {
exit: false,
output: chalk.yellow(
`Unknown preference: ${preference}\n\nAvailable preferences:\n disableCommitSignature <true|false> - Control commit message attribution`,
),
};
}
} catch (error: any) {
return {
exit: false,
output: chalk.red(`Failed to update preference: ${error.message}`),
};
}
}

const commandHandlers: Record<string, CommandHandler> = {
help: handleHelp,
clear: () => {
Expand Down Expand Up @@ -195,6 +240,7 @@ const commandHandlers: Record<string, CommandHandler> = {
},
fork: handleFork,
title: handleTitle,
set: handleSet,
init: (args, assistant) => {
posthogService.capture("useSlashCommand", { name: "init" });
return handleInit(args, assistant);
Expand Down
51 changes: 50 additions & 1 deletion extensions/cli/src/systemMessage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,19 @@ const { constructSystemMessage } = await import("./systemMessage.js");
// Mock the service container to avoid "No factory registered for service 'config'" error
vi.mock("./services/ServiceContainer.js", () => ({
serviceContainer: {
get: vi.fn().mockResolvedValue({ config: { rules: [] } }),
get: vi.fn(),
set: vi.fn(),
},
}));

// Mock GlobalContext
const mockGlobalContextGet = vi.fn((key: string) => undefined);
vi.mock("core/util/GlobalContext.js", () => ({
GlobalContext: class {
get = mockGlobalContextGet as any;
},
}));

// Mock processRule to avoid file system operations in tests
vi.mock("./hubLoader.js", () => ({
processRule: vi
Expand All @@ -21,6 +29,16 @@ vi.mock("./hubLoader.js", () => ({

const PLAN_MODE_STRING = "You are operating in _Plan Mode_";

const { serviceContainer } = await import("./services/ServiceContainer.js");
const { GlobalContext } = await import("core/util/GlobalContext.js");

beforeEach(() => {
vi.clearAllMocks();
vi.mocked(serviceContainer.get).mockResolvedValue({ config: { rules: [] } });
// Reset GlobalContext mock
mockGlobalContextGet.mockReturnValue(undefined);
});

describe("constructSystemMessage", () => {
it("should return base system message with rules when additionalRules is provided", async () => {
const rules = ["These are the rules for the assistant."];
Expand Down Expand Up @@ -260,4 +278,35 @@ Rule 3: Third rule`;
"which means that your goal is to help the user investigate their ideas",
);
});

it("should include commit signature by default in normal mode", async () => {
const result = await constructSystemMessage("normal");

expect(result).toContain("Generated with [Continue]");
expect(result).toContain("Co-Authored-By: Continue");
});

it("should not include commit signature when disableCommitSignature is true", async () => {
mockGlobalContextGet.mockImplementation((key: string) => {
if (key === "disableCommitSignature") return true as any;
return undefined;
});

const result = await constructSystemMessage("normal");

expect(result).not.toContain("Generated with [Continue]");
expect(result).not.toContain("Co-Authored-By: Continue");
});

it("should include commit signature when disableCommitSignature is false", async () => {
mockGlobalContextGet.mockImplementation((key: string) => {
if (key === "disableCommitSignature") return false as any;
return undefined;
});

const result = await constructSystemMessage("normal");

expect(result).toContain("Generated with [Continue]");
expect(result).toContain("Co-Authored-By: Continue");
});
});
21 changes: 14 additions & 7 deletions extensions/cli/src/systemMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { execSync } from "child_process";
import * as fs from "fs";
import * as path from "path";

import { GlobalContext } from "core/util/GlobalContext.js";
import pkg from "ignore-walk";
import { Minimatch } from "minimatch";

Expand Down Expand Up @@ -98,21 +99,24 @@ ${getDirectoryStructure()}
${getGitStatus()}
</context>`;

async function getConfigYamlRules(): Promise<string[]> {
async function getConfigYamlRules(): Promise<{
rules: string[];
configState: ConfigServiceState;
}> {
const configState = await serviceContainer.get<ConfigServiceState>(
SERVICE_NAMES.CONFIG,
);
let rules: string[] = [];
if (configState.config?.rules) {
// Extract systemMessage from the config if it exists
const rules = configState.config.rules;
return rules
rules = configState.config.rules
.map((rule) => {
return typeof rule === "string" ? rule : rule?.rule;
})
.filter((rule): rule is string => !!rule);
}

return [];
return { rules, configState };
}

/**
Expand Down Expand Up @@ -162,7 +166,7 @@ export async function constructSystemMessage(
}
}

const configYamlRules = await getConfigYamlRules();
const { rules: configYamlRules } = await getConfigYamlRules();
processedRules.push(...configYamlRules);

// Construct the comprehensive system message
Expand All @@ -173,12 +177,15 @@ export async function constructSystemMessage(
systemMessage +=
'\n<context name="planMode">You are operating in _Plan Mode_, which means that your goal is to help the user investigate their ideas and develop a plan before taking action. You only have access to read-only tools and should not attempt to circumvent them to write / delete / create files. For example, it is not acceptable to use the Bash tool to write to files.</context>\n';
} else {
// TODO - make including this coauthor commit configurable
systemMessage += `\n<context name="commitSignature">When creating commits using any CLI or tool, include the following in the commit message:
const globalContext = new GlobalContext();
const disableSignature = globalContext.get("disableCommitSignature" as any);
if (!disableSignature) {
systemMessage += `\n<context name="commitSignature">When creating commits using any CLI or tool, include the following in the commit message:
Generated with [Continue](https://continue.dev)

Co-Authored-By: Continue <noreply@continue.dev>
</context>\n`;
}
}

// In headless mode, add instructions to be concise and only provide final answers
Expand Down
9 changes: 1 addition & 8 deletions gui/src/redux/thunks/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,14 +145,7 @@ export const loadRemoteSession = createAsyncThunk<
export const loadLastSession = createAsyncThunk<void, void, ThunkApiType>(
"session/loadLast",
async (_, { extra, dispatch, getState }) => {
let lastSessionId = getState().session.lastSessionId;

// const lastSessionResult = await extra.ideMessenger.request("history/list", {
// limit: 1,
// });
// if (lastSessionResult.status === "success") {
// lastSessionId = lastSessionResult.content.at(0)?.sessionId;
// }
const lastSessionId = getState().session.lastSessionId;

if (!lastSessionId) {
dispatch(newSession());
Expand Down
Loading
Loading