feat: migrate Claude Code to Theia native slash commands and modes#16541
feat: migrate Claude Code to Theia native slash commands and modes#16541
Conversation
There was a problem hiding this comment.
The change works for me. Great work 👍
I left some comments about the code. All of them are nitpicks and can be ignored, handled later or be applied to this PR.
I performed all suggested tests. Generally speaking they succeeded for me, but there are some rough edges:
Changing modes
The Claude Code modes work, however changing the mode while a request is in process does not work. Even if the request is stopped because Claude Code asks for an approval, the new mode will not be respected by Claude Code until there is an actual new request from the user.
As we start in "Ask before edit" mode, the user will typically encounter an approval message pretty quick. Then they change the mode and click approve, still all further changes need to be manually improved
ExitPlanTool
Claude Code has an ExitPlanTool it tries to use to exit plan mode (after approval from the user). This fails and the user has to change the mode manually afterwards to continue
"Ask before edit" does not populate the change set
The "Ask before edit" asks for edit approval before doing any edits. However the approved edits do not show up in the changeset. Therefore there is no convenient way of directly seeing the edits of what Claude Code did compared to the "Edit automatically" mode
Custom commands request rendering
This "regression" is not caused by this PR. However it seems very weird to me that the Claude Code commands are rendered as #prompt in the request, e.g.
Mode preference?
Personally I don't like that I need to change the mode for Claude Code in every new chat session. There should be some way to avoid this, for example via a preference.
None of these are deal breakers, so we can merge as is. However please capture these remarks as follow ups in case you don't tackle them here.
| const modeId = request.request.modeId ?? 'default'; | ||
| switch (modeId) { | ||
| case 'acceptEdits': | ||
| return 'acceptEdits'; | ||
| case 'plan': | ||
| return 'plan'; | ||
| case 'bypassPermissions': | ||
| return 'bypassPermissions'; | ||
| case 'default': | ||
| default: | ||
| return 'default'; | ||
| } |
There was a problem hiding this comment.
This looks a bit clunky... should we instead have an array of allowed modes and check whether the request.modeId is contained in them?
| commandAgents: [CLAUDE_CHAT_AGENT_ID] | ||
| }); | ||
| } catch (error) { | ||
| console.error(`Failed to register dynamic command ${commandName}:`, error); |
There was a problem hiding this comment.
We should mention claude code in this error message so it's easier to understand for readers what is going on. Bonus points for using a named logger instead.
|
|
||
| protected getWorkspaceRoot(): URI | undefined { | ||
| const roots = this.workspaceService.tryGetRoots(); | ||
| return roots.length > 0 ? roots[0].resource : undefined; |
There was a problem hiding this comment.
We should create a follow up to properly support multi root workspaces
| case 'bypassPermissions': | ||
| return 'bypassPermissions'; |
There was a problem hiding this comment.
The bypassPermissions is currently not on any code path, correct?
- Replace custom Monaco completion provider with PromptService-based commands - Add support for dynamic .claude/commands/*.md files with live file watching - Implement workspace-aware file monitoring - Add mode support in Claude Code chat agent
b554327 to
e3496d1
Compare
What it does
This PR migrates Claude Code to use Theia's native slash command and mode infrastructure, replacing custom Monaco-based completion providers with platform-standard implementations.
Native Slash Command Support: Migrates from a custom Monaco completion provider to Theia's
PromptServicefor registering slash commands.claude/commands/*.mdfiles with live file watchingDynamic Command Management: Implements file system watching for
.claude/commands/directory.mdfiles are addedMode Support: Adds three operational modes to the Claude Code chat agent
ChatAgent.modesinterfaceHow to test
Testing Slash Commands:
Open the chat view
Type
@ClaudeCode /and verify all static commands appear (clear, compact, config, init, memory, review, resume)Create a
.claude/commands/directory in your workspaceAdd a markdown file (e.g.,
test.md) with command descriptionVerify the command appears in the slash command list without restarting
Modify the file name and verify the command updates
Delete the file and verify the command is removed
Switch to a different workspace and verify commands update accordingly
Type
@ClaudeCode /and verify all static commands work (clear, compact, config, init, resume, ...)Try if custom commands work
Testing Modes:
@ClaudeCodeFollow-ups
Breaking changes
Attribution
Review checklist
Reminder for reviewers