From 2020a84ba9b2d4d8d45a7b32610e3cd5b73eab8e Mon Sep 17 00:00:00 2001 From: James Feng <47167674+GhostDragon124@users.noreply.github.com> Date: Sat, 6 Jun 2026 21:05:00 +0800 Subject: [PATCH] feat: port mode system with 6 AI personality presets from CCB upstream (9947ae75) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - /mode command to switch between 6 interaction modes - Default (⚡), Gentle (🌸), Dr. Sharp (🔍), Workhorse (🐴), Token Saver (💰), Super AI (🧠) - Each mode: distinct system prompt, UI theme, permission defaults, response verbosity - Custom modes via YAML in ~/.claude/modes/ - Source: upstream 9947ae75 (YYMa, PR #1255) --- src/commands.ts | 2 + src/commands/mode/index.ts | 13 +++ src/commands/mode/mode.tsx | 79 ++++++++++++++++ src/modes/defaults.ts | 181 +++++++++++++++++++++++++++++++++++++ src/modes/store.ts | 133 +++++++++++++++++++++++++++ src/modes/types.ts | 21 +++++ 6 files changed, 429 insertions(+) create mode 100644 src/commands/mode/index.ts create mode 100644 src/commands/mode/mode.tsx create mode 100644 src/modes/defaults.ts create mode 100644 src/modes/store.ts create mode 100644 src/modes/types.ts diff --git a/src/commands.ts b/src/commands.ts index 7ed75e7f3..a177356e2 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -20,6 +20,7 @@ import diff from './commands/diff/index.js' import ctx_viz from './commands/ctx_viz/index.js' import doctor from './commands/doctor/index.js' import memory from './commands/memory/index.js' +import mode from './commands/mode/index.js' import help from './commands/help/index.js' import ide from './commands/ide/index.js' import init from './commands/init.js' @@ -279,6 +280,7 @@ const COMMANDS = memoize((): Command[] => [ mcp, memory, mobile, + mode, model, outputStyle, remoteEnv, diff --git a/src/commands/mode/index.ts b/src/commands/mode/index.ts new file mode 100644 index 000000000..d9b9e7339 --- /dev/null +++ b/src/commands/mode/index.ts @@ -0,0 +1,13 @@ +import type { Command } from '../../commands.js' + +const mode = { + type: 'local-jsx', + name: 'mode', + description: + 'Switch interaction mode (default, gentle, sharp, workhorse, token-saver, super-ai)', + isEnabled: () => true, + argumentHint: '', + load: () => import('./mode.js'), +} satisfies Command + +export default mode diff --git a/src/commands/mode/mode.tsx b/src/commands/mode/mode.tsx new file mode 100644 index 000000000..2aad5fde8 --- /dev/null +++ b/src/commands/mode/mode.tsx @@ -0,0 +1,79 @@ +import { useMemo } from 'react'; +import { Box, Text } from '@anthropic/ink'; +import { Select } from '../../components/CustomSelect/select.js'; +import type { LocalJSXCommandCall, LocalJSXCommandOnDone } from '../../types/command.js'; +import { getCurrentModeSlug, listModes, setCurrentMode } from '../../modes/store.js'; + +function ModePicker({ onDone }: { onDone: LocalJSXCommandOnDone }) { + const modes = listModes(); + const currentSlug = getCurrentModeSlug(); + + const options = useMemo( + () => + modes.map(m => ({ + label: ( + + {m.icon} {m.name}{' '} + + ({m.slug}) — {m.description} + + + ), + value: m.slug, + })), + [modes], + ); + + function handleSelect(slug: string) { + setCurrentMode(slug); + const target = modes.find(m => m.slug === slug); + onDone(`${target?.icon} Mode switched to: ${target?.name} (${target?.slug}) — ${target?.description}`, { + display: 'system', + }); + } + + function handleCancel() { + onDone('Mode selection cancelled.', { display: 'system' }); + } + + return ( + + + + Select mode + + Arrow keys to navigate, Enter to select, Esc to cancel. + +