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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Thumbs.db
pnpm-lock.yaml
records/**
.claude/**
.augment/**

# Documentation
CLAUDE.md
11 changes: 11 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,17 @@
},
"default": [],
"description": "Environment variables to set when launching Claude"
},
"claudix.initialPermissionMode": {
"type": "string",
"enum": [
"default",
"acceptEdits",
"plan",
"bypassPermissions"
],
"default": "default",
"description": "Default permission mode for new Claude sessions. WARNING: 'bypassPermissions' will allow Claude to run tools and apply edits without asking for confirmation."
}
}
},
Expand Down
4 changes: 1 addition & 3 deletions src/services/claude/ClaudeSdkService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ export class ClaudeSdkService implements IClaudeSdkService {
model: modelParam,
permissionMode: permissionModeParam,
maxThinkingTokens: maxThinkingTokens,
allowDangerouslySkipPermissions: true,

// CanUseTool 回调
canUseTool,
Expand Down Expand Up @@ -191,9 +192,6 @@ export class ClaudeSdkService implements IClaudeSdkService {
// CLI 可执行文件路径
pathToClaudeCodeExecutable: this.getClaudeExecutablePath(),

// 额外参数
extraArgs: {} as Record<string, string | null>,

// 设置源
// 'user': ~/.claude/settings.json (API 密钥)
// 'project': .claude/settings.json (项目设置, CLAUDE.md)
Expand Down
7 changes: 6 additions & 1 deletion src/services/claude/handlers/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ export async function handleInit(
// 获取 thinking level (默认值)
const thinkingLevel = 'default_on';

// 获取初始权限模式(默认 default)
const initialPermissionModeSetting = configService.getValue<string>('claudix.initialPermissionMode');
const initialPermissionMode: PermissionMode = (initialPermissionModeSetting as PermissionMode) || 'default';

return {
type: "init_response",
state: {
Expand All @@ -115,7 +119,8 @@ export async function handleInit(
// authStatus,
modelSetting,
platform: process.platform,
thinkingLevel
thinkingLevel,
initialPermissionMode
}
};
}
Expand Down
1 change: 1 addition & 0 deletions src/shared/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ export interface InitResponse {
modelSetting: string;
platform: string;
thinkingLevel?: string; // Thinking 等级(off | default_on)
initialPermissionMode?: PermissionMode;
};
}

Expand Down
16 changes: 16 additions & 0 deletions src/webview/src/components/ModeSelect.vue
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,18 @@
:index="2"
@click="(item) => handleModeSelect(item, close)"
/>
<DropdownItem
:item="{
id: 'bypassPermissions',
label: 'Bypass',
icon: 'codicon-warning text-[14px]!',
checked: permissionMode === 'bypassPermissions',
type: 'bypass-mode'
}"
:is-selected="permissionMode === 'bypassPermissions'"
:index="3"
@click="(item) => handleModeSelect(item, close)"
/>
</template>
</DropdownTrigger>
</template>
Expand Down Expand Up @@ -82,6 +94,8 @@ const selectedModeLabel = computed(() => {
return 'Agent'
case 'plan':
return 'Plan'
case 'bypassPermissions':
return 'Bypass'
case 'default':
return 'Default'
default:
Expand All @@ -96,6 +110,8 @@ const selectedModeIcon = computed(() => {
return 'codicon-infinity'
case 'plan':
return 'codicon-todos'
case 'bypassPermissions':
return 'codicon-warning'
case 'default':
return 'codicon-chat'
default:
Expand Down
11 changes: 11 additions & 0 deletions src/webview/src/core/Session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export class Session {
private currentConnectionPromise?: Promise<BaseTransport>;
private lastSentSelection?: SelectionRange;
private effectCleanup?: () => void;
private hasExplicitlySetPermissionMode = false;

readonly connection = signal<BaseTransport | undefined>(undefined);

Expand Down Expand Up @@ -263,6 +264,15 @@ export class Session {
this.thinkingLevel(connection.config()?.thinkingLevel || 'default_on');
}

const config = connection.config?.();
if (
config?.initialPermissionMode &&
this.permissionMode() === 'default' &&
!this.hasExplicitlySetPermissionMode
) {
this.permissionMode(config.initialPermissionMode);
}

const stream = connection.launchClaude(
channelId,
this.sessionId() ?? undefined,
Expand Down Expand Up @@ -298,6 +308,7 @@ export class Session {
}

async setPermissionMode(mode: PermissionMode, applyToConnection = true): Promise<boolean> {
this.hasExplicitlySetPermissionMode = true;
const previous = this.permissionMode();
this.permissionMode(mode);

Expand Down
2 changes: 1 addition & 1 deletion src/webview/src/pages/ChatPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@
const togglePermissionMode = () => {
const s = session.value;
if (!s) return;
const order: PermissionMode[] = ['default', 'acceptEdits', 'plan'];
const order: PermissionMode[] = ['default', 'acceptEdits', 'plan', 'bypassPermissions'];
const cur = (s.permissionMode.value as PermissionMode) ?? 'default';
const idx = Math.max(0, order.indexOf(cur));
const next = order[(idx + 1) % order.length];
Expand Down
1 change: 1 addition & 0 deletions src/webview/src/transport/BaseTransport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export abstract class BaseTransport {
modelSetting: initResponse.state.modelSetting,
platform: initResponse.state.platform,
thinkingLevel: initResponse.state.thinkingLevel,
initialPermissionMode: initResponse.state.initialPermissionMode,
} as InitResponse["state"]);

const claudeState = await this.sendRequest<GetClaudeStateResponse>({
Expand Down