Skip to content

Commit 6229e8f

Browse files
authored
feat(acp): can specify default mode (#2901)
1 parent 01d4fae commit 6229e8f

5 files changed

Lines changed: 112 additions & 0 deletions

File tree

doc/codecompanion.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,6 +1033,17 @@ Using a `function` is useful for working around the limitations
10331033
Code SDK (which enables ACP support).
10341034

10351035

1036+
DEFAULT MODE ~
1037+
1038+
You can configure an ACP adapter to start in a specific agent mode (e.g., plan
1039+
mode) by setting the `defaults.mode` option. This is useful if you want to
1040+
always start sessions in plan mode or another specific mode.
1041+
1042+
1043+
The mode is applied automatically after the session is established. Available
1044+
mode IDs can be viewed using the `/mode` slash command in the chat buffer.
1045+
1046+
10361047
ADAPTER SETTINGS ~
10371048

10381049
To change any of the default settings for an ACP adapter, you can extend it in

doc/configuration/adapters-acp.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,52 @@ require("codecompanion").setup({
7979

8080
Using a _function_ is useful for working around the [limitations](https://github.com/zed-industries/claude-code-acp/issues/225) in the Claude Code SDK (which enables ACP support).
8181

82+
## Configuring Default Mode
83+
84+
You can configure an ACP adapter to start in a specific agent mode (e.g., plan mode) by setting the `defaults.mode` option. This is useful if you want to always start sessions in plan mode or another specific mode.
85+
86+
::: code-group
87+
88+
```lua [Adapters: Text] {6-8}
89+
require("codecompanion").setup({
90+
adapters = {
91+
acp = {
92+
claude_code = function()
93+
return require("codecompanion.adapters").extend("claude_code", {
94+
defaults = {
95+
mode = "plan"
96+
},
97+
})
98+
end,
99+
}
100+
},
101+
}),
102+
```
103+
104+
```lua [Adapters: Function] {6-12}
105+
require("codecompanion").setup({
106+
adapters = {
107+
acp = {
108+
claude_code = function()
109+
return require("codecompanion.adapters").extend("claude_code", {
110+
defaults = {
111+
---@param self CodeCompanion.ACPAdapter
112+
---@return string
113+
mode = function(self)
114+
return "plan"
115+
end,
116+
},
117+
})
118+
end,
119+
}
120+
},
121+
}),
122+
```
123+
124+
:::
125+
126+
The mode is applied automatically after the session is established. Available mode IDs can be viewed using the `/mode` slash command in the chat buffer.
127+
82128
## Configuring Adapter Settings
83129

84130
To change any of the default settings for an ACP adapter, you can extend it in your CodeCompanion setup. For example, to change the timeout and authentication method for the Gemini CLI adapter, you can do the following:

lua/codecompanion/acp/init.lua

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ function Connection:connect_and_initialize()
151151
end
152152

153153
self:apply_default_model()
154+
self:apply_default_mode()
154155

155156
return self
156157
end
@@ -299,6 +300,53 @@ function Connection:apply_default_model()
299300
return self:set_model(model_id)
300301
end
301302

303+
---Apply the default mode from the adapter config
304+
---@return boolean
305+
function Connection:apply_default_mode()
306+
if not self._modes then
307+
return false
308+
end
309+
310+
local default_mode = self.adapter_modified and self.adapter_modified.defaults and self.adapter_modified.defaults.mode
311+
if not default_mode then
312+
return false
313+
end
314+
315+
-- Support function values for default mode
316+
if type(default_mode) == "function" then
317+
default_mode = default_mode(self.adapter_modified)
318+
end
319+
320+
if type(default_mode) ~= "string" or default_mode == "" then
321+
return false
322+
end
323+
324+
-- Check if the requested mode is available
325+
local mode_id = nil
326+
for _, mode in ipairs(self._modes.availableModes or {}) do
327+
-- Match by id first, then by partial name match (e.g., "plan" matches mode with name containing "plan")
328+
if mode.id == default_mode then
329+
mode_id = mode.id
330+
break
331+
elseif mode.name and mode.name:lower():find(default_mode:lower(), 1, true) then
332+
mode_id = mode.id
333+
break
334+
end
335+
end
336+
337+
if not mode_id then
338+
log:warn("[acp::apply_default_mode] Mode `%s` not found in available modes", default_mode)
339+
return false
340+
end
341+
342+
if mode_id == self._modes.currentModeId then
343+
log:debug("[acp::apply_default_mode] Mode `%s` is already selected", mode_id)
344+
return true
345+
end
346+
347+
return self:set_mode(mode_id)
348+
end
349+
302350
---Create the ACP process
303351
---@return boolean success
304352
function Connection:start_agent_process()

lua/codecompanion/adapters/acp/claude_code.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ return {
2424
defaults = {
2525
mcpServers = {},
2626
timeout = 20000, -- 20 seconds
27+
-- mode = "plan", -- Optional: Set default agent mode (e.g., "plan")
2728
},
2829
env = {
2930
CLAUDE_CODE_OAUTH_TOKEN = "CLAUDE_CODE_OAUTH_TOKEN",

lua/codecompanion/adapters/acp/init.lua

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,12 @@ function Adapter.resolve(adapter, opts)
9595
})
9696
end
9797

98+
if opts.mode then
99+
adapter = vim.tbl_deep_extend("force", vim.deepcopy(adapter), {
100+
defaults = { mode = opts.mode },
101+
})
102+
end
103+
98104
adapter = Adapter.new(adapter)
99105
elseif type(adapter) == "string" then
100106
if not config.adapters.acp or not config.adapters.acp[adapter] then

0 commit comments

Comments
 (0)