chore: rebrand user-facing copy to OpenClaude (#851)
* chore: rebrand user-facing copy to OpenClaude Replace lingering Claude Code branding in CLI, tips, and runtime UI with OpenClaude/openclaude, including the startup tip Gitlawb mention. Co-Authored-By: Claude GPT-5.4 <noreply@openclaude.dev> * chore: address branding-sweep review feedback - PermissionRequest.tsx: rebrand the two remaining "Claude needs your approval/permission" notifications to OpenClaude (review-artifact and generic tool permission paths). - main.tsx, teleport.tsx, session.tsx, WebFetchTool/utils.ts, skills/bundled/{debug,updateConfig}.ts: replace leftover `claude --…` CLI hints and "Claude Code" labels missed by the original sweep. - main.tsx: drop the inline gitlawb.com marketing copy from the stale-prompt tip; keep it a pure rebrand. - auth.ts: finish the half-rename so both `claude setup-token` and `claude auth login` references in the same error block now read `openclaude …`. - mcp/client.ts: keep `name: 'claude-code'` for MCP server allowlist compatibility (now explicit via comment) and replace the "Anthropic's agentic coding tool" description with an OpenClaude one. - MCPSettings.tsx: point the empty-server-list hint at https://github.com/Gitlawb/openclaude instead of code.claude.com. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore: replace help link with OpenClaude repo URL Replace https://code.claude.com/docs/en/overview with https://github.com/Gitlawb/openclaude in the help screen. Co-Authored-By: OpenClaude <openclaude@gitlawb.com> --------- Co-authored-by: Claude GPT-5.4 <noreply@openclaude.dev> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: OpenClaude <openclaude@gitlawb.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@gitlawb/openclaude",
|
"name": "@gitlawb/openclaude",
|
||||||
"version": "0.6.0",
|
"version": "0.6.0",
|
||||||
"description": "Claude Code opened to any LLM — OpenAI, Gemini, DeepSeek, Ollama, and 200+ models",
|
"description": "OpenClaude opens coding-agent workflows to any LLM — OpenAI, Gemini, DeepSeek, Ollama, and 200+ models",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"bin": {
|
"bin": {
|
||||||
"openclaude": "./bin/openclaude"
|
"openclaude": "./bin/openclaude"
|
||||||
|
|||||||
@@ -70,13 +70,13 @@ export async function isBridgeEnabledBlocking(): Promise<boolean> {
|
|||||||
export async function getBridgeDisabledReason(): Promise<string | null> {
|
export async function getBridgeDisabledReason(): Promise<string | null> {
|
||||||
if (feature('BRIDGE_MODE')) {
|
if (feature('BRIDGE_MODE')) {
|
||||||
if (!isClaudeAISubscriber()) {
|
if (!isClaudeAISubscriber()) {
|
||||||
return 'Remote Control requires a claude.ai subscription. Run `claude auth login` to sign in with your claude.ai account.'
|
return 'Remote Control requires a claude.ai subscription. Run `openclaude auth login` to sign in with your claude.ai account.'
|
||||||
}
|
}
|
||||||
if (!hasProfileScope()) {
|
if (!hasProfileScope()) {
|
||||||
return 'Remote Control requires a full-scope login token. Long-lived tokens (from `claude setup-token` or CLAUDE_CODE_OAUTH_TOKEN) are limited to inference-only for security reasons. Run `claude auth login` to use Remote Control.'
|
return 'Remote Control requires a full-scope login token. Long-lived tokens (from `openclaude setup-token` or CLAUDE_CODE_OAUTH_TOKEN) are limited to inference-only for security reasons. Run `openclaude auth login` to use Remote Control.'
|
||||||
}
|
}
|
||||||
if (!getOauthAccountInfo()?.organizationUuid) {
|
if (!getOauthAccountInfo()?.organizationUuid) {
|
||||||
return 'Unable to determine your organization for Remote Control eligibility. Run `claude auth login` to refresh your account information.'
|
return 'Unable to determine your organization for Remote Control eligibility. Run `openclaude auth login` to refresh your account information.'
|
||||||
}
|
}
|
||||||
if (!(await checkGate_CACHED_OR_BLOCKING('tengu_ccr_bridge'))) {
|
if (!(await checkGate_CACHED_OR_BLOCKING('tengu_ccr_bridge'))) {
|
||||||
return 'Remote Control is not yet enabled for your account.'
|
return 'Remote Control is not yet enabled for your account.'
|
||||||
@@ -166,7 +166,7 @@ export function checkBridgeMinVersion(): string | null {
|
|||||||
minVersion: string
|
minVersion: string
|
||||||
}>('tengu_bridge_min_version', { minVersion: '0.0.0' })
|
}>('tengu_bridge_min_version', { minVersion: '0.0.0' })
|
||||||
if (config.minVersion && lt(MACRO.VERSION, config.minVersion)) {
|
if (config.minVersion && lt(MACRO.VERSION, config.minVersion)) {
|
||||||
return `Your version of Claude Code (${MACRO.VERSION}) is too old for Remote Control.\nVersion ${config.minVersion} or higher is required. Run \`claude update\` to update.`
|
return `Your version of OpenClaude (${MACRO.VERSION}) is too old for Remote Control.\nVersion ${config.minVersion} or higher is required. Run \`openclaude update\` to update.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
|
|||||||
@@ -2248,7 +2248,7 @@ export async function bridgeMain(args: string[]): Promise<void> {
|
|||||||
})
|
})
|
||||||
// biome-ignore lint/suspicious/noConsole: intentional dialog output
|
// biome-ignore lint/suspicious/noConsole: intentional dialog output
|
||||||
console.log(
|
console.log(
|
||||||
`\nClaude Remote Control is launching in spawn mode which lets you create new sessions in this project from Claude Code on Web or your Mobile app. Learn more here: https://code.claude.com/docs/en/remote-control\n\n` +
|
`\nClaude Remote Control is launching in spawn mode which lets you create new sessions in this project from OpenClaude on the web or your mobile app. Learn more here: https://code.claude.com/docs/en/remote-control\n\n` +
|
||||||
`Spawn mode for this project:\n` +
|
`Spawn mode for this project:\n` +
|
||||||
` [1] same-dir \u2014 sessions share the current directory (default)\n` +
|
` [1] same-dir \u2014 sessions share the current directory (default)\n` +
|
||||||
` [2] worktree \u2014 each session gets an isolated git worktree\n\n` +
|
` [2] worktree \u2014 each session gets an isolated git worktree\n\n` +
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ export async function getEnvLessBridgeConfig(): Promise<EnvLessBridgeConfig> {
|
|||||||
export async function checkEnvLessBridgeMinVersion(): Promise<string | null> {
|
export async function checkEnvLessBridgeMinVersion(): Promise<string | null> {
|
||||||
const cfg = await getEnvLessBridgeConfig()
|
const cfg = await getEnvLessBridgeConfig()
|
||||||
if (cfg.min_version && lt(MACRO.VERSION, cfg.min_version)) {
|
if (cfg.min_version && lt(MACRO.VERSION, cfg.min_version)) {
|
||||||
return `Your version of Claude Code (${MACRO.VERSION}) is too old for Remote Control.\nVersion ${cfg.min_version} or higher is required. Run \`claude update\` to update.`
|
return `Your version of OpenClaude (${MACRO.VERSION}) is too old for Remote Control.\nVersion ${cfg.min_version} or higher is required. Run \`openclaude update\` to update.`
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -415,7 +415,7 @@ export async function initReplBridge(
|
|||||||
`[bridge:repl] Skipping: ${versionError}`,
|
`[bridge:repl] Skipping: ${versionError}`,
|
||||||
true,
|
true,
|
||||||
)
|
)
|
||||||
onStateChange?.('failed', 'run `claude update` to upgrade')
|
onStateChange?.('failed', 'run `openclaude update` to upgrade')
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
logForDebugging(
|
logForDebugging(
|
||||||
@@ -456,7 +456,7 @@ export async function initReplBridge(
|
|||||||
const versionError = checkBridgeMinVersion()
|
const versionError = checkBridgeMinVersion()
|
||||||
if (versionError) {
|
if (versionError) {
|
||||||
logBridgeSkip('version_too_old', `[bridge:repl] Skipping: ${versionError}`)
|
logBridgeSkip('version_too_old', `[bridge:repl] Skipping: ${versionError}`)
|
||||||
onStateChange?.('failed', 'run `claude update` to upgrade')
|
onStateChange?.('failed', 'run `openclaude update` to upgrade')
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ export async function enrollTrustedDevice(): Promise<void> {
|
|||||||
device_id?: string
|
device_id?: string
|
||||||
}>(
|
}>(
|
||||||
`${baseUrl}/api/auth/trusted_devices`,
|
`${baseUrl}/api/auth/trusted_devices`,
|
||||||
{ display_name: `Claude Code on ${hostname()} · ${process.platform}` },
|
{ display_name: `OpenClaude on ${hostname()} · ${process.platform}` },
|
||||||
{
|
{
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${accessToken}`,
|
Authorization: `Bearer ${accessToken}`,
|
||||||
|
|||||||
@@ -287,7 +287,7 @@ export async function authStatus(opts: {
|
|||||||
}
|
}
|
||||||
if (!loggedIn) {
|
if (!loggedIn) {
|
||||||
process.stdout.write(
|
process.stdout.write(
|
||||||
'Not logged in. Run claude auth login to authenticate.\n',
|
'Not logged in. Run openclaude auth login to authenticate.\n',
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ export async function autoModeCritiqueHandler(options: {
|
|||||||
process.stdout.write(
|
process.stdout.write(
|
||||||
'No custom auto mode rules found.\n\n' +
|
'No custom auto mode rules found.\n\n' +
|
||||||
'Add rules to your settings file under autoMode.{allow, soft_deny, environment}.\n' +
|
'Add rules to your settings file under autoMode.{allow, soft_deny, environment}.\n' +
|
||||||
'Run `claude auto-mode defaults` to see the default rules for reference.\n',
|
'Run `openclaude auto-mode defaults` to see the default rules for reference.\n',
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -233,7 +233,7 @@ export async function mcpRemoveHandler(name: string, options: {
|
|||||||
});
|
});
|
||||||
process.stderr.write('\nTo remove from a specific scope, use:\n');
|
process.stderr.write('\nTo remove from a specific scope, use:\n');
|
||||||
scopes.forEach(scope => {
|
scopes.forEach(scope => {
|
||||||
process.stderr.write(` claude mcp remove "${name}" -s ${scope}\n`);
|
process.stderr.write(` openclaude mcp remove "${name}" -s ${scope}\n`);
|
||||||
});
|
});
|
||||||
cliError();
|
cliError();
|
||||||
}
|
}
|
||||||
@@ -250,7 +250,7 @@ export async function mcpListHandler(): Promise<void> {
|
|||||||
} = await getAllMcpConfigs();
|
} = await getAllMcpConfigs();
|
||||||
if (Object.keys(configs).length === 0) {
|
if (Object.keys(configs).length === 0) {
|
||||||
// biome-ignore lint/suspicious/noConsole:: intentional console output
|
// biome-ignore lint/suspicious/noConsole:: intentional console output
|
||||||
console.log('No MCP servers configured. Use `claude mcp add` to add a server.');
|
console.log('No MCP servers configured. Use `openclaude mcp add` to add a server.');
|
||||||
} else {
|
} else {
|
||||||
// biome-ignore lint/suspicious/noConsole:: intentional console output
|
// biome-ignore lint/suspicious/noConsole:: intentional console output
|
||||||
console.log('Checking MCP server health...\n');
|
console.log('Checking MCP server health...\n');
|
||||||
@@ -374,7 +374,7 @@ export async function mcpGetHandler(name: string): Promise<void> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// biome-ignore lint/suspicious/noConsole:: intentional console output
|
// biome-ignore lint/suspicious/noConsole:: intentional console output
|
||||||
console.log(`\nTo remove this server, run: claude mcp remove "${name}" -s ${server.scope}`);
|
console.log(`\nTo remove this server, run: openclaude mcp remove "${name}" -s ${server.scope}`);
|
||||||
// Use gracefulShutdown to properly clean up MCP server connections
|
// Use gracefulShutdown to properly clean up MCP server connections
|
||||||
// (process.exit bypasses cleanup handlers, leaving child processes orphaned)
|
// (process.exit bypasses cleanup handlers, leaving child processes orphaned)
|
||||||
await gracefulShutdown(0);
|
await gracefulShutdown(0);
|
||||||
@@ -455,5 +455,5 @@ export async function mcpResetChoicesHandler(): Promise<void> {
|
|||||||
disabledMcpjsonServers: [],
|
disabledMcpjsonServers: [],
|
||||||
enableAllProjectMcpServers: false
|
enableAllProjectMcpServers: false
|
||||||
}));
|
}));
|
||||||
cliOk('All project-scoped (.mcp.json) server approvals and rejections have been reset.\n' + 'You will be prompted for approval next time you start Claude Code.');
|
cliOk('All project-scoped (.mcp.json) server approvals and rejections have been reset.\n' + 'You will be prompted for approval next time you start OpenClaude.');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -352,7 +352,7 @@ export async function pluginListHandler(options: {
|
|||||||
// through to the session section so the failure is visible.
|
// through to the session section so the failure is visible.
|
||||||
if (inlineLoadErrors.length === 0) {
|
if (inlineLoadErrors.length === 0) {
|
||||||
cliOk(
|
cliOk(
|
||||||
'No plugins installed. Use `claude plugin install` to install a plugin.',
|
'No plugins installed. Use `openclaude plugin install` to install a plugin.',
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5026,7 +5026,7 @@ async function loadInitialMessages(
|
|||||||
)
|
)
|
||||||
if (!parsedSessionId) {
|
if (!parsedSessionId) {
|
||||||
let errorMessage =
|
let errorMessage =
|
||||||
'Error: --resume requires a valid session ID when used with --print. Usage: claude -p --resume <session-id>'
|
'Error: --resume requires a valid session ID when used with --print. Usage: openclaude -p --resume <session-id>'
|
||||||
if (typeof options.resume === 'string') {
|
if (typeof options.resume === 'string') {
|
||||||
errorMessage += `. Session IDs must be in UUID format (e.g., 550e8400-e29b-41d4-a716-446655440000). Provided value "${options.resume}" is not a valid UUID`
|
errorMessage += `. Session IDs must be in UUID format (e.g., 550e8400-e29b-41d4-a716-446655440000). Provided value "${options.resume}" is not a valid UUID`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -276,7 +276,7 @@ export async function update() {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
process.stderr.write('Error: Failed to install native update\n')
|
process.stderr.write('Error: Failed to install native update\n')
|
||||||
process.stderr.write(String(error) + '\n')
|
process.stderr.write(String(error) + '\n')
|
||||||
process.stderr.write('Try running "claude doctor" for diagnostics\n')
|
process.stderr.write('Try running "openclaude doctor" for diagnostics\n')
|
||||||
await gracefulShutdown(1)
|
await gracefulShutdown(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -199,7 +199,7 @@ import stats from './commands/stats/index.js'
|
|||||||
const usageReport: Command = {
|
const usageReport: Command = {
|
||||||
type: 'prompt',
|
type: 'prompt',
|
||||||
name: 'insights',
|
name: 'insights',
|
||||||
description: 'Generate a report analyzing your Claude Code sessions',
|
description: 'Generate a report analyzing your OpenClaude sessions',
|
||||||
contentLength: 0,
|
contentLength: 0,
|
||||||
progressMessage: 'analyzing your sessions',
|
progressMessage: 'analyzing your sessions',
|
||||||
source: 'builtin',
|
source: 'builtin',
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import type { Command } from '../../commands.js'
|
|||||||
const buddy = {
|
const buddy = {
|
||||||
type: 'local-jsx',
|
type: 'local-jsx',
|
||||||
name: 'buddy',
|
name: 'buddy',
|
||||||
description: 'Hatch, pet, and manage your Open Claude companion',
|
description: 'Hatch, pet, and manage your OpenClaude companion',
|
||||||
immediate: true,
|
immediate: true,
|
||||||
argumentHint: '[status|mute|unmute|help]',
|
argumentHint: '[status|mute|unmute|help]',
|
||||||
load: () => import('./buddy.js'),
|
load: () => import('./buddy.js'),
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ function ClaudeInChromeMenu(t0) {
|
|||||||
}
|
}
|
||||||
let t6;
|
let t6;
|
||||||
if ($[20] === Symbol.for("react.memo_cache_sentinel")) {
|
if ($[20] === Symbol.for("react.memo_cache_sentinel")) {
|
||||||
t6 = <Text>Claude in Chrome works with the Chrome extension to let you control your browser directly from Claude Code. Navigate websites, fill forms, capture screenshots, record GIFs, and debug with console logs and network requests.</Text>;
|
t6 = <Text>Claude in Chrome works with the Chrome extension to let you control your browser directly from OpenClaude. Navigate websites, fill forms, capture screenshots, record GIFs, and debug with console logs and network requests.</Text>;
|
||||||
$[20] = t6;
|
$[20] = t6;
|
||||||
} else {
|
} else {
|
||||||
t6 = $[20];
|
t6 = $[20];
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ export function createMovedToPluginCommand({
|
|||||||
text: `This command has been moved to a plugin. Tell the user:
|
text: `This command has been moved to a plugin. Tell the user:
|
||||||
|
|
||||||
1. To install the plugin, run:
|
1. To install the plugin, run:
|
||||||
claude plugin install ${pluginName}@claude-code-marketplace
|
openclaude plugin install ${pluginName}@claude-code-marketplace
|
||||||
|
|
||||||
2. After installation, use /${pluginName}:${pluginCommand} to run this command
|
2. After installation, use /${pluginName}:${pluginCommand} to run this command
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { isEnvTruthy } from '../../utils/envUtils.js'
|
|||||||
|
|
||||||
const doctor: Command = {
|
const doctor: Command = {
|
||||||
name: 'doctor',
|
name: 'doctor',
|
||||||
description: 'Diagnose and verify your Claude Code installation and settings',
|
description: 'Diagnose and verify your OpenClaude installation and settings',
|
||||||
isEnabled: () => !isEnvTruthy(process.env.DISABLE_DOCTOR_COMMAND),
|
isEnabled: () => !isEnvTruthy(process.env.DISABLE_DOCTOR_COMMAND),
|
||||||
type: 'local-jsx',
|
type: 'local-jsx',
|
||||||
load: () => import('./doctor.js'),
|
load: () => import('./doctor.js'),
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ const feedback = {
|
|||||||
aliases: ['bug'],
|
aliases: ['bug'],
|
||||||
type: 'local-jsx',
|
type: 'local-jsx',
|
||||||
name: 'feedback',
|
name: 'feedback',
|
||||||
description: `Submit feedback about Claude Code`,
|
description: `Submit feedback about OpenClaude`,
|
||||||
argumentHint: '[report]',
|
argumentHint: '[report]',
|
||||||
isEnabled: () =>
|
isEnabled: () =>
|
||||||
!(
|
!(
|
||||||
|
|||||||
@@ -247,7 +247,7 @@ function getSessionMetaDir(): string {
|
|||||||
return join(getDataDir(), 'session-meta')
|
return join(getDataDir(), 'session-meta')
|
||||||
}
|
}
|
||||||
|
|
||||||
const FACET_EXTRACTION_PROMPT = `Analyze this Claude Code session and extract structured facets.
|
const FACET_EXTRACTION_PROMPT = `Analyze this OpenClaude session and extract structured facets.
|
||||||
|
|
||||||
CRITICAL GUIDELINES:
|
CRITICAL GUIDELINES:
|
||||||
|
|
||||||
@@ -687,7 +687,7 @@ function formatTranscriptForFacets(log: LogOption): string {
|
|||||||
return lines.join('\n')
|
return lines.join('\n')
|
||||||
}
|
}
|
||||||
|
|
||||||
const SUMMARIZE_CHUNK_PROMPT = `Summarize this portion of a Claude Code session transcript. Focus on:
|
const SUMMARIZE_CHUNK_PROMPT = `Summarize this portion of a OpenClaude session transcript. Focus on:
|
||||||
1. What the user asked for
|
1. What the user asked for
|
||||||
2. What Claude did (tools used, files modified)
|
2. What Claude did (tools used, files modified)
|
||||||
3. Any friction or issues
|
3. Any friction or issues
|
||||||
@@ -1156,12 +1156,12 @@ type InsightSection = {
|
|||||||
const INSIGHT_SECTIONS: InsightSection[] = [
|
const INSIGHT_SECTIONS: InsightSection[] = [
|
||||||
{
|
{
|
||||||
name: 'project_areas',
|
name: 'project_areas',
|
||||||
prompt: `Analyze this Claude Code usage data and identify project areas.
|
prompt: `Analyze this OpenClaude usage data and identify project areas.
|
||||||
|
|
||||||
RESPOND WITH ONLY A VALID JSON OBJECT:
|
RESPOND WITH ONLY A VALID JSON OBJECT:
|
||||||
{
|
{
|
||||||
"areas": [
|
"areas": [
|
||||||
{"name": "Area name", "session_count": N, "description": "2-3 sentences about what was worked on and how Claude Code was used."}
|
{"name": "Area name", "session_count": N, "description": "2-3 sentences about what was worked on and how OpenClaude was used."}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1170,18 +1170,18 @@ Include 4-5 areas. Skip internal CC operations.`,
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'interaction_style',
|
name: 'interaction_style',
|
||||||
prompt: `Analyze this Claude Code usage data and describe the user's interaction style.
|
prompt: `Analyze this OpenClaude usage data and describe the user's interaction style.
|
||||||
|
|
||||||
RESPOND WITH ONLY A VALID JSON OBJECT:
|
RESPOND WITH ONLY A VALID JSON OBJECT:
|
||||||
{
|
{
|
||||||
"narrative": "2-3 paragraphs analyzing HOW the user interacts with Claude Code. Use second person 'you'. Describe patterns: iterate quickly vs detailed upfront specs? Interrupt often or let Claude run? Include specific examples. Use **bold** for key insights.",
|
"narrative": "2-3 paragraphs analyzing HOW the user interacts with OpenClaude. Use second person 'you'. Describe patterns: iterate quickly vs detailed upfront specs? Interrupt often or let Claude run? Include specific examples. Use **bold** for key insights.",
|
||||||
"key_pattern": "One sentence summary of most distinctive interaction style"
|
"key_pattern": "One sentence summary of most distinctive interaction style"
|
||||||
}`,
|
}`,
|
||||||
maxTokens: 8192,
|
maxTokens: 8192,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'what_works',
|
name: 'what_works',
|
||||||
prompt: `Analyze this Claude Code usage data and identify what's working well for this user. Use second person ("you").
|
prompt: `Analyze this OpenClaude usage data and identify what's working well for this user. Use second person ("you").
|
||||||
|
|
||||||
RESPOND WITH ONLY A VALID JSON OBJECT:
|
RESPOND WITH ONLY A VALID JSON OBJECT:
|
||||||
{
|
{
|
||||||
@@ -1196,7 +1196,7 @@ Include 3 impressive workflows.`,
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'friction_analysis',
|
name: 'friction_analysis',
|
||||||
prompt: `Analyze this Claude Code usage data and identify friction points for this user. Use second person ("you").
|
prompt: `Analyze this OpenClaude usage data and identify friction points for this user. Use second person ("you").
|
||||||
|
|
||||||
RESPOND WITH ONLY A VALID JSON OBJECT:
|
RESPOND WITH ONLY A VALID JSON OBJECT:
|
||||||
{
|
{
|
||||||
@@ -1211,7 +1211,7 @@ Include 3 friction categories with 2 examples each.`,
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'suggestions',
|
name: 'suggestions',
|
||||||
prompt: `Analyze this Claude Code usage data and suggest improvements.
|
prompt: `Analyze this OpenClaude usage data and suggest improvements.
|
||||||
|
|
||||||
## CC FEATURES REFERENCE (pick from these for features_to_try):
|
## CC FEATURES REFERENCE (pick from these for features_to_try):
|
||||||
1. **MCP Servers**: Connect Claude to external tools, databases, and APIs via Model Context Protocol.
|
1. **MCP Servers**: Connect Claude to external tools, databases, and APIs via Model Context Protocol.
|
||||||
@@ -1254,7 +1254,7 @@ IMPORTANT for features_to_try: Pick 2-3 from the CC FEATURES REFERENCE above. In
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'on_the_horizon',
|
name: 'on_the_horizon',
|
||||||
prompt: `Analyze this Claude Code usage data and identify future opportunities.
|
prompt: `Analyze this OpenClaude usage data and identify future opportunities.
|
||||||
|
|
||||||
RESPOND WITH ONLY A VALID JSON OBJECT:
|
RESPOND WITH ONLY A VALID JSON OBJECT:
|
||||||
{
|
{
|
||||||
@@ -1271,7 +1271,7 @@ Include 3 opportunities. Think BIG - autonomous workflows, parallel agents, iter
|
|||||||
? [
|
? [
|
||||||
{
|
{
|
||||||
name: 'cc_team_improvements',
|
name: 'cc_team_improvements',
|
||||||
prompt: `Analyze this Claude Code usage data and suggest product improvements for the CC team.
|
prompt: `Analyze this OpenClaude usage data and suggest product improvements for the CC team.
|
||||||
|
|
||||||
RESPOND WITH ONLY A VALID JSON OBJECT:
|
RESPOND WITH ONLY A VALID JSON OBJECT:
|
||||||
{
|
{
|
||||||
@@ -1285,7 +1285,7 @@ Include 2-3 improvements based on friction patterns observed.`,
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'model_behavior_improvements',
|
name: 'model_behavior_improvements',
|
||||||
prompt: `Analyze this Claude Code usage data and suggest model behavior improvements.
|
prompt: `Analyze this OpenClaude usage data and suggest model behavior improvements.
|
||||||
|
|
||||||
RESPOND WITH ONLY A VALID JSON OBJECT:
|
RESPOND WITH ONLY A VALID JSON OBJECT:
|
||||||
{
|
{
|
||||||
@@ -1301,7 +1301,7 @@ Include 2-3 improvements based on friction patterns observed.`,
|
|||||||
: []),
|
: []),
|
||||||
{
|
{
|
||||||
name: 'fun_ending',
|
name: 'fun_ending',
|
||||||
prompt: `Analyze this Claude Code usage data and find a memorable moment.
|
prompt: `Analyze this OpenClaude usage data and find a memorable moment.
|
||||||
|
|
||||||
RESPOND WITH ONLY A VALID JSON OBJECT:
|
RESPOND WITH ONLY A VALID JSON OBJECT:
|
||||||
{
|
{
|
||||||
@@ -1555,7 +1555,7 @@ async function generateParallelInsights(
|
|||||||
.join('\n') || ''
|
.join('\n') || ''
|
||||||
|
|
||||||
// Now generate "At a Glance" with access to other sections' outputs
|
// Now generate "At a Glance" with access to other sections' outputs
|
||||||
const atAGlancePrompt = `You're writing an "At a Glance" summary for a Claude Code usage insights report for Claude Code users. The goal is to help them understand their usage and improve how they can use Claude better, especially as models improve.
|
const atAGlancePrompt = `You're writing an "At a Glance" summary for a OpenClaude usage insights report for OpenClaude users. The goal is to help them understand their usage and improve how they can use Claude better, especially as models improve.
|
||||||
|
|
||||||
Use this 4-part structure:
|
Use this 4-part structure:
|
||||||
|
|
||||||
@@ -1563,7 +1563,7 @@ Use this 4-part structure:
|
|||||||
|
|
||||||
2. **What's hindering you** - Split into (a) Claude's fault (misunderstandings, wrong approaches, bugs) and (b) user-side friction (not providing enough context, environment issues -- ideally more general than just one project). Be honest but constructive.
|
2. **What's hindering you** - Split into (a) Claude's fault (misunderstandings, wrong approaches, bugs) and (b) user-side friction (not providing enough context, environment issues -- ideally more general than just one project). Be honest but constructive.
|
||||||
|
|
||||||
3. **Quick wins to try** - Specific Claude Code features they could try from the examples below, or a workflow technique if you think it's really compelling. (Avoid stuff like "Ask Claude to confirm before taking actions" or "Type out more context up front" which are less compelling.)
|
3. **Quick wins to try** - Specific OpenClaude features they could try from the examples below, or a workflow technique if you think it's really compelling. (Avoid stuff like "Ask Claude to confirm before taking actions" or "Type out more context up front" which are less compelling.)
|
||||||
|
|
||||||
4. **Ambitious workflows for better models** - As we move to much more capable models over the next 3-6 months, what should they prepare for? What workflows that seem impossible now will become possible? Draw from the appropriate section below.
|
4. **Ambitious workflows for better models** - As we move to much more capable models over the next 3-6 months, what should they prepare for? What workflows that seem impossible now will become possible? Draw from the appropriate section below.
|
||||||
|
|
||||||
@@ -1826,7 +1826,7 @@ function generateHtmlReport(
|
|||||||
const interactionStyle = insights.interaction_style
|
const interactionStyle = insights.interaction_style
|
||||||
const interactionHtml = interactionStyle?.narrative
|
const interactionHtml = interactionStyle?.narrative
|
||||||
? `
|
? `
|
||||||
<h2 id="section-usage">How You Use Claude Code</h2>
|
<h2 id="section-usage">How You Use OpenClaude</h2>
|
||||||
<div class="narrative">
|
<div class="narrative">
|
||||||
${markdownToHtml(interactionStyle.narrative)}
|
${markdownToHtml(interactionStyle.narrative)}
|
||||||
${interactionStyle.key_pattern ? `<div class="key-insight"><strong>Key pattern:</strong> ${escapeHtml(interactionStyle.key_pattern)}</div>` : ''}
|
${interactionStyle.key_pattern ? `<div class="key-insight"><strong>Key pattern:</strong> ${escapeHtml(interactionStyle.key_pattern)}</div>` : ''}
|
||||||
@@ -1890,7 +1890,7 @@ function generateHtmlReport(
|
|||||||
<h2 id="section-features">Existing CC Features to Try</h2>
|
<h2 id="section-features">Existing CC Features to Try</h2>
|
||||||
<div class="claude-md-section">
|
<div class="claude-md-section">
|
||||||
<h3>Suggested CLAUDE.md Additions</h3>
|
<h3>Suggested CLAUDE.md Additions</h3>
|
||||||
<p style="font-size: 12px; color: #64748b; margin-bottom: 12px;">Just copy this into Claude Code to add it to your CLAUDE.md.</p>
|
<p style="font-size: 12px; color: #64748b; margin-bottom: 12px;">Just copy this into OpenClaude to add it to your CLAUDE.md.</p>
|
||||||
<div class="claude-md-actions">
|
<div class="claude-md-actions">
|
||||||
<button class="copy-all-btn" onclick="copyAllCheckedClaudeMd()">Copy All Checked</button>
|
<button class="copy-all-btn" onclick="copyAllCheckedClaudeMd()">Copy All Checked</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -1915,7 +1915,7 @@ function generateHtmlReport(
|
|||||||
${
|
${
|
||||||
suggestions.features_to_try && suggestions.features_to_try.length > 0
|
suggestions.features_to_try && suggestions.features_to_try.length > 0
|
||||||
? `
|
? `
|
||||||
<p style="font-size: 13px; color: #64748b; margin-bottom: 12px;">Just copy this into Claude Code and it'll set it up for you.</p>
|
<p style="font-size: 13px; color: #64748b; margin-bottom: 12px;">Just copy this into OpenClaude and it'll set it up for you.</p>
|
||||||
<div class="features-section">
|
<div class="features-section">
|
||||||
${suggestions.features_to_try
|
${suggestions.features_to_try
|
||||||
.map(
|
.map(
|
||||||
@@ -1949,8 +1949,8 @@ function generateHtmlReport(
|
|||||||
${
|
${
|
||||||
suggestions.usage_patterns && suggestions.usage_patterns.length > 0
|
suggestions.usage_patterns && suggestions.usage_patterns.length > 0
|
||||||
? `
|
? `
|
||||||
<h2 id="section-patterns">New Ways to Use Claude Code</h2>
|
<h2 id="section-patterns">New Ways to Use OpenClaude</h2>
|
||||||
<p style="font-size: 13px; color: #64748b; margin-bottom: 12px;">Just copy this into Claude Code and it'll walk you through it.</p>
|
<p style="font-size: 13px; color: #64748b; margin-bottom: 12px;">Just copy this into OpenClaude and it'll walk you through it.</p>
|
||||||
<div class="patterns-section">
|
<div class="patterns-section">
|
||||||
${suggestions.usage_patterns
|
${suggestions.usage_patterns
|
||||||
.map(
|
.map(
|
||||||
@@ -1963,7 +1963,7 @@ function generateHtmlReport(
|
|||||||
pat.copyable_prompt
|
pat.copyable_prompt
|
||||||
? `
|
? `
|
||||||
<div class="copyable-prompt-section">
|
<div class="copyable-prompt-section">
|
||||||
<div class="prompt-label">Paste into Claude Code:</div>
|
<div class="prompt-label">Paste into OpenClaude:</div>
|
||||||
<div class="copyable-prompt-row">
|
<div class="copyable-prompt-row">
|
||||||
<code class="copyable-prompt">${escapeHtml(pat.copyable_prompt)}</code>
|
<code class="copyable-prompt">${escapeHtml(pat.copyable_prompt)}</code>
|
||||||
<button class="copy-btn" onclick="copyText(this)">Copy</button>
|
<button class="copy-btn" onclick="copyText(this)">Copy</button>
|
||||||
@@ -1998,7 +1998,7 @@ function generateHtmlReport(
|
|||||||
<div class="horizon-title">${escapeHtml(opp.title || '')}</div>
|
<div class="horizon-title">${escapeHtml(opp.title || '')}</div>
|
||||||
<div class="horizon-possible">${escapeHtml(opp.whats_possible || '')}</div>
|
<div class="horizon-possible">${escapeHtml(opp.whats_possible || '')}</div>
|
||||||
${opp.how_to_try ? `<div class="horizon-tip"><strong>Getting started:</strong> ${escapeHtml(opp.how_to_try)}</div>` : ''}
|
${opp.how_to_try ? `<div class="horizon-tip"><strong>Getting started:</strong> ${escapeHtml(opp.how_to_try)}</div>` : ''}
|
||||||
${opp.copyable_prompt ? `<div class="pattern-prompt"><div class="prompt-label">Paste into Claude Code:</div><code>${escapeHtml(opp.copyable_prompt)}</code><button class="copy-btn" onclick="copyText(this)">Copy</button></div>` : ''}
|
${opp.copyable_prompt ? `<div class="pattern-prompt"><div class="prompt-label">Paste into OpenClaude:</div><code>${escapeHtml(opp.copyable_prompt)}</code><button class="copy-btn" onclick="copyText(this)">Copy</button></div>` : ''}
|
||||||
</div>
|
</div>
|
||||||
`,
|
`,
|
||||||
)
|
)
|
||||||
@@ -2305,13 +2305,13 @@ function generateHtmlReport(
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>Claude Code Insights</title>
|
<title>OpenClaude Insights</title>
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||||
<style>${css}</style>
|
<style>${css}</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h1>Claude Code Insights</h1>
|
<h1>OpenClaude Insights</h1>
|
||||||
<p class="subtitle">${data.total_messages.toLocaleString()} messages across ${data.total_sessions} sessions${data.total_sessions_scanned && data.total_sessions_scanned > data.total_sessions ? ` (${data.total_sessions_scanned.toLocaleString()} total)` : ''} | ${data.date_range.start} to ${data.date_range.end}</p>
|
<p class="subtitle">${data.total_messages.toLocaleString()} messages across ${data.total_sessions} sessions${data.total_sessions_scanned && data.total_sessions_scanned > data.total_sessions ? ` (${data.total_sessions_scanned.toLocaleString()} total)` : ''} | ${data.date_range.start} to ${data.date_range.end}</p>
|
||||||
|
|
||||||
${atAGlanceHtml}
|
${atAGlanceHtml}
|
||||||
@@ -2377,7 +2377,7 @@ function generateHtmlReport(
|
|||||||
data.multi_clauding.overlap_events === 0
|
data.multi_clauding.overlap_events === 0
|
||||||
? `
|
? `
|
||||||
<p style="font-size: 14px; color: #64748b; padding: 8px 0;">
|
<p style="font-size: 14px; color: #64748b; padding: 8px 0;">
|
||||||
No parallel session usage detected. You typically work with one Claude Code session at a time.
|
No parallel session usage detected. You typically work with one OpenClaude session at a time.
|
||||||
</p>
|
</p>
|
||||||
`
|
`
|
||||||
: `
|
: `
|
||||||
@@ -2396,7 +2396,7 @@ function generateHtmlReport(
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p style="font-size: 13px; color: #475569; margin-top: 12px;">
|
<p style="font-size: 13px; color: #475569; margin-top: 12px;">
|
||||||
You run multiple Claude Code sessions simultaneously. Multi-clauding is detected when sessions
|
You run multiple OpenClaude sessions simultaneously. Multi-clauding is detected when sessions
|
||||||
overlap in time, suggesting parallel workflows.
|
overlap in time, suggesting parallel workflows.
|
||||||
</p>
|
</p>
|
||||||
`
|
`
|
||||||
@@ -2836,7 +2836,7 @@ function safeKeys(obj: Record<string, unknown> | undefined | null): string[] {
|
|||||||
const usageReport: Command = {
|
const usageReport: Command = {
|
||||||
type: 'prompt',
|
type: 'prompt',
|
||||||
name: 'insights',
|
name: 'insights',
|
||||||
description: 'Generate a report analyzing your Claude Code sessions',
|
description: 'Generate a report analyzing your OpenClaude sessions',
|
||||||
contentLength: 0, // Dynamic content
|
contentLength: 0, // Dynamic content
|
||||||
progressMessage: 'analyzing your sessions',
|
progressMessage: 'analyzing your sessions',
|
||||||
source: 'builtin',
|
source: 'builtin',
|
||||||
@@ -2874,7 +2874,7 @@ ${atAGlance.quick_wins ? `**Quick wins to try:** ${atAGlance.quick_wins} See _Fe
|
|||||||
${atAGlance.ambitious_workflows ? `**Ambitious workflows:** ${atAGlance.ambitious_workflows} See _On the Horizon_.` : ''}`
|
${atAGlance.ambitious_workflows ? `**Ambitious workflows:** ${atAGlance.ambitious_workflows} See _On the Horizon_.` : ''}`
|
||||||
: '_No insights generated_'
|
: '_No insights generated_'
|
||||||
|
|
||||||
const header = `# Claude Code Insights
|
const header = `# OpenClaude Insights
|
||||||
|
|
||||||
${stats}
|
${stats}
|
||||||
${data.date_range.start} to ${data.date_range.end}
|
${data.date_range.start} to ${data.date_range.end}
|
||||||
@@ -2888,7 +2888,7 @@ Your full shareable insights report is ready: ${reportUrl}${uploadHint}`
|
|||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
type: 'text',
|
type: 'text',
|
||||||
text: `The user just ran /insights to generate a usage report analyzing their Claude Code sessions.
|
text: `The user just ran /insights to generate a usage report analyzing their OpenClaude sessions.
|
||||||
|
|
||||||
Here is the full insights data:
|
Here is the full insights data:
|
||||||
${jsonStringify(insights, null, 2)}
|
${jsonStringify(insights, null, 2)}
|
||||||
|
|||||||
@@ -210,12 +210,12 @@ function Install({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (state.type === 'success') {
|
if (state.type === 'success') {
|
||||||
// Give success message time to render before exiting
|
// Give success message time to render before exiting
|
||||||
setTimeout(onDone, 2000, 'Claude Code installation completed successfully', {
|
setTimeout(onDone, 2000, 'OpenClaude installation completed successfully', {
|
||||||
display: 'system' as const
|
display: 'system' as const
|
||||||
});
|
});
|
||||||
} else if (state.type === 'error') {
|
} else if (state.type === 'error') {
|
||||||
// Give error message time to render before exiting
|
// Give error message time to render before exiting
|
||||||
setTimeout(onDone, 3000, 'Claude Code installation failed', {
|
setTimeout(onDone, 3000, 'OpenClaude installation failed', {
|
||||||
display: 'system' as const
|
display: 'system' as const
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -226,7 +226,7 @@ function Install({
|
|||||||
{state.type === 'cleaning-npm' && <Text color="warning">Cleaning up old npm installations...</Text>}
|
{state.type === 'cleaning-npm' && <Text color="warning">Cleaning up old npm installations...</Text>}
|
||||||
|
|
||||||
{state.type === 'installing' && <Text color="claude">
|
{state.type === 'installing' && <Text color="claude">
|
||||||
Installing Claude Code native build {state.version}...
|
Installing OpenClaude native build {state.version}...
|
||||||
</Text>}
|
</Text>}
|
||||||
|
|
||||||
{state.type === 'setting-up' && <Text color="claude">Setting up launcher and shell integration...</Text>}
|
{state.type === 'setting-up' && <Text color="claude">Setting up launcher and shell integration...</Text>}
|
||||||
@@ -237,7 +237,7 @@ function Install({
|
|||||||
<Box>
|
<Box>
|
||||||
<StatusIcon status="success" withSpace />
|
<StatusIcon status="success" withSpace />
|
||||||
<Text color="success" bold>
|
<Text color="success" bold>
|
||||||
Claude Code successfully installed!
|
OpenClaude successfully installed!
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
<Box marginLeft={2} flexDirection="column" gap={1}>
|
<Box marginLeft={2} flexDirection="column" gap={1}>
|
||||||
@@ -254,7 +254,7 @@ function Install({
|
|||||||
<Box marginTop={1}>
|
<Box marginTop={1}>
|
||||||
<Text dimColor>Next: Run </Text>
|
<Text dimColor>Next: Run </Text>
|
||||||
<Text color="claude" bold>
|
<Text color="claude" bold>
|
||||||
claude --help
|
openclaude --help
|
||||||
</Text>
|
</Text>
|
||||||
<Text dimColor> to get started</Text>
|
<Text dimColor> to get started</Text>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -279,7 +279,7 @@ function Install({
|
|||||||
export const install = {
|
export const install = {
|
||||||
type: 'local-jsx' as const,
|
type: 'local-jsx' as const,
|
||||||
name: 'install',
|
name: 'install',
|
||||||
description: 'Install Claude Code native build',
|
description: 'Install OpenClaude native build',
|
||||||
argumentHint: '[options]',
|
argumentHint: '[options]',
|
||||||
async call(onDone: (result: string, options?: {
|
async call(onDone: (result: string, options?: {
|
||||||
display?: CommandResultDisplay;
|
display?: CommandResultDisplay;
|
||||||
|
|||||||
@@ -34,16 +34,16 @@ export function registerMcpAddCommand(mcp: Command): void {
|
|||||||
mcp
|
mcp
|
||||||
.command('add <name> <commandOrUrl> [args...]')
|
.command('add <name> <commandOrUrl> [args...]')
|
||||||
.description(
|
.description(
|
||||||
'Add an MCP server to Claude Code.\n\n' +
|
'Add an MCP server to OpenClaude.\n\n' +
|
||||||
'Examples:\n' +
|
'Examples:\n' +
|
||||||
' # Add HTTP server:\n' +
|
' # Add HTTP server:\n' +
|
||||||
' claude mcp add --transport http sentry https://mcp.sentry.dev/mcp\n\n' +
|
' openclaude mcp add --transport http sentry https://mcp.sentry.dev/mcp\n\n' +
|
||||||
' # Add HTTP server with headers:\n' +
|
' # Add HTTP server with headers:\n' +
|
||||||
' claude mcp add --transport http corridor https://app.corridor.dev/api/mcp --header "Authorization: Bearer ..."\n\n' +
|
' openclaude mcp add --transport http corridor https://app.corridor.dev/api/mcp --header "Authorization: Bearer ..."\n\n' +
|
||||||
' # Add stdio server with environment variables:\n' +
|
' # Add stdio server with environment variables:\n' +
|
||||||
' claude mcp add -e API_KEY=xxx my-server -- npx my-mcp-server\n\n' +
|
' openclaude mcp add -e API_KEY=xxx my-server -- npx my-mcp-server\n\n' +
|
||||||
' # Add stdio server with subprocess flags:\n' +
|
' # Add stdio server with subprocess flags:\n' +
|
||||||
' claude mcp add my-server -- my-command --some-flag arg1',
|
' openclaude mcp add my-server -- my-command --some-flag arg1',
|
||||||
)
|
)
|
||||||
.option(
|
.option(
|
||||||
'-s, --scope <scope>',
|
'-s, --scope <scope>',
|
||||||
@@ -75,7 +75,7 @@ export function registerMcpAddCommand(mcp: Command): void {
|
|||||||
.addOption(
|
.addOption(
|
||||||
new Option(
|
new Option(
|
||||||
'--xaa',
|
'--xaa',
|
||||||
"Enable XAA (SEP-990) for this server. Requires 'claude mcp xaa setup' first. Also requires --client-id and --client-secret (for the MCP server's AS).",
|
"Enable XAA (SEP-990) for this server. Requires 'openclaude mcp xaa setup' first. Also requires --client-id and --client-secret (for the MCP server's AS).",
|
||||||
).hideHelp(!isXaaEnabled()),
|
).hideHelp(!isXaaEnabled()),
|
||||||
)
|
)
|
||||||
.action(async (name, commandOrUrl, args, options) => {
|
.action(async (name, commandOrUrl, args, options) => {
|
||||||
@@ -87,12 +87,12 @@ export function registerMcpAddCommand(mcp: Command): void {
|
|||||||
if (!name) {
|
if (!name) {
|
||||||
cliError(
|
cliError(
|
||||||
'Error: Server name is required.\n' +
|
'Error: Server name is required.\n' +
|
||||||
'Usage: claude mcp add <name> <command> [args...]',
|
'Usage: openclaude mcp add <name> <command> [args...]',
|
||||||
)
|
)
|
||||||
} else if (!actualCommand) {
|
} else if (!actualCommand) {
|
||||||
cliError(
|
cliError(
|
||||||
'Error: Command is required when server name is provided.\n' +
|
'Error: Command is required when server name is provided.\n' +
|
||||||
'Usage: claude mcp add <name> <command> [args...]',
|
'Usage: openclaude mcp add <name> <command> [args...]',
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,7 +113,7 @@ export function registerMcpAddCommand(mcp: Command): void {
|
|||||||
if (!options.clientSecret) missing.push('--client-secret')
|
if (!options.clientSecret) missing.push('--client-secret')
|
||||||
if (!getXaaIdpSettings()) {
|
if (!getXaaIdpSettings()) {
|
||||||
missing.push(
|
missing.push(
|
||||||
"'claude mcp xaa setup' (settings.xaaIdp not configured)",
|
"'openclaude mcp xaa setup' (settings.xaaIdp not configured)",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (missing.length) {
|
if (missing.length) {
|
||||||
@@ -254,10 +254,10 @@ export function registerMcpAddCommand(mcp: Command): void {
|
|||||||
`\nWarning: The command "${actualCommand}" looks like a URL, but is being interpreted as a stdio server as --transport was not specified.\n`,
|
`\nWarning: The command "${actualCommand}" looks like a URL, but is being interpreted as a stdio server as --transport was not specified.\n`,
|
||||||
)
|
)
|
||||||
process.stderr.write(
|
process.stderr.write(
|
||||||
`If this is an HTTP server, use: claude mcp add --transport http ${name} ${actualCommand}\n`,
|
`If this is an HTTP server, use: openclaude mcp add --transport http ${name} ${actualCommand}\n`,
|
||||||
)
|
)
|
||||||
process.stderr.write(
|
process.stderr.write(
|
||||||
`If this is an SSE server, use: claude mcp add --transport sse ${name} ${actualCommand}\n`,
|
`If this is an SSE server, use: openclaude mcp add --transport sse ${name} ${actualCommand}\n`,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ export function registerMcpXaaIdpCommand(mcp: Command): void {
|
|||||||
const idp = getXaaIdpSettings()
|
const idp = getXaaIdpSettings()
|
||||||
if (!idp) {
|
if (!idp) {
|
||||||
return cliError(
|
return cliError(
|
||||||
"Error: no XAA IdP connection. Run 'claude mcp xaa setup' first.",
|
"Error: no XAA IdP connection. Run 'openclaude mcp xaa setup' first.",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -235,7 +235,7 @@ export function registerMcpXaaIdpCommand(mcp: Command): void {
|
|||||||
`Client secret: ${hasSecret ? '(stored in keychain)' : '(not set — PKCE-only)'}\n`,
|
`Client secret: ${hasSecret ? '(stored in keychain)' : '(not set — PKCE-only)'}\n`,
|
||||||
)
|
)
|
||||||
process.stdout.write(
|
process.stdout.write(
|
||||||
`Logged in: ${hasIdToken ? 'yes (id_token cached)' : "no — run 'claude mcp xaa login'"}\n`,
|
`Logged in: ${hasIdToken ? 'yes (id_token cached)' : "no — run 'openclaude mcp xaa login'"}\n`,
|
||||||
)
|
)
|
||||||
cliOk()
|
cliOk()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ export default {
|
|||||||
type: 'local-jsx',
|
type: 'local-jsx',
|
||||||
name: 'model',
|
name: 'model',
|
||||||
get description() {
|
get description() {
|
||||||
return `Set the AI model for Claude Code (currently ${renderModelName(getMainLoopModel())})`
|
return `Set the AI model for OpenClaude (currently ${renderModelName(getMainLoopModel())})`
|
||||||
},
|
},
|
||||||
argumentHint: '[model]',
|
argumentHint: '[model]',
|
||||||
get immediate() {
|
get immediate() {
|
||||||
|
|||||||
@@ -713,7 +713,7 @@ function EmptyStateMessage(t0) {
|
|||||||
{
|
{
|
||||||
let t1;
|
let t1;
|
||||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||||
t1 = <><Text dimColor={true}>Git is required to install marketplaces.</Text><Text dimColor={true}>Please install git and restart Claude Code.</Text></>;
|
t1 = <><Text dimColor={true}>Git is required to install marketplaces.</Text><Text dimColor={true}>Please install git and restart OpenClaude.</Text></>;
|
||||||
$[0] = t1;
|
$[0] = t1;
|
||||||
} else {
|
} else {
|
||||||
t1 = $[0];
|
t1 = $[0];
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ const plugin = {
|
|||||||
type: 'local-jsx',
|
type: 'local-jsx',
|
||||||
name: 'plugin',
|
name: 'plugin',
|
||||||
aliases: ['plugins', 'marketplace'],
|
aliases: ['plugins', 'marketplace'],
|
||||||
description: 'Manage Claude Code plugins',
|
description: 'Manage OpenClaude plugins',
|
||||||
immediate: true,
|
immediate: true,
|
||||||
load: () => import('./plugin.js')
|
load: () => import('./plugin.js')
|
||||||
} satisfies Command;
|
} satisfies Command;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ const web = {
|
|||||||
type: 'local-jsx',
|
type: 'local-jsx',
|
||||||
name: 'web-setup',
|
name: 'web-setup',
|
||||||
description:
|
description:
|
||||||
'Setup Claude Code on the web (requires connecting your GitHub account)',
|
'Setup OpenClaude on the web (requires connecting your GitHub account)',
|
||||||
availability: ['claude-ai'],
|
availability: ['claude-ai'],
|
||||||
isEnabled: () =>
|
isEnabled: () =>
|
||||||
getFeatureValue_CACHED_MAY_BE_STALE('tengu_cobalt_lantern', false) &&
|
getFeatureValue_CACHED_MAY_BE_STALE('tengu_cobalt_lantern', false) &&
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ const review: Command = {
|
|||||||
const ultrareview: Command = {
|
const ultrareview: Command = {
|
||||||
type: 'local-jsx',
|
type: 'local-jsx',
|
||||||
name: 'ultrareview',
|
name: 'ultrareview',
|
||||||
description: `~10–20 min · Finds and verifies bugs in your branch. Runs in Claude Code on the web. See ${CCR_TERMS_URL}`,
|
description: `~10–20 min · Finds and verifies bugs in your branch. Runs in OpenClaude on the web. See ${CCR_TERMS_URL}`,
|
||||||
isEnabled: () => isUltrareviewEnabled(),
|
isEnabled: () => isUltrareviewEnabled(),
|
||||||
load: () => import('./review/ultrareviewCommand.js'),
|
load: () => import('./review/ultrareviewCommand.js'),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ function SessionInfo(t0) {
|
|||||||
if (!remoteSessionUrl) {
|
if (!remoteSessionUrl) {
|
||||||
let t4;
|
let t4;
|
||||||
if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
|
if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
|
||||||
t4 = <Pane><Text color="warning">Not in remote mode. Start with `claude --remote` to use this command.</Text><Text dimColor={true}>(press esc to close)</Text></Pane>;
|
t4 = <Pane><Text color="warning">Not in remote mode. Start with `openclaude --remote` to use this command.</Text><Text dimColor={true}>(press esc to close)</Text></Pane>;
|
||||||
$[4] = t4;
|
$[4] = t4;
|
||||||
} else {
|
} else {
|
||||||
t4 = $[4];
|
t4 = $[4];
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import type { Command } from '../../commands.js'
|
|||||||
const stats = {
|
const stats = {
|
||||||
type: 'local-jsx',
|
type: 'local-jsx',
|
||||||
name: 'stats',
|
name: 'stats',
|
||||||
description: 'Show your Claude Code usage statistics and activity',
|
description: 'Show your OpenClaude usage statistics and activity',
|
||||||
load: () => import('./stats.js'),
|
load: () => import('./stats.js'),
|
||||||
} satisfies Command
|
} satisfies Command
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ const status = {
|
|||||||
type: 'local-jsx',
|
type: 'local-jsx',
|
||||||
name: 'status',
|
name: 'status',
|
||||||
description:
|
description:
|
||||||
'Show Claude Code status including version, model, account, API connectivity, and tool statuses',
|
'Show OpenClaude status including version, model, account, API connectivity, and tool statuses',
|
||||||
immediate: true,
|
immediate: true,
|
||||||
load: () => import('./status.js'),
|
load: () => import('./status.js'),
|
||||||
} satisfies Command
|
} satisfies Command
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import type { Command } from '../commands.js';
|
|||||||
import { AGENT_TOOL_NAME } from '../tools/AgentTool/constants.js';
|
import { AGENT_TOOL_NAME } from '../tools/AgentTool/constants.js';
|
||||||
const statusline = {
|
const statusline = {
|
||||||
type: 'prompt',
|
type: 'prompt',
|
||||||
description: "Set up Claude Code's status line UI",
|
description: "Set up OpenClaude's status line UI",
|
||||||
contentLength: 0,
|
contentLength: 0,
|
||||||
// Dynamic content
|
// Dynamic content
|
||||||
aliases: [],
|
aliases: [],
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import type { Command } from '../../commands.js'
|
|||||||
const stickers = {
|
const stickers = {
|
||||||
type: 'local',
|
type: 'local',
|
||||||
name: 'stickers',
|
name: 'stickers',
|
||||||
description: 'Order Claude Code stickers',
|
description: 'Order OpenClaude stickers',
|
||||||
supportsNonInteractive: false,
|
supportsNonInteractive: false,
|
||||||
load: () => import('./stickers.js'),
|
load: () => import('./stickers.js'),
|
||||||
} satisfies Command
|
} satisfies Command
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { checkStatsigFeatureGate_CACHED_MAY_BE_STALE } from '../../services/anal
|
|||||||
const thinkback = {
|
const thinkback = {
|
||||||
type: 'local-jsx',
|
type: 'local-jsx',
|
||||||
name: 'think-back',
|
name: 'think-back',
|
||||||
description: 'Your 2025 Claude Code Year in Review',
|
description: 'Your 2025 OpenClaude Year in Review',
|
||||||
isEnabled: () =>
|
isEnabled: () =>
|
||||||
checkStatsigFeatureGate_CACHED_MAY_BE_STALE('tengu_thinkback'),
|
checkStatsigFeatureGate_CACHED_MAY_BE_STALE('tengu_thinkback'),
|
||||||
load: () => import('./thinkback.js'),
|
load: () => import('./thinkback.js'),
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ function startDetachedPoll(taskId: string, sessionId: string, url: string, getAp
|
|||||||
ultraplanSessionUrl: undefined
|
ultraplanSessionUrl: undefined
|
||||||
} : prev);
|
} : prev);
|
||||||
enqueuePendingNotification({
|
enqueuePendingNotification({
|
||||||
value: [`Ultraplan approved — executing in Claude Code on the web. Follow along at: ${url}`, '', 'Results will land as a pull request when the remote session finishes. There is nothing to do here.'].join('\n'),
|
value: [`Ultraplan approved — executing in OpenClaude on the web. Follow along at: ${url}`, '', 'Results will land as a pull request when the remote session finishes. There is nothing to do here.'].join('\n'),
|
||||||
mode: 'task-notification'
|
mode: 'task-notification'
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -184,10 +184,10 @@ function startDetachedPoll(taskId: string, sessionId: string, url: string, getAp
|
|||||||
// multi-second teleportToRemote round-trip.
|
// multi-second teleportToRemote round-trip.
|
||||||
function buildLaunchMessage(disconnectedBridge?: boolean): string {
|
function buildLaunchMessage(disconnectedBridge?: boolean): string {
|
||||||
const prefix = disconnectedBridge ? `${REMOTE_CONTROL_DISCONNECTED_MSG} ` : '';
|
const prefix = disconnectedBridge ? `${REMOTE_CONTROL_DISCONNECTED_MSG} ` : '';
|
||||||
return `${DIAMOND_OPEN} ultraplan\n${prefix}Starting Claude Code on the web…`;
|
return `${DIAMOND_OPEN} ultraplan\n${prefix}Starting OpenClaude on the web…`;
|
||||||
}
|
}
|
||||||
function buildSessionReadyMessage(url: string): string {
|
function buildSessionReadyMessage(url: string): string {
|
||||||
return `${DIAMOND_OPEN} ultraplan · Monitor progress in Claude Code on the web ${url}\nYou can continue working — when the ${DIAMOND_OPEN} fills, press ↓ to view results`;
|
return `${DIAMOND_OPEN} ultraplan · Monitor progress in OpenClaude on the web ${url}\nYou can continue working — when the ${DIAMOND_OPEN} fills, press ↓ to view results`;
|
||||||
}
|
}
|
||||||
function buildAlreadyActiveMessage(url: string | undefined): string {
|
function buildAlreadyActiveMessage(url: string | undefined): string {
|
||||||
return url ? `ultraplan: already polling. Open ${url} to check status, or wait for the plan to land here.` : 'ultraplan: already launching. Please wait for the session to start.';
|
return url ? `ultraplan: already polling. Open ${url} to check status, or wait for the plan to land here.` : 'ultraplan: already launching. Please wait for the session to start.';
|
||||||
@@ -272,7 +272,7 @@ export async function launchUltraplan(opts: {
|
|||||||
return [
|
return [
|
||||||
// Rendered via <Markdown>; raw <message> is tokenized as HTML
|
// Rendered via <Markdown>; raw <message> is tokenized as HTML
|
||||||
// and dropped. Backslash-escape the brackets.
|
// and dropped. Backslash-escape the brackets.
|
||||||
'Usage: /ultraplan \\<prompt\\>, or include "ultraplan" anywhere', 'in your prompt', '', 'Advanced multi-agent plan mode with our most powerful model', '(Opus). Runs in Claude Code on the web. When the plan is ready,', 'you can execute it in the web session or send it back here.', 'Terminal stays free while the remote plans.', 'Requires /login.', '', `Terms: ${CCR_TERMS_URL}`].join('\n');
|
'Usage: /ultraplan \\<prompt\\>, or include "ultraplan" anywhere', 'in your prompt', '', 'Advanced multi-agent plan mode with our most powerful model', '(Opus). Runs in OpenClaude on the web. When the plan is ready,', 'you can execute it in the web session or send it back here.', 'Terminal stays free while the remote plans.', 'Requires /login.', '', `Terms: ${CCR_TERMS_URL}`].join('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set synchronously before the detached flow to prevent duplicate launches
|
// Set synchronously before the detached flow to prevent duplicate launches
|
||||||
@@ -461,7 +461,7 @@ const call: LocalJSXCommandCall = async (onDone, context, args) => {
|
|||||||
export default {
|
export default {
|
||||||
type: 'local-jsx',
|
type: 'local-jsx',
|
||||||
name: 'ultraplan',
|
name: 'ultraplan',
|
||||||
description: `~10–30 min · Claude Code on the web drafts an advanced plan you can edit and approve. See ${CCR_TERMS_URL}`,
|
description: `~10–30 min · OpenClaude on the web drafts an advanced plan you can edit and approve. See ${CCR_TERMS_URL}`,
|
||||||
argumentHint: '<prompt>',
|
argumentHint: '<prompt>',
|
||||||
isEnabled: () => "external" === 'ant',
|
isEnabled: () => "external" === 'ant',
|
||||||
load: () => Promise.resolve({
|
load: () => Promise.resolve({
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ export function ClaudeInChromeOnboarding(t0) {
|
|||||||
}
|
}
|
||||||
let t5;
|
let t5;
|
||||||
if ($[6] !== t4) {
|
if ($[6] !== t4) {
|
||||||
t5 = <Text>Claude in Chrome works with the Chrome extension to let you control your browser directly from Claude Code. You can navigate websites, fill forms, capture screenshots, record GIFs, and debug with console logs and network requests.{t4}</Text>;
|
t5 = <Text>Claude in Chrome works with the Chrome extension to let you control your browser directly from OpenClaude. You can navigate websites, fill forms, capture screenshots, record GIFs, and debug with console logs and network requests.{t4}</Text>;
|
||||||
$[6] = t4;
|
$[6] = t4;
|
||||||
$[7] = t5;
|
$[7] = t5;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -262,7 +262,7 @@ export function ConsoleOAuthFlow({
|
|||||||
state: 'success'
|
state: 'success'
|
||||||
});
|
});
|
||||||
void sendNotification({
|
void sendNotification({
|
||||||
message: 'Claude Code login successful',
|
message: 'OpenClaude login successful',
|
||||||
notificationType: 'auth_success'
|
notificationType: 'auth_success'
|
||||||
}, terminal);
|
}, terminal);
|
||||||
}
|
}
|
||||||
@@ -384,7 +384,7 @@ function OAuthStatusMessage({
|
|||||||
case 'idle': {
|
case 'idle': {
|
||||||
const promptText =
|
const promptText =
|
||||||
startingMessage ||
|
startingMessage ||
|
||||||
'Claude Code can be used with your Claude subscription or billed based on API usage through your Console account.'
|
'OpenClaude can be used with your Claude subscription or billed based on API usage through your Console account.'
|
||||||
|
|
||||||
const loginOptions = [
|
const loginOptions = [
|
||||||
{
|
{
|
||||||
@@ -512,7 +512,7 @@ function OAuthStatusMessage({
|
|||||||
<Box flexDirection="column" gap={1}>
|
<Box flexDirection="column" gap={1}>
|
||||||
<Box>
|
<Box>
|
||||||
<Spinner />
|
<Spinner />
|
||||||
<Text>Creating API key for Claude Code…</Text>
|
<Text>Creating API key for OpenClaude…</Text>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ export function DesktopUpsellStartup(t0) {
|
|||||||
let t3;
|
let t3;
|
||||||
if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
|
if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
|
||||||
t3 = {
|
t3 = {
|
||||||
label: "Open in Claude Code Desktop",
|
label: "Open in Claude desktop app",
|
||||||
value: "try" as const
|
value: "try" as const
|
||||||
};
|
};
|
||||||
$[5] = t3;
|
$[5] = t3;
|
||||||
@@ -120,7 +120,7 @@ export function DesktopUpsellStartup(t0) {
|
|||||||
const options = t5;
|
const options = t5;
|
||||||
let t6;
|
let t6;
|
||||||
if ($[8] === Symbol.for("react.memo_cache_sentinel")) {
|
if ($[8] === Symbol.for("react.memo_cache_sentinel")) {
|
||||||
t6 = <Box marginBottom={1}><Text>Same Claude Code with visual diffs, live app preview, parallel sessions, and more.</Text></Box>;
|
t6 = <Box marginBottom={1}><Text>Use OpenClaude in the Claude desktop app for visual diffs, live app preview, parallel sessions, and more.</Text></Box>;
|
||||||
$[8] = t6;
|
$[8] = t6;
|
||||||
} else {
|
} else {
|
||||||
t6 = $[8];
|
t6 = $[8];
|
||||||
@@ -135,7 +135,7 @@ export function DesktopUpsellStartup(t0) {
|
|||||||
}
|
}
|
||||||
let t8;
|
let t8;
|
||||||
if ($[11] !== handleSelect || $[12] !== t7) {
|
if ($[11] !== handleSelect || $[12] !== t7) {
|
||||||
t8 = <PermissionDialog title="Try Claude Code Desktop"><Box flexDirection="column" paddingX={2} paddingY={1}>{t6}<Select options={options} onChange={handleSelect} onCancel={t7} /></Box></PermissionDialog>;
|
t8 = <PermissionDialog title="Try the Claude desktop app"><Box flexDirection="column" paddingX={2} paddingY={1}>{t6}<Select options={options} onChange={handleSelect} onCancel={t7} /></Box></PermissionDialog>;
|
||||||
$[11] = handleSelect;
|
$[11] = handleSelect;
|
||||||
$[12] = t7;
|
$[12] = t7;
|
||||||
$[13] = t8;
|
$[13] = t8;
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ export function HelpV2(t0) {
|
|||||||
const t5 = insideModal ? undefined : maxHeight;
|
const t5 = insideModal ? undefined : maxHeight;
|
||||||
let t6;
|
let t6;
|
||||||
if ($[31] !== tabs) {
|
if ($[31] !== tabs) {
|
||||||
t6 = <Tabs title={false ? "/help" : `Claude Code v${MACRO.VERSION}`} color="professionalBlue" defaultTab="general">{tabs}</Tabs>;
|
t6 = <Tabs title={false ? "/help" : `OpenClaude v${MACRO.VERSION}`} color="professionalBlue" defaultTab="general">{tabs}</Tabs>;
|
||||||
$[31] = tabs;
|
$[31] = tabs;
|
||||||
$[32] = t6;
|
$[32] = t6;
|
||||||
} else {
|
} else {
|
||||||
@@ -146,7 +146,7 @@ export function HelpV2(t0) {
|
|||||||
}
|
}
|
||||||
let t7;
|
let t7;
|
||||||
if ($[33] === Symbol.for("react.memo_cache_sentinel")) {
|
if ($[33] === Symbol.for("react.memo_cache_sentinel")) {
|
||||||
t7 = <Box marginTop={1}><Text>For more help:{" "}<Link url="https://code.claude.com/docs/en/overview" /></Text></Box>;
|
t7 = <Box marginTop={1}><Text>For more help:{" "}<Link url="https://github.com/Gitlawb/openclaude" /></Text></Box>;
|
||||||
$[33] = t7;
|
$[33] = t7;
|
||||||
} else {
|
} else {
|
||||||
t7 = $[33];
|
t7 = $[33];
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ export function IdeOnboardingDialog(t0) {
|
|||||||
}
|
}
|
||||||
let t6;
|
let t6;
|
||||||
if ($[8] !== ideName) {
|
if ($[8] !== ideName) {
|
||||||
t6 = <>{t5}<Text>Welcome to Claude Code for {ideName}</Text></>;
|
t6 = <>{t5}<Text>Welcome to OpenClaude for {ideName}</Text></>;
|
||||||
$[8] = ideName;
|
$[8] = ideName;
|
||||||
$[9] = t6;
|
$[9] = t6;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ export function ChannelsNotice() {
|
|||||||
}
|
}
|
||||||
let t2;
|
let t2;
|
||||||
if ($[24] !== flag) {
|
if ($[24] !== flag) {
|
||||||
t2 = <Text dimColor={true}>Experimental · inbound messages will be pushed into this session, this carries prompt injection risks. Restart Claude Code without {flag} to disable.</Text>;
|
t2 = <Text dimColor={true}>Experimental · inbound messages will be pushed into this session, this carries prompt injection risks. Restart OpenClaude without {flag} to disable.</Text>;
|
||||||
$[24] = flag;
|
$[24] = flag;
|
||||||
$[25] = t2;
|
$[25] = t2;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -250,8 +250,8 @@ export function LogoV2() {
|
|||||||
}
|
}
|
||||||
const layoutMode = getLayoutMode(columns);
|
const layoutMode = getLayoutMode(columns);
|
||||||
const userTheme = resolveThemeSetting(getGlobalConfig().theme);
|
const userTheme = resolveThemeSetting(getGlobalConfig().theme);
|
||||||
const borderTitle = ` ${color("text", userTheme)("Open Claude")} ${color("inactive", userTheme)(`v${version}`)} `;
|
const borderTitle = ` ${color("text", userTheme)("OpenClaude")} ${color("inactive", userTheme)(`v${version}`)} `;
|
||||||
const compactBorderTitle = color("text", userTheme)(" Open Claude ");
|
const compactBorderTitle = color("text", userTheme)(" OpenClaude ");
|
||||||
if (layoutMode === "compact") {
|
if (layoutMode === "compact") {
|
||||||
let welcomeMessage = formatWelcomeMessage(username);
|
let welcomeMessage = formatWelcomeMessage(username);
|
||||||
if (stringWidth(welcomeMessage) > columns - 4) {
|
if (stringWidth(welcomeMessage) > columns - 4) {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export function WelcomeV2() {
|
|||||||
if (env.terminal === "Apple_Terminal") {
|
if (env.terminal === "Apple_Terminal") {
|
||||||
let t0;
|
let t0;
|
||||||
if ($[0] !== theme) {
|
if ($[0] !== theme) {
|
||||||
t0 = <AppleTerminalWelcomeV2 theme={theme} welcomeMessage="Welcome to Claude Code" />;
|
t0 = <AppleTerminalWelcomeV2 theme={theme} welcomeMessage="Welcome to OpenClaude" />;
|
||||||
$[0] = theme;
|
$[0] = theme;
|
||||||
$[1] = t0;
|
$[1] = t0;
|
||||||
} else {
|
} else {
|
||||||
@@ -28,7 +28,7 @@ export function WelcomeV2() {
|
|||||||
let t7;
|
let t7;
|
||||||
let t8;
|
let t8;
|
||||||
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
|
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
|
||||||
t0 = <Text><Text color="claude">{"Welcome to Open Claude"} </Text><Text dimColor={true}>v{MACRO.DISPLAY_VERSION ?? MACRO.VERSION} </Text></Text>;
|
t0 = <Text><Text color="claude">{"Welcome to OpenClaude"} </Text><Text dimColor={true}>v{MACRO.DISPLAY_VERSION ?? MACRO.VERSION} </Text></Text>;
|
||||||
t1 = <Text>{"\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026"}</Text>;
|
t1 = <Text>{"\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026"}</Text>;
|
||||||
t2 = <Text>{" "}</Text>;
|
t2 = <Text>{" "}</Text>;
|
||||||
t3 = <Text>{" "}</Text>;
|
t3 = <Text>{" "}</Text>;
|
||||||
@@ -113,7 +113,7 @@ export function WelcomeV2() {
|
|||||||
let t5;
|
let t5;
|
||||||
let t6;
|
let t6;
|
||||||
if ($[18] === Symbol.for("react.memo_cache_sentinel")) {
|
if ($[18] === Symbol.for("react.memo_cache_sentinel")) {
|
||||||
t0 = <Text><Text color="claude">{"Welcome to Open Claude"} </Text><Text dimColor={true}>v{MACRO.DISPLAY_VERSION ?? MACRO.VERSION} </Text></Text>;
|
t0 = <Text><Text color="claude">{"Welcome to OpenClaude"} </Text><Text dimColor={true}>v{MACRO.DISPLAY_VERSION ?? MACRO.VERSION} </Text></Text>;
|
||||||
t1 = <Text>{"\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026"}</Text>;
|
t1 = <Text>{"\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026"}</Text>;
|
||||||
t2 = <Text>{" "}</Text>;
|
t2 = <Text>{" "}</Text>;
|
||||||
t3 = <Text>{" * \u2588\u2588\u2588\u2588\u2588\u2593\u2593\u2591 "}</Text>;
|
t3 = <Text>{" * \u2588\u2588\u2588\u2588\u2588\u2593\u2593\u2591 "}</Text>;
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ export function createWhatsNewFeed(releaseNotes: string[]): FeedConfig {
|
|||||||
});
|
});
|
||||||
const emptyMessage = "external" === 'ant' ? 'Unable to fetch latest claude-cli-internal commits' : 'Check /release-notes for recent updates';
|
const emptyMessage = "external" === 'ant' ? 'Unable to fetch latest claude-cli-internal commits' : 'Check /release-notes for recent updates';
|
||||||
return {
|
return {
|
||||||
title: "external" === 'ant' ? "Open Claude Updates [internal-only: Latest CC commits]" : "Open Claude Updates",
|
title: "external" === 'ant' ? "OpenClaude Updates [internal-only: Latest CC commits]" : "OpenClaude Updates",
|
||||||
lines,
|
lines,
|
||||||
footer: lines.length > 0 ? '/release-notes for more' : undefined,
|
footer: lines.length > 0 ? '/release-notes for more' : undefined,
|
||||||
emptyMessage
|
emptyMessage
|
||||||
@@ -60,7 +60,7 @@ export function createProjectOnboardingFeed(steps: Step[]): FeedConfig {
|
|||||||
text: `${checkmark}${text}`
|
text: `${checkmark}${text}`
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
const warningText = getCwd() === homedir() ? 'Note: You have launched claude in your home directory. For the best experience, launch it in a project directory instead.' : undefined;
|
const warningText = getCwd() === homedir() ? 'Note: You have launched openclaude in your home directory. For the best experience, launch it in a project directory instead.' : undefined;
|
||||||
if (warningText) {
|
if (warningText) {
|
||||||
lines.push({
|
lines.push({
|
||||||
text: warningText
|
text: warningText
|
||||||
@@ -73,7 +73,7 @@ export function createProjectOnboardingFeed(steps: Step[]): FeedConfig {
|
|||||||
}
|
}
|
||||||
export function createGuestPassesFeed(): FeedConfig {
|
export function createGuestPassesFeed(): FeedConfig {
|
||||||
const reward = getCachedReferrerReward();
|
const reward = getCachedReferrerReward();
|
||||||
const subtitle = reward ? `Share Open Claude and earn ${formatCreditAmount(reward)} of extra usage` : 'Share Open Claude with friends';
|
const subtitle = reward ? `Share OpenClaude and earn ${formatCreditAmount(reward)} of extra usage` : 'Share OpenClaude with friends';
|
||||||
return {
|
return {
|
||||||
title: '3 guest passes',
|
title: '3 guest passes',
|
||||||
lines: [],
|
lines: [],
|
||||||
|
|||||||
@@ -265,7 +265,7 @@ export function ModelPicker(t0) {
|
|||||||
} else {
|
} else {
|
||||||
t15 = $[41];
|
t15 = $[41];
|
||||||
}
|
}
|
||||||
const t16 = headerText ?? "Switch between Claude models. Applies to this session and future Claude Code sessions. For other/previous model names, specify with --model.";
|
const t16 = headerText ?? "Switch between Claude models. Applies to this session and future OpenClaude sessions. For other/previous model names, specify with --model.";
|
||||||
let t17;
|
let t17;
|
||||||
if ($[42] !== t16) {
|
if ($[42] !== t16) {
|
||||||
t17 = <Text dimColor={true}>{t16}</Text>;
|
t17 = <Text dimColor={true}>{t16}</Text>;
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ export function Onboarding({
|
|||||||
steps.push({
|
steps.push({
|
||||||
id: 'terminal-setup',
|
id: 'terminal-setup',
|
||||||
component: <Box flexDirection="column" gap={1} paddingLeft={1}>
|
component: <Box flexDirection="column" gap={1} paddingLeft={1}>
|
||||||
<Text bold>Use Claude Code's terminal setup?</Text>
|
<Text bold>Use OpenClaude's terminal setup?</Text>
|
||||||
<Box flexDirection="column" width={70} gap={1}>
|
<Box flexDirection="column" width={70} gap={1}>
|
||||||
<Text>
|
<Text>
|
||||||
For the optimal coding experience, enable the recommended settings
|
For the optimal coding experience, enable the recommended settings
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ export function OutputStylePicker(t0) {
|
|||||||
const t6 = !isStandaloneCommand;
|
const t6 = !isStandaloneCommand;
|
||||||
let t7;
|
let t7;
|
||||||
if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
|
if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
|
||||||
t7 = <Box marginTop={1}><Text dimColor={true}>This changes how Claude Code communicates with you</Text></Box>;
|
t7 = <Box marginTop={1}><Text dimColor={true}>This changes how OpenClaude communicates with you</Text></Box>;
|
||||||
$[5] = t7;
|
$[5] = t7;
|
||||||
} else {
|
} else {
|
||||||
t7 = $[5];
|
t7 = $[5];
|
||||||
|
|||||||
@@ -773,7 +773,7 @@ function PromptInput({
|
|||||||
if (feature('ULTRAPLAN') && ultraplanTriggers.length) {
|
if (feature('ULTRAPLAN') && ultraplanTriggers.length) {
|
||||||
addNotification({
|
addNotification({
|
||||||
key: 'ultraplan-active',
|
key: 'ultraplan-active',
|
||||||
text: 'This prompt will launch an ultraplan session in Claude Code on the web',
|
text: 'This prompt will launch an ultraplan session in OpenClaude on the web',
|
||||||
priority: 'immediate',
|
priority: 'immediate',
|
||||||
timeoutMs: 5000
|
timeoutMs: 5000
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -119,17 +119,17 @@ export function ResumeTask({
|
|||||||
return <Box flexDirection="column" padding={1}>
|
return <Box flexDirection="column" padding={1}>
|
||||||
<Box flexDirection="row">
|
<Box flexDirection="row">
|
||||||
<Spinner />
|
<Spinner />
|
||||||
<Text bold>Loading Claude Code sessions…</Text>
|
<Text bold>Loading OpenClaude sessions…</Text>
|
||||||
</Box>
|
</Box>
|
||||||
<Text dimColor>
|
<Text dimColor>
|
||||||
{retrying ? 'Retrying…' : 'Fetching your Claude Code sessions…'}
|
{retrying ? 'Retrying…' : 'Fetching your OpenClaude sessions…'}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>;
|
</Box>;
|
||||||
}
|
}
|
||||||
if (loadErrorType) {
|
if (loadErrorType) {
|
||||||
return <Box flexDirection="column" padding={1}>
|
return <Box flexDirection="column" padding={1}>
|
||||||
<Text bold color="error">
|
<Text bold color="error">
|
||||||
Error loading Claude Code sessions
|
Error loading OpenClaude sessions
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
{renderErrorSpecificGuidance(loadErrorType)}
|
{renderErrorSpecificGuidance(loadErrorType)}
|
||||||
@@ -143,7 +143,7 @@ export function ResumeTask({
|
|||||||
if (sessions.length === 0) {
|
if (sessions.length === 0) {
|
||||||
return <Box flexDirection="column" padding={1}>
|
return <Box flexDirection="column" padding={1}>
|
||||||
<Text bold>
|
<Text bold>
|
||||||
No Claude Code sessions found
|
No OpenClaude sessions found
|
||||||
{currentRepo && <Text> for {currentRepo}</Text>}
|
{currentRepo && <Text> for {currentRepo}</Text>}
|
||||||
</Text>
|
</Text>
|
||||||
<Box marginTop={1}>
|
<Box marginTop={1}>
|
||||||
@@ -261,7 +261,7 @@ function renderErrorSpecificGuidance(errorType: LoadErrorType): React.ReactNode
|
|||||||
</Box>;
|
</Box>;
|
||||||
case 'other':
|
case 'other':
|
||||||
return <Box marginY={1} flexDirection="row">
|
return <Box marginY={1} flexDirection="row">
|
||||||
<Text dimColor>Sorry, Claude Code encountered an error</Text>
|
<Text dimColor>Sorry, OpenClaude encountered an error</Text>
|
||||||
</Box>;
|
</Box>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ export function Stats(t0) {
|
|||||||
const allTimePromise = t1;
|
const allTimePromise = t1;
|
||||||
let t2;
|
let t2;
|
||||||
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
|
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
|
||||||
t2 = <Box marginTop={1}><Spinner /><Text> Loading your Claude Code stats…</Text></Box>;
|
t2 = <Box marginTop={1}><Spinner /><Text> Loading your OpenClaude stats…</Text></Box>;
|
||||||
$[1] = t2;
|
$[1] = t2;
|
||||||
} else {
|
} else {
|
||||||
t2 = $[1];
|
t2 = $[1];
|
||||||
@@ -242,7 +242,7 @@ function StatsContent(t0) {
|
|||||||
if (allTimeResult.type === "empty") {
|
if (allTimeResult.type === "empty") {
|
||||||
let t7;
|
let t7;
|
||||||
if ($[15] === Symbol.for("react.memo_cache_sentinel")) {
|
if ($[15] === Symbol.for("react.memo_cache_sentinel")) {
|
||||||
t7 = <Box marginTop={1}><Text color="warning">No stats available yet. Start using Claude Code!</Text></Box>;
|
t7 = <Box marginTop={1}><Text color="warning">No stats available yet. Start using OpenClaude!</Text></Box>;
|
||||||
$[15] = t7;
|
$[15] = t7;
|
||||||
} else {
|
} else {
|
||||||
t7 = $[15];
|
t7 = $[15];
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ export function TeleportRepoMismatchDialog(t0) {
|
|||||||
const options = t2;
|
const options = t2;
|
||||||
let t3;
|
let t3;
|
||||||
if ($[8] !== availablePaths.length || $[9] !== errorMessage || $[10] !== handleChange || $[11] !== options || $[12] !== targetRepo || $[13] !== validating) {
|
if ($[8] !== availablePaths.length || $[9] !== errorMessage || $[10] !== handleChange || $[11] !== options || $[12] !== targetRepo || $[13] !== validating) {
|
||||||
t3 = availablePaths.length > 0 ? <><Box flexDirection="column" gap={1}>{errorMessage && <Text color="error">{errorMessage}</Text>}<Text>Open Claude Code in <Text bold={true}>{targetRepo}</Text>:</Text></Box>{validating ? <Box><Spinner /><Text> Validating repository…</Text></Box> : <Select options={options} onChange={value_0 => void handleChange(value_0)} />}</> : <Box flexDirection="column" gap={1}>{errorMessage && <Text color="error">{errorMessage}</Text>}<Text dimColor={true}>Run claude --teleport from a checkout of {targetRepo}</Text></Box>;
|
t3 = availablePaths.length > 0 ? <><Box flexDirection="column" gap={1}>{errorMessage && <Text color="error">{errorMessage}</Text>}<Text>Open OpenClaude in <Text bold={true}>{targetRepo}</Text>:</Text></Box>{validating ? <Box><Spinner /><Text> Validating repository…</Text></Box> : <Select options={options} onChange={value_0 => void handleChange(value_0)} />}</> : <Box flexDirection="column" gap={1}>{errorMessage && <Text color="error">{errorMessage}</Text>}<Text dimColor={true}>Run openclaude --teleport from a checkout of {targetRepo}</Text></Box>;
|
||||||
$[8] = availablePaths.length;
|
$[8] = availablePaths.length;
|
||||||
$[9] = errorMessage;
|
$[9] = errorMessage;
|
||||||
$[10] = handleChange;
|
$[10] = handleChange;
|
||||||
|
|||||||
@@ -206,7 +206,7 @@ export function TrustDialog(t0) {
|
|||||||
if ($[20] === Symbol.for("react.memo_cache_sentinel")) {
|
if ($[20] === Symbol.for("react.memo_cache_sentinel")) {
|
||||||
t16 = <Text bold={true}>{getFsImplementation().cwd()}</Text>;
|
t16 = <Text bold={true}>{getFsImplementation().cwd()}</Text>;
|
||||||
t17 = <Text>Quick safety check: Is this a project you created or one you trust? (Like your own code, a well-known open source project, or work from your team). If not, take a moment to review what{"'"}s in this folder first.</Text>;
|
t17 = <Text>Quick safety check: Is this a project you created or one you trust? (Like your own code, a well-known open source project, or work from your team). If not, take a moment to review what{"'"}s in this folder first.</Text>;
|
||||||
t18 = <Text>Claude Code{"'"}ll be able to read, edit, and execute files here.</Text>;
|
t18 = <Text>OpenClaude{"'"}ll be able to read, edit, and execute files here.</Text>;
|
||||||
$[20] = t16;
|
$[20] = t16;
|
||||||
$[21] = t17;
|
$[21] = t17;
|
||||||
$[22] = t18;
|
$[22] = t18;
|
||||||
|
|||||||
@@ -254,7 +254,7 @@ function ElicitationFormDialog({
|
|||||||
// Text fields are always in edit mode when focused — no Enter-to-edit step.
|
// Text fields are always in edit mode when focused — no Enter-to-edit step.
|
||||||
const isEditingTextField = currentFieldIsText && !focusedButton;
|
const isEditingTextField = currentFieldIsText && !focusedButton;
|
||||||
useRegisterOverlay('elicitation');
|
useRegisterOverlay('elicitation');
|
||||||
useNotifyAfterTimeout('Claude Code needs your input', 'elicitation_dialog');
|
useNotifyAfterTimeout('OpenClaude needs your input', 'elicitation_dialog');
|
||||||
|
|
||||||
// Sync textInputValue when the focused field changes
|
// Sync textInputValue when the focused field changes
|
||||||
const syncTextInput = useCallback((fieldIndex: number | undefined) => {
|
const syncTextInput = useCallback((fieldIndex: number | undefined) => {
|
||||||
@@ -1004,7 +1004,7 @@ function ElicitationURLDialog({
|
|||||||
const phaseRef = useRef<'prompt' | 'waiting'>('prompt');
|
const phaseRef = useRef<'prompt' | 'waiting'>('prompt');
|
||||||
const [focusedButton, setFocusedButton] = useState<'accept' | 'decline' | 'open' | 'action' | 'cancel'>('accept');
|
const [focusedButton, setFocusedButton] = useState<'accept' | 'decline' | 'open' | 'action' | 'cancel'>('accept');
|
||||||
const showCancel = waitingState?.showCancel ?? false;
|
const showCancel = waitingState?.showCancel ?? false;
|
||||||
useNotifyAfterTimeout('Claude Code needs your input', 'elicitation_url_dialog');
|
useNotifyAfterTimeout('OpenClaude needs your input', 'elicitation_url_dialog');
|
||||||
useRegisterOverlay('elicitation-url');
|
useRegisterOverlay('elicitation-url');
|
||||||
|
|
||||||
// Keep refs in sync for use in abort handler (avoids re-registering listener)
|
// Keep refs in sync for use in abort handler (avoids re-registering listener)
|
||||||
|
|||||||
@@ -102,9 +102,9 @@ export function MCPRemoteServerMenu({
|
|||||||
if (success) {
|
if (success) {
|
||||||
onComplete?.(`Authentication successful. Connected to ${server.name}.`);
|
onComplete?.(`Authentication successful. Connected to ${server.name}.`);
|
||||||
} else if (result.client.type === 'needs-auth') {
|
} else if (result.client.type === 'needs-auth') {
|
||||||
onComplete?.('Authentication successful, but server still requires authentication. You may need to manually restart Claude Code.');
|
onComplete?.('Authentication successful, but server still requires authentication. You may need to manually restart OpenClaude.');
|
||||||
} else {
|
} else {
|
||||||
onComplete?.('Authentication successful, but server reconnection failed. You may need to manually restart Claude Code for the changes to take effect.');
|
onComplete?.('Authentication successful, but server reconnection failed. You may need to manually restart OpenClaude for the changes to take effect.');
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logEvent('tengu_claudeai_mcp_auth_completed', {
|
logEvent('tengu_claudeai_mcp_auth_completed', {
|
||||||
@@ -281,11 +281,11 @@ export function MCPRemoteServerMenu({
|
|||||||
const message = isEffectivelyAuthenticated ? `Authentication successful. Reconnected to ${server.name}.` : `Authentication successful. Connected to ${server.name}.`;
|
const message = isEffectivelyAuthenticated ? `Authentication successful. Reconnected to ${server.name}.` : `Authentication successful. Connected to ${server.name}.`;
|
||||||
onComplete?.(message);
|
onComplete?.(message);
|
||||||
} else if (result_0.client.type === 'needs-auth') {
|
} else if (result_0.client.type === 'needs-auth') {
|
||||||
onComplete?.('Authentication successful, but server still requires authentication. You may need to manually restart Claude Code.');
|
onComplete?.('Authentication successful, but server still requires authentication. You may need to manually restart OpenClaude.');
|
||||||
} else {
|
} else {
|
||||||
// result.client.type === 'failed'
|
// result.client.type === 'failed'
|
||||||
logMCPDebug(server.name, `Reconnection failed after authentication`);
|
logMCPDebug(server.name, `Reconnection failed after authentication`);
|
||||||
onComplete?.('Authentication successful, but server reconnection failed. You may need to manually restart Claude Code for the changes to take effect.');
|
onComplete?.('Authentication successful, but server reconnection failed. You may need to manually restart OpenClaude for the changes to take effect.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (err_1) {
|
} catch (err_1) {
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ export function MCPSettings(t0) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (servers.length === 0 && agentMcpServers.length === 0) {
|
if (servers.length === 0 && agentMcpServers.length === 0) {
|
||||||
onComplete("No MCP servers configured. Please run /doctor if this is unexpected. Otherwise, run `claude mcp --help` or visit https://code.claude.com/docs/en/mcp to learn more.");
|
onComplete("No MCP servers configured. Please run /doctor if this is unexpected. Otherwise, run `openclaude mcp --help` or visit https://github.com/Gitlawb/openclaude to learn more.");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
t8 = [servers.length, filteredClients.length, agentMcpServers.length, onComplete];
|
t8 = [servers.length, filteredClients.length, agentMcpServers.length, onComplete];
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ function ComputerUseTccPanel(t0) {
|
|||||||
}
|
}
|
||||||
let t7;
|
let t7;
|
||||||
if ($[15] === Symbol.for("react.memo_cache_sentinel")) {
|
if ($[15] === Symbol.for("react.memo_cache_sentinel")) {
|
||||||
t7 = <Text dimColor={true}>Grant the missing permissions in System Settings, then select "Try again". macOS may require you to restart Claude Code after granting Screen Recording.</Text>;
|
t7 = <Text dimColor={true}>Grant the missing permissions in System Settings, then select "Try again". macOS may require you to restart OpenClaude after granting Screen Recording.</Text>;
|
||||||
$[15] = t7;
|
$[15] = t7;
|
||||||
} else {
|
} else {
|
||||||
t7 = $[15];
|
t7 = $[15];
|
||||||
|
|||||||
@@ -730,7 +730,7 @@ export function buildPlanApprovalOptions({
|
|||||||
});
|
});
|
||||||
if (showUltraplan) {
|
if (showUltraplan) {
|
||||||
options.push({
|
options.push({
|
||||||
label: 'No, refine with Ultraplan on Claude Code on the web',
|
label: 'No, refine with Ultraplan on OpenClaude on the web',
|
||||||
value: 'ultraplan'
|
value: 'ultraplan'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -128,18 +128,18 @@ export type ToolUseConfirm<Input extends AnyObject = AnyObject> = {
|
|||||||
function getNotificationMessage(toolUseConfirm: ToolUseConfirm): string {
|
function getNotificationMessage(toolUseConfirm: ToolUseConfirm): string {
|
||||||
const toolName = toolUseConfirm.tool.userFacingName(toolUseConfirm.input as never);
|
const toolName = toolUseConfirm.tool.userFacingName(toolUseConfirm.input as never);
|
||||||
if (toolUseConfirm.tool === ExitPlanModeV2Tool) {
|
if (toolUseConfirm.tool === ExitPlanModeV2Tool) {
|
||||||
return 'Claude Code needs your approval for the plan';
|
return 'OpenClaude needs your approval for the plan';
|
||||||
}
|
}
|
||||||
if (toolUseConfirm.tool === EnterPlanModeTool) {
|
if (toolUseConfirm.tool === EnterPlanModeTool) {
|
||||||
return 'Claude Code wants to enter plan mode';
|
return 'OpenClaude wants to enter plan mode';
|
||||||
}
|
}
|
||||||
if (feature('REVIEW_ARTIFACT') && toolUseConfirm.tool === ReviewArtifactTool) {
|
if (feature('REVIEW_ARTIFACT') && toolUseConfirm.tool === ReviewArtifactTool) {
|
||||||
return 'Claude needs your approval for a review artifact';
|
return 'OpenClaude needs your approval for a review artifact';
|
||||||
}
|
}
|
||||||
if (!toolName || toolName.trim() === '') {
|
if (!toolName || toolName.trim() === '') {
|
||||||
return 'Claude Code needs your attention';
|
return 'OpenClaude needs your attention';
|
||||||
}
|
}
|
||||||
return `Claude needs your permission to use ${toolName}`;
|
return `OpenClaude needs your permission to use ${toolName}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Move this to Tool.renderPermissionRequest
|
// TODO: Move this to Tool.renderPermissionRequest
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ function PermissionDescription() {
|
|||||||
const $ = _c(1);
|
const $ = _c(1);
|
||||||
let t0;
|
let t0;
|
||||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||||
t0 = <Text dimColor={true}>Claude Code will be able to read files in this directory and make edits when auto-accept edits is on.</Text>;
|
t0 = <Text dimColor={true}>OpenClaude will be able to read files in this directory and make edits when auto-accept edits is on.</Text>;
|
||||||
$[0] = t0;
|
$[0] = t0;
|
||||||
} else {
|
} else {
|
||||||
t0 = $[0];
|
t0 = $[0];
|
||||||
|
|||||||
@@ -388,9 +388,9 @@ function PermissionRulesTab(t0) {
|
|||||||
let t8;
|
let t8;
|
||||||
if ($[10] === Symbol.for("react.memo_cache_sentinel")) {
|
if ($[10] === Symbol.for("react.memo_cache_sentinel")) {
|
||||||
t8 = {
|
t8 = {
|
||||||
allow: "Claude Code won't ask before using allowed tools.",
|
allow: "OpenClaude won't ask before using allowed tools.",
|
||||||
ask: "Claude Code will always ask for confirmation before using these tools.",
|
ask: "OpenClaude will always ask for confirmation before using these tools.",
|
||||||
deny: "Claude Code will always reject requests to use denied tools."
|
deny: "OpenClaude will always reject requests to use denied tools."
|
||||||
};
|
};
|
||||||
$[10] = t8;
|
$[10] = t8;
|
||||||
} else {
|
} else {
|
||||||
@@ -1098,7 +1098,7 @@ export function PermissionRuleList(t0) {
|
|||||||
}
|
}
|
||||||
let t28;
|
let t28;
|
||||||
if ($[89] === Symbol.for("react.memo_cache_sentinel")) {
|
if ($[89] === Symbol.for("react.memo_cache_sentinel")) {
|
||||||
t28 = <Text>Claude Code can read files in the workspace, and make edits when auto-accept edits is on.</Text>;
|
t28 = <Text>OpenClaude can read files in the workspace, and make edits when auto-accept edits is on.</Text>;
|
||||||
$[89] = t28;
|
$[89] = t28;
|
||||||
} else {
|
} else {
|
||||||
t28 = $[89];
|
t28 = $[89];
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ export function RemoveWorkspaceDirectory(t0) {
|
|||||||
}
|
}
|
||||||
let t4;
|
let t4;
|
||||||
if ($[10] === Symbol.for("react.memo_cache_sentinel")) {
|
if ($[10] === Symbol.for("react.memo_cache_sentinel")) {
|
||||||
t4 = <Text>Claude Code will no longer have access to files in this directory.</Text>;
|
t4 = <Text>OpenClaude will no longer have access to files in this directory.</Text>;
|
||||||
$[10] = t4;
|
$[10] = t4;
|
||||||
} else {
|
} else {
|
||||||
t4 = $[10];
|
t4 = $[10];
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ type Props = {
|
|||||||
export function formatToolUseSummary(name: string, input: unknown): string {
|
export function formatToolUseSummary(name: string, input: unknown): string {
|
||||||
// plan_ready phase is only reached via ExitPlanMode tool
|
// plan_ready phase is only reached via ExitPlanMode tool
|
||||||
if (name === EXIT_PLAN_MODE_V2_TOOL_NAME) {
|
if (name === EXIT_PLAN_MODE_V2_TOOL_NAME) {
|
||||||
return 'Review the plan in Claude Code on the web';
|
return 'Review the plan in OpenClaude on the web';
|
||||||
}
|
}
|
||||||
if (!input || typeof input !== 'object') return name;
|
if (!input || typeof input !== 'object') return name;
|
||||||
// AskUserQuestion: show the question text as a CTA, not the tool name.
|
// AskUserQuestion: show the question text as a CTA, not the tool name.
|
||||||
@@ -168,7 +168,7 @@ function UltraplanSessionDetail(t0) {
|
|||||||
}
|
}
|
||||||
let t7;
|
let t7;
|
||||||
if ($[12] === Symbol.for("react.memo_cache_sentinel")) {
|
if ($[12] === Symbol.for("react.memo_cache_sentinel")) {
|
||||||
t7 = <Text dimColor={true}>This will terminate the Claude Code on the web session.</Text>;
|
t7 = <Text dimColor={true}>This will terminate the OpenClaude on the web session.</Text>;
|
||||||
$[12] = t7;
|
$[12] = t7;
|
||||||
} else {
|
} else {
|
||||||
t7 = $[12];
|
t7 = $[12];
|
||||||
@@ -311,7 +311,7 @@ function UltraplanSessionDetail(t0) {
|
|||||||
let t19;
|
let t19;
|
||||||
if ($[47] === Symbol.for("react.memo_cache_sentinel")) {
|
if ($[47] === Symbol.for("react.memo_cache_sentinel")) {
|
||||||
t19 = {
|
t19 = {
|
||||||
label: "Review in Claude Code on the web",
|
label: "Review in OpenClaude on the web",
|
||||||
value: "open" as const
|
value: "open" as const
|
||||||
};
|
};
|
||||||
$[47] = t19;
|
$[47] = t19;
|
||||||
@@ -595,13 +595,13 @@ function ReviewSessionDetail(t0) {
|
|||||||
let t3;
|
let t3;
|
||||||
if ($[11] !== completed || $[12] !== onKill || $[13] !== running) {
|
if ($[11] !== completed || $[12] !== onKill || $[13] !== running) {
|
||||||
t3 = completed ? [{
|
t3 = completed ? [{
|
||||||
label: "Open in Claude Code on the web",
|
label: "Open in OpenClaude on the web",
|
||||||
value: "open"
|
value: "open"
|
||||||
}, {
|
}, {
|
||||||
label: "Dismiss",
|
label: "Dismiss",
|
||||||
value: "dismiss"
|
value: "dismiss"
|
||||||
}] : [{
|
}] : [{
|
||||||
label: "Open in Claude Code on the web",
|
label: "Open in OpenClaude on the web",
|
||||||
value: "open"
|
value: "open"
|
||||||
}, ...(onKill && running ? [{
|
}, ...(onKill && running ? [{
|
||||||
label: "Stop ultrareview",
|
label: "Stop ultrareview",
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ async function main(): Promise<void> {
|
|||||||
if (args.length === 1 && (args[0] === '--version' || args[0] === '-v' || args[0] === '-V')) {
|
if (args.length === 1 && (args[0] === '--version' || args[0] === '-v' || args[0] === '-V')) {
|
||||||
// MACRO.VERSION is inlined at build time
|
// MACRO.VERSION is inlined at build time
|
||||||
// biome-ignore lint/suspicious/noConsole:: intentional console output
|
// biome-ignore lint/suspicious/noConsole:: intentional console output
|
||||||
console.log(`${MACRO.DISPLAY_VERSION ?? MACRO.VERSION} (Open Claude)`);
|
console.log(`${MACRO.DISPLAY_VERSION ?? MACRO.VERSION} (OpenClaude)`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { isInBundledMode } from 'src/utils/bundledMode.js';
|
|||||||
import { getCurrentInstallationType } from 'src/utils/doctorDiagnostic.js';
|
import { getCurrentInstallationType } from 'src/utils/doctorDiagnostic.js';
|
||||||
import { isEnvTruthy } from 'src/utils/envUtils.js';
|
import { isEnvTruthy } from 'src/utils/envUtils.js';
|
||||||
import { useStartupNotification } from './useStartupNotification.js';
|
import { useStartupNotification } from './useStartupNotification.js';
|
||||||
const NPM_DEPRECATION_MESSAGE = 'Claude Code has switched from npm to native installer. Run `claude install` or see https://docs.anthropic.com/en/docs/claude-code/getting-started for more options.';
|
const NPM_DEPRECATION_MESSAGE = 'OpenClaude has switched from npm to the native installer. Run `openclaude install` or see https://github.com/Gitlawb/openclaude#quick-start for more options.';
|
||||||
export function useNpmDeprecationNotification() {
|
export function useNpmDeprecationNotification() {
|
||||||
useStartupNotification(_temp);
|
useStartupNotification(_temp);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ export function useDiffInIDE({
|
|||||||
|
|
||||||
const sha = useMemo(() => randomUUID().slice(0, 6), [])
|
const sha = useMemo(() => randomUUID().slice(0, 6), [])
|
||||||
const tabName = useMemo(
|
const tabName = useMemo(
|
||||||
() => `✻ [Claude Code] ${basename(filePath)} (${sha}) ⧉`,
|
() => `✻ [OpenClaude] ${basename(filePath)} (${sha}) ⧉`,
|
||||||
[filePath, sha],
|
[filePath, sha],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -501,7 +501,7 @@ export function useVoice({
|
|||||||
} else if (!hadAudioSignal) {
|
} else if (!hadAudioSignal) {
|
||||||
// Distinguish silent mic (capture issue) from speech not recognized.
|
// Distinguish silent mic (capture issue) from speech not recognized.
|
||||||
onErrorRef.current?.(
|
onErrorRef.current?.(
|
||||||
'No audio detected from microphone. Check that the correct input device is selected and that Claude Code has microphone access.',
|
'No audio detected from microphone. Check that the correct input device is selected and that OpenClaude has microphone access.',
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
onErrorRef.current?.('No speech detected.')
|
onErrorRef.current?.('No speech detected.')
|
||||||
|
|||||||
38
src/main.tsx
38
src/main.tsx
@@ -785,7 +785,7 @@ export async function main() {
|
|||||||
// Headless (-p) mode is not supported with SSH in v1 — reject early
|
// Headless (-p) mode is not supported with SSH in v1 — reject early
|
||||||
// so the flag doesn't silently cause local execution.
|
// so the flag doesn't silently cause local execution.
|
||||||
if (rest.includes('-p') || rest.includes('--print')) {
|
if (rest.includes('-p') || rest.includes('--print')) {
|
||||||
process.stderr.write('Error: headless (-p/--print) mode is not supported with claude ssh\n');
|
process.stderr.write('Error: headless (-p/--print) mode is not supported with openclaude ssh\n');
|
||||||
gracefulShutdownSync(1);
|
gracefulShutdownSync(1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -959,7 +959,7 @@ async function run(): Promise<CommanderCommand> {
|
|||||||
}
|
}
|
||||||
profileCheckpoint('preAction_after_settings_sync');
|
profileCheckpoint('preAction_after_settings_sync');
|
||||||
});
|
});
|
||||||
program.name('claude').description(`Claude Code - starts an interactive session by default, use -p/--print for non-interactive output`).argument('[prompt]', 'Your prompt', String)
|
program.name('openclaude').description(`OpenClaude - starts an interactive session by default, use -p/--print for non-interactive output`).argument('[prompt]', 'Your prompt', String)
|
||||||
// Subcommands inherit helpOption via commander's copyInheritedSettings —
|
// Subcommands inherit helpOption via commander's copyInheritedSettings —
|
||||||
// setting it once here covers mcp, plugin, auth, and all other subcommands.
|
// setting it once here covers mcp, plugin, auth, and all other subcommands.
|
||||||
.helpOption('-h, --help', 'Display help for command').option('-d, --debug [filter]', 'Enable debug mode with optional category filtering (e.g., "api,hooks" or "!1p,!file")', (_value: string | true) => {
|
.helpOption('-h, --help', 'Display help for command').option('-d, --debug [filter]', 'Enable debug mode with optional category filtering (e.g., "api,hooks" or "!1p,!file")', (_value: string | true) => {
|
||||||
@@ -1013,7 +1013,7 @@ async function run(): Promise<CommanderCommand> {
|
|||||||
if (prompt === 'code') {
|
if (prompt === 'code') {
|
||||||
logEvent('tengu_code_prompt_ignored', {});
|
logEvent('tengu_code_prompt_ignored', {});
|
||||||
// biome-ignore lint/suspicious/noConsole:: intentional console output
|
// biome-ignore lint/suspicious/noConsole:: intentional console output
|
||||||
console.warn(chalk.yellow('Tip: You can launch Claude Code with just `claude`'));
|
console.warn(chalk.yellow('Tip: You can launch OpenClaude with just `openclaude`'));
|
||||||
prompt = undefined;
|
prompt = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3275,7 +3275,7 @@ async function run(): Promise<CommanderCommand> {
|
|||||||
}
|
}
|
||||||
// The daemon needs a few seconds to spin up its worker and
|
// The daemon needs a few seconds to spin up its worker and
|
||||||
// establish a bridge session before discovery will find it.
|
// establish a bridge session before discovery will find it.
|
||||||
return await exitWithMessage(root, `Assistant installed in ${installedDir}. The daemon is starting up — run \`claude assistant\` again in a few seconds to connect.`, {
|
return await exitWithMessage(root, `Assistant installed in ${installedDir}. The daemon is starting up — run \`openclaude assistant\` again in a few seconds to connect.`, {
|
||||||
exitCode: 0,
|
exitCode: 0,
|
||||||
beforeExit: () => gracefulShutdown(0)
|
beforeExit: () => gracefulShutdown(0)
|
||||||
});
|
});
|
||||||
@@ -3401,7 +3401,7 @@ async function run(): Promise<CommanderCommand> {
|
|||||||
// Check if TUI mode is enabled - description is only optional in TUI mode
|
// Check if TUI mode is enabled - description is only optional in TUI mode
|
||||||
const isRemoteTuiEnabled = getFeatureValue_CACHED_MAY_BE_STALE('tengu_remote_backend', false);
|
const isRemoteTuiEnabled = getFeatureValue_CACHED_MAY_BE_STALE('tengu_remote_backend', false);
|
||||||
if (!isRemoteTuiEnabled && !hasInitialPrompt) {
|
if (!isRemoteTuiEnabled && !hasInitialPrompt) {
|
||||||
return await exitWithError(root, 'Error: --remote requires a description.\nUsage: claude --remote "your task description"', () => gracefulShutdown(1));
|
return await exitWithError(root, 'Error: --remote requires a description.\nUsage: openclaude --remote "your task description"', () => gracefulShutdown(1));
|
||||||
}
|
}
|
||||||
logEvent('tengu_remote_create_session', {
|
logEvent('tengu_remote_create_session', {
|
||||||
has_initial_prompt: String(hasInitialPrompt) as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS
|
has_initial_prompt: String(hasInitialPrompt) as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS
|
||||||
@@ -3425,7 +3425,7 @@ async function run(): Promise<CommanderCommand> {
|
|||||||
// Original behavior: print session info and exit
|
// Original behavior: print session info and exit
|
||||||
process.stdout.write(`Created remote session: ${createdSession.title}\n`);
|
process.stdout.write(`Created remote session: ${createdSession.title}\n`);
|
||||||
process.stdout.write(`View: ${getRemoteSessionUrl(createdSession.id)}?m=0\n`);
|
process.stdout.write(`View: ${getRemoteSessionUrl(createdSession.id)}?m=0\n`);
|
||||||
process.stdout.write(`Resume with: claude --teleport ${createdSession.id}\n`);
|
process.stdout.write(`Resume with: openclaude --teleport ${createdSession.id}\n`);
|
||||||
await gracefulShutdown(0);
|
await gracefulShutdown(0);
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
}
|
}
|
||||||
@@ -3537,7 +3537,7 @@ async function run(): Promise<CommanderCommand> {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// No known paths - show original error
|
// No known paths - show original error
|
||||||
throw new TeleportOperationError(`You must run claude --teleport ${teleport} from a checkout of ${sessionRepo}.`, chalk.red(`You must run claude --teleport ${teleport} from a checkout of ${chalk.bold(sessionRepo)}.\n`));
|
throw new TeleportOperationError(`You must run openclaude --teleport ${teleport} from a checkout of ${sessionRepo}.`, chalk.red(`You must run openclaude --teleport ${teleport} from a checkout of ${chalk.bold(sessionRepo)}.\n`));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (repoValidation.status === 'error') {
|
} else if (repoValidation.status === 'error') {
|
||||||
@@ -3789,7 +3789,7 @@ async function run(): Promise<CommanderCommand> {
|
|||||||
pendingHookMessages
|
pendingHookMessages
|
||||||
}, renderAndRun);
|
}, renderAndRun);
|
||||||
}
|
}
|
||||||
}).version(`${MACRO.DISPLAY_VERSION ?? MACRO.VERSION} (Open Claude)`, '-v, --version', 'Output the version number');
|
}).version(`${MACRO.DISPLAY_VERSION ?? MACRO.VERSION} (OpenClaude)`, '-v, --version', 'Output the version number');
|
||||||
|
|
||||||
// Worktree flags
|
// Worktree flags
|
||||||
program.option('-w, --worktree [name]', 'Create a new git worktree for this session (optionally specify a name)');
|
program.option('-w, --worktree [name]', 'Create a new git worktree for this session (optionally specify a name)');
|
||||||
@@ -3876,7 +3876,7 @@ async function run(): Promise<CommanderCommand> {
|
|||||||
// claude mcp
|
// claude mcp
|
||||||
|
|
||||||
const mcp = program.command('mcp').description('Configure and manage MCP servers').configureHelp(createSortedHelpConfig()).enablePositionalOptions();
|
const mcp = program.command('mcp').description('Configure and manage MCP servers').configureHelp(createSortedHelpConfig()).enablePositionalOptions();
|
||||||
mcp.command('serve').description(`Start the Claude Code MCP server`).option('-d, --debug', 'Enable debug mode', () => true).option('--verbose', 'Override verbose mode setting from config', () => true).action(async ({
|
mcp.command('serve').description(`Start the OpenClaude MCP server`).option('-d, --debug', 'Enable debug mode', () => true).option('--verbose', 'Override verbose mode setting from config', () => true).action(async ({
|
||||||
debug,
|
debug,
|
||||||
verbose
|
verbose
|
||||||
}: {
|
}: {
|
||||||
@@ -3944,7 +3944,7 @@ async function run(): Promise<CommanderCommand> {
|
|||||||
|
|
||||||
// claude server
|
// claude server
|
||||||
if (feature('DIRECT_CONNECT')) {
|
if (feature('DIRECT_CONNECT')) {
|
||||||
program.command('server').description('Start a Claude Code session server').option('--port <number>', 'HTTP port', '0').option('--host <string>', 'Bind address', '0.0.0.0').option('--auth-token <token>', 'Bearer token for auth').option('--unix <path>', 'Listen on a unix domain socket').option('--workspace <dir>', 'Default working directory for sessions that do not specify cwd').option('--idle-timeout <ms>', 'Idle timeout for detached sessions in ms (0 = never expire)', '600000').option('--max-sessions <n>', 'Maximum concurrent sessions (0 = unlimited)', '32').action(async (opts: {
|
program.command('server').description('Start an OpenClaude session server').option('--port <number>', 'HTTP port', '0').option('--host <string>', 'Bind address', '0.0.0.0').option('--auth-token <token>', 'Bearer token for auth').option('--unix <path>', 'Listen on a unix domain socket').option('--workspace <dir>', 'Default working directory for sessions that do not specify cwd').option('--idle-timeout <ms>', 'Idle timeout for detached sessions in ms (0 = never expire)', '600000').option('--max-sessions <n>', 'Maximum concurrent sessions (0 = unlimited)', '32').action(async (opts: {
|
||||||
port: string;
|
port: string;
|
||||||
host: string;
|
host: string;
|
||||||
authToken?: string;
|
authToken?: string;
|
||||||
@@ -3978,7 +3978,7 @@ async function run(): Promise<CommanderCommand> {
|
|||||||
} = await import('./server/lockfile.js');
|
} = await import('./server/lockfile.js');
|
||||||
const existing = await probeRunningServer();
|
const existing = await probeRunningServer();
|
||||||
if (existing) {
|
if (existing) {
|
||||||
process.stderr.write(`A claude server is already running (pid ${existing.pid}) at ${existing.httpUrl}\n`);
|
process.stderr.write(`An OpenClaude server is already running (pid ${existing.pid}) at ${existing.httpUrl}\n`);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
const authToken = opts.authToken ?? `sk-ant-cc-${randomBytes(16).toString('base64url')}`;
|
const authToken = opts.authToken ?? `sk-ant-cc-${randomBytes(16).toString('base64url')}`;
|
||||||
@@ -4028,11 +4028,11 @@ async function run(): Promise<CommanderCommand> {
|
|||||||
// this action it means the argv rewrite didn't fire (e.g. user ran
|
// this action it means the argv rewrite didn't fire (e.g. user ran
|
||||||
// `claude ssh` with no host) — just print usage.
|
// `claude ssh` with no host) — just print usage.
|
||||||
if (feature('SSH_REMOTE')) {
|
if (feature('SSH_REMOTE')) {
|
||||||
program.command('ssh <host> [dir]').description('Run Claude Code on a remote host over SSH. Deploys the binary and ' + 'tunnels API auth back through your local machine — no remote setup needed.').option('--permission-mode <mode>', 'Permission mode for the remote session').option('--dangerously-skip-permissions', 'Skip all permission prompts on the remote (dangerous)').option('--local', 'e2e test mode — spawn the child CLI locally (skip ssh/deploy). ' + 'Exercises the auth proxy and unix-socket plumbing without a remote host.').action(async () => {
|
program.command('ssh <host> [dir]').description('Run OpenClaude on a remote host over SSH. Deploys the binary and ' + 'tunnels API auth back through your local machine — no remote setup needed.').option('--permission-mode <mode>', 'Permission mode for the remote session').option('--dangerously-skip-permissions', 'Skip all permission prompts on the remote (dangerous)').option('--local', 'e2e test mode — spawn the child CLI locally (skip ssh/deploy). ' + 'Exercises the auth proxy and unix-socket plumbing without a remote host.').action(async () => {
|
||||||
// Argv rewriting in main() should have consumed `ssh <host>` before
|
// Argv rewriting in main() should have consumed `ssh <host>` before
|
||||||
// commander runs. Reaching here means host was missing or the
|
// commander runs. Reaching here means host was missing or the
|
||||||
// rewrite predicate didn't match.
|
// rewrite predicate didn't match.
|
||||||
process.stderr.write('Usage: claude ssh <user@host | ssh-config-alias> [dir]\n\n' + "Runs Claude Code on a remote Linux host. You don't need to install\n" + 'anything on the remote or run `claude auth login` there — the binary is\n' + 'deployed over SSH and API auth tunnels back through your local machine.\n');
|
process.stderr.write('Usage: openclaude ssh <user@host | ssh-config-alias> [dir]\n\n' + "Runs OpenClaude on a remote Linux host. You don't need to install\n" + 'anything on the remote or run `openclaude auth login` there — the binary is\n' + 'deployed over SSH and API auth tunnels back through your local machine.\n');
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -4041,7 +4041,7 @@ async function run(): Promise<CommanderCommand> {
|
|||||||
// Interactive mode (without -p) is handled by early argv rewriting in main()
|
// Interactive mode (without -p) is handled by early argv rewriting in main()
|
||||||
// which redirects to the main command with full TUI support.
|
// which redirects to the main command with full TUI support.
|
||||||
if (feature('DIRECT_CONNECT')) {
|
if (feature('DIRECT_CONNECT')) {
|
||||||
program.command('open <cc-url>').description('Connect to a Claude Code server (internal — use cc:// URLs)').option('-p, --print [prompt]', 'Print mode (headless)').option('--output-format <format>', 'Output format: text, json, stream-json', 'text').action(async (ccUrl: string, opts: {
|
program.command('open <cc-url>').description('Connect to an OpenClaude server (internal — use cc:// URLs)').option('-p, --print [prompt]', 'Print mode (headless)').option('--output-format <format>', 'Output format: text, json, stream-json', 'text').action(async (ccUrl: string, opts: {
|
||||||
print?: string | boolean;
|
print?: string | boolean;
|
||||||
outputFormat: string;
|
outputFormat: string;
|
||||||
}) => {
|
}) => {
|
||||||
@@ -4130,7 +4130,7 @@ async function run(): Promise<CommanderCommand> {
|
|||||||
const coworkOption = () => new Option('--cowork', 'Use cowork_plugins directory').hideHelp();
|
const coworkOption = () => new Option('--cowork', 'Use cowork_plugins directory').hideHelp();
|
||||||
|
|
||||||
// Plugin validate command
|
// Plugin validate command
|
||||||
const pluginCmd = program.command('plugin').alias('plugins').description('Manage Claude Code plugins').configureHelp(createSortedHelpConfig());
|
const pluginCmd = program.command('plugin').alias('plugins').description('Manage OpenClaude plugins').configureHelp(createSortedHelpConfig());
|
||||||
pluginCmd.command('validate <path>').description('Validate a plugin or marketplace manifest').addOption(coworkOption()).action(async (manifestPath: string, options: {
|
pluginCmd.command('validate <path>').description('Validate a plugin or marketplace manifest').addOption(coworkOption()).action(async (manifestPath: string, options: {
|
||||||
cowork?: boolean;
|
cowork?: boolean;
|
||||||
}) => {
|
}) => {
|
||||||
@@ -4153,7 +4153,7 @@ async function run(): Promise<CommanderCommand> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Marketplace subcommands
|
// Marketplace subcommands
|
||||||
const marketplaceCmd = pluginCmd.command('marketplace').description('Manage Claude Code marketplaces').configureHelp(createSortedHelpConfig());
|
const marketplaceCmd = pluginCmd.command('marketplace').description('Manage OpenClaude marketplaces').configureHelp(createSortedHelpConfig());
|
||||||
marketplaceCmd.command('add <source>').description('Add a marketplace from a URL, path, or GitHub repo').addOption(coworkOption()).option('--sparse <paths...>', 'Limit checkout to specific directories via git sparse-checkout (for monorepos). Example: --sparse .claude-plugin plugins').option('--scope <scope>', 'Where to declare the marketplace: user (default), project, or local').action(async (source: string, options: {
|
marketplaceCmd.command('add <source>').description('Add a marketplace from a URL, path, or GitHub repo').addOption(coworkOption()).option('--sparse <paths...>', 'Limit checkout to specific directories via git sparse-checkout (for monorepos). Example: --sparse .claude-plugin plugins').option('--scope <scope>', 'Where to declare the marketplace: user (default), project, or local').action(async (source: string, options: {
|
||||||
cowork?: boolean;
|
cowork?: boolean;
|
||||||
sparse?: string[];
|
sparse?: string[];
|
||||||
@@ -4322,13 +4322,13 @@ async function run(): Promise<CommanderCommand> {
|
|||||||
// before commander runs. Reaching here means a root flag came first
|
// before commander runs. Reaching here means a root flag came first
|
||||||
// (e.g. `--debug assistant`) and the position-0 predicate
|
// (e.g. `--debug assistant`) and the position-0 predicate
|
||||||
// didn't match. Print usage like the ssh stub does.
|
// didn't match. Print usage like the ssh stub does.
|
||||||
process.stderr.write('Usage: claude assistant [sessionId]\n\n' + 'Attach the REPL as a viewer client to a running bridge session.\n' + 'Omit sessionId to discover and pick from available sessions.\n');
|
process.stderr.write('Usage: openclaude assistant [sessionId]\n\n' + 'Attach the REPL as a viewer client to a running bridge session.\n' + 'Omit sessionId to discover and pick from available sessions.\n');
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Doctor command - check installation health
|
// Doctor command - check installation health
|
||||||
program.command('doctor').description('Check the health of your Claude Code auto-updater. Note: The workspace trust dialog is skipped and stdio servers from .mcp.json are spawned for health checks. Only use this command in directories you trust.').action(async () => {
|
program.command('doctor').description('Check the health of your OpenClaude auto-updater. Note: The workspace trust dialog is skipped and stdio servers from .mcp.json are spawned for health checks. Only use this command in directories you trust.').action(async () => {
|
||||||
const [{
|
const [{
|
||||||
doctorHandler
|
doctorHandler
|
||||||
}, {
|
}, {
|
||||||
@@ -4377,7 +4377,7 @@ async function run(): Promise<CommanderCommand> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// claude install
|
// claude install
|
||||||
program.command('install [target]').description('Install Claude Code native build. Use [target] to specify version (stable, latest, or specific version)').option('--force', 'Force installation even if already installed').action(async (target: string | undefined, options: {
|
program.command('install [target]').description('Install OpenClaude native build. Use [target] to specify version (stable, latest, or specific version)').option('--force', 'Force installation even if already installed').action(async (target: string | undefined, options: {
|
||||||
force?: boolean;
|
force?: boolean;
|
||||||
}) => {
|
}) => {
|
||||||
const {
|
const {
|
||||||
|
|||||||
@@ -222,7 +222,7 @@ export function Doctor(t0) {
|
|||||||
let t7;
|
let t7;
|
||||||
if ($[11] !== onDone) {
|
if ($[11] !== onDone) {
|
||||||
t7 = () => {
|
t7 = () => {
|
||||||
onDone("Claude Code diagnostics dismissed", {
|
onDone("OpenClaude diagnostics dismissed", {
|
||||||
display: "system"
|
display: "system"
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1136,7 +1136,7 @@ export function REPL({
|
|||||||
// session from mid-conversation context.
|
// session from mid-conversation context.
|
||||||
const haikuTitleAttemptedRef = useRef((initialMessages?.length ?? 0) > 0);
|
const haikuTitleAttemptedRef = useRef((initialMessages?.length ?? 0) > 0);
|
||||||
const agentTitle = mainThreadAgentDefinition?.agentType;
|
const agentTitle = mainThreadAgentDefinition?.agentType;
|
||||||
const terminalTitle = sessionTitle ?? agentTitle ?? haikuTitle ?? 'Open Claude';
|
const terminalTitle = sessionTitle ?? agentTitle ?? haikuTitle ?? 'OpenClaude';
|
||||||
const isWaitingForApproval = toolUseConfirmQueue.length > 0 || promptQueue.length > 0 || pendingWorkerRequest || pendingSandboxRequest;
|
const isWaitingForApproval = toolUseConfirmQueue.length > 0 || promptQueue.length > 0 || pendingWorkerRequest || pendingSandboxRequest;
|
||||||
// Local-jsx commands (like /plugin, /config) show user-facing dialogs that
|
// Local-jsx commands (like /plugin, /config) show user-facing dialogs that
|
||||||
// wait for input. Require jsx != null — if the flag is stuck true but jsx
|
// wait for input. Require jsx != null — if the flag is stuck true but jsx
|
||||||
@@ -4189,7 +4189,7 @@ export function REPL({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleSuspend = () => {
|
const handleSuspend = () => {
|
||||||
// Print suspension instructions
|
// Print suspension instructions
|
||||||
process.stdout.write(`\nClaude Code has been suspended. Run \`fg\` to bring Claude Code back.\nNote: ctrl + z now suspends Claude Code, ctrl + _ undoes input.\n`);
|
process.stdout.write(`\nOpenClaude has been suspended. Run \`fg\` to bring OpenClaude back.\nNote: ctrl + z now suspends OpenClaude, ctrl + _ undoes input.\n`);
|
||||||
};
|
};
|
||||||
const handleResume = () => {
|
const handleResume = () => {
|
||||||
// Force complete component tree replacement instead of terminal clear
|
// Force complete component tree replacement instead of terminal clear
|
||||||
|
|||||||
@@ -302,7 +302,7 @@ export function getRequestTooLargeErrorMessage(): string {
|
|||||||
: `Request too large (${limits}). Double press esc to go back and try with a smaller file.`
|
: `Request too large (${limits}). Double press esc to go back and try with a smaller file.`
|
||||||
}
|
}
|
||||||
export const OAUTH_ORG_NOT_ALLOWED_ERROR_MESSAGE =
|
export const OAUTH_ORG_NOT_ALLOWED_ERROR_MESSAGE =
|
||||||
'Your account does not have access to Claude Code. Please run /login.'
|
'Your account does not have access to OpenClaude. Please run /login.'
|
||||||
|
|
||||||
export function getTokenRevokedErrorMessage(): string {
|
export function getTokenRevokedErrorMessage(): string {
|
||||||
return getIsNonInteractiveSession()
|
return getIsNonInteractiveSession()
|
||||||
@@ -1346,8 +1346,8 @@ export function getErrorMessageIfRefusal(
|
|||||||
: "your provider's acceptable use policy"
|
: "your provider's acceptable use policy"
|
||||||
|
|
||||||
const baseMessage = getIsNonInteractiveSession()
|
const baseMessage = getIsNonInteractiveSession()
|
||||||
? `${API_ERROR_MESSAGE_PREFIX}: Claude Code is unable to respond to this request, which appears to violate our Usage Policy (${usagePolicyUrl}). Try rephrasing the request or attempting a different approach.`
|
? `${API_ERROR_MESSAGE_PREFIX}: OpenClaude is unable to respond to this request, which appears to violate our Usage Policy (${usagePolicyUrl}). Try rephrasing the request or attempting a different approach.`
|
||||||
: `${API_ERROR_MESSAGE_PREFIX}: Claude Code is unable to respond to this request, which appears to violate our Usage Policy (${usagePolicyUrl}). Please double press esc to edit your last message or start a new session for Claude Code to assist with a different task.`
|
: `${API_ERROR_MESSAGE_PREFIX}: OpenClaude is unable to respond to this request, which appears to violate our Usage Policy (${usagePolicyUrl}). Please double press esc to edit your last message or start a new session for OpenClaude to assist with a different task.`
|
||||||
|
|
||||||
const modelSuggestion =
|
const modelSuggestion =
|
||||||
model !== 'claude-sonnet-4-20250514'
|
model !== 'claude-sonnet-4-20250514'
|
||||||
|
|||||||
@@ -343,13 +343,13 @@ export async function checkGroveForNonInteractive(): Promise<void> {
|
|||||||
if (config === null || config.notice_is_grace_period) {
|
if (config === null || config.notice_is_grace_period) {
|
||||||
// Grace period is still active - show informational message and continue
|
// Grace period is still active - show informational message and continue
|
||||||
writeToStderr(
|
writeToStderr(
|
||||||
'\nAn update to our Consumer Terms and Privacy Policy will take effect on October 8, 2025. Run `claude` to review the updated terms.\n\n',
|
'\nAn update to our Consumer Terms and Privacy Policy will take effect on October 8, 2025. Run `openclaude` to review the updated terms.\n\n',
|
||||||
)
|
)
|
||||||
await markGroveNoticeViewed()
|
await markGroveNoticeViewed()
|
||||||
} else {
|
} else {
|
||||||
// Grace period has ended - show error message and exit
|
// Grace period has ended - show error message and exit
|
||||||
writeToStderr(
|
writeToStderr(
|
||||||
'\n[ACTION REQUIRED] An update to our Consumer Terms and Privacy Policy has taken effect on October 8, 2025. You must run `claude` to review the updated terms.\n\n',
|
'\n[ACTION REQUIRED] An update to our Consumer Terms and Privacy Policy has taken effect on October 8, 2025. You must run `openclaude` to review the updated terms.\n\n',
|
||||||
)
|
)
|
||||||
await gracefulShutdown(1)
|
await gracefulShutdown(1)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1209,7 +1209,7 @@ export async function performMCPOAuthFlow(
|
|||||||
|
|
||||||
res.writeHead(200, { 'Content-Type': 'text/html' })
|
res.writeHead(200, { 'Content-Type': 'text/html' })
|
||||||
res.end(
|
res.end(
|
||||||
`<h1>Authentication Successful</h1><p>You can close this window. Return to Claude Code.</p>`,
|
`<h1>Authentication Successful</h1><p>You can close this window. Return to OpenClaude.</p>`,
|
||||||
)
|
)
|
||||||
cleanup()
|
cleanup()
|
||||||
resolveOnce(result.code)
|
resolveOnce(result.code)
|
||||||
|
|||||||
@@ -1001,10 +1001,12 @@ export const connectToServer = memoize(
|
|||||||
|
|
||||||
const client = new Client(
|
const client = new Client(
|
||||||
{
|
{
|
||||||
|
// name stays 'claude-code' for compatibility with MCP servers that
|
||||||
|
// gate features on the upstream client identifier.
|
||||||
name: 'claude-code',
|
name: 'claude-code',
|
||||||
title: 'Open Claude',
|
title: 'OpenClaude',
|
||||||
version: MACRO.VERSION ?? 'unknown',
|
version: MACRO.VERSION ?? 'unknown',
|
||||||
description: "Anthropic's agentic coding tool",
|
description: 'OpenClaude — coding-agent CLI for any LLM provider',
|
||||||
websiteUrl: PRODUCT_URL,
|
websiteUrl: PRODUCT_URL,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -3329,10 +3331,12 @@ export async function setupSdkMcpClients(
|
|||||||
|
|
||||||
const client = new Client(
|
const client = new Client(
|
||||||
{
|
{
|
||||||
|
// name stays 'claude-code' for compatibility with MCP servers that
|
||||||
|
// gate features on the upstream client identifier.
|
||||||
name: 'claude-code',
|
name: 'claude-code',
|
||||||
title: 'Open Claude',
|
title: 'OpenClaude',
|
||||||
version: MACRO.VERSION ?? 'unknown',
|
version: MACRO.VERSION ?? 'unknown',
|
||||||
description: "Anthropic's agentic coding tool",
|
description: 'OpenClaude — coding-agent CLI for any LLM provider',
|
||||||
websiteUrl: PRODUCT_URL,
|
websiteUrl: PRODUCT_URL,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ export async function sendNotification(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const DEFAULT_TITLE = 'Open Claude'
|
const DEFAULT_TITLE = 'OpenClaude'
|
||||||
|
|
||||||
async function sendToChannel(
|
async function sendToChannel(
|
||||||
channel: string,
|
channel: string,
|
||||||
|
|||||||
@@ -279,7 +279,7 @@ function getWarningUpsellText(
|
|||||||
|
|
||||||
// Pro/Max users: prompt to upgrade
|
// Pro/Max users: prompt to upgrade
|
||||||
if (subscriptionType === 'pro' || subscriptionType === 'max') {
|
if (subscriptionType === 'pro' || subscriptionType === 'max') {
|
||||||
return '/upgrade to keep using Claude Code'
|
return '/upgrade to keep using OpenClaude'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ const externalTips: Tip[] = [
|
|||||||
{
|
{
|
||||||
id: 'new-user-warmup',
|
id: 'new-user-warmup',
|
||||||
content: async () =>
|
content: async () =>
|
||||||
`Start with small features or bug fixes, tell Claude to propose a plan, and verify its suggested edits`,
|
`Start with small features or bug fixes, tell OpenClaude to propose a plan, and verify its suggested edits`,
|
||||||
cooldownSessions: 3,
|
cooldownSessions: 3,
|
||||||
async isRelevant() {
|
async isRelevant() {
|
||||||
const config = getGlobalConfig()
|
const config = getGlobalConfig()
|
||||||
@@ -142,7 +142,7 @@ const externalTips: Tip[] = [
|
|||||||
{
|
{
|
||||||
id: 'git-worktrees',
|
id: 'git-worktrees',
|
||||||
content: async () =>
|
content: async () =>
|
||||||
'Use git worktrees to run multiple Claude sessions in parallel.',
|
'Use git worktrees to run multiple OpenClaude sessions in parallel.',
|
||||||
cooldownSessions: 10,
|
cooldownSessions: 10,
|
||||||
isRelevant: async () => {
|
isRelevant: async () => {
|
||||||
try {
|
try {
|
||||||
@@ -157,7 +157,7 @@ const externalTips: Tip[] = [
|
|||||||
{
|
{
|
||||||
id: 'color-when-multi-clauding',
|
id: 'color-when-multi-clauding',
|
||||||
content: async () =>
|
content: async () =>
|
||||||
'Running multiple Claude sessions? Use /color and /rename to tell them apart at a glance.',
|
'Running multiple OpenClaude sessions? Use /color and /rename to tell them apart at a glance.',
|
||||||
cooldownSessions: 10,
|
cooldownSessions: 10,
|
||||||
isRelevant: async () => {
|
isRelevant: async () => {
|
||||||
if (getCurrentSessionAgentColor()) return false
|
if (getCurrentSessionAgentColor()) return false
|
||||||
@@ -215,7 +215,7 @@ const externalTips: Tip[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'memory-command',
|
id: 'memory-command',
|
||||||
content: async () => 'Use /memory to view and manage Claude memory',
|
content: async () => 'Use /memory to view and manage OpenClaude memory',
|
||||||
cooldownSessions: 15,
|
cooldownSessions: 15,
|
||||||
async isRelevant() {
|
async isRelevant() {
|
||||||
const config = getGlobalConfig()
|
const config = getGlobalConfig()
|
||||||
@@ -254,7 +254,7 @@ const externalTips: Tip[] = [
|
|||||||
{
|
{
|
||||||
id: 'prompt-queue',
|
id: 'prompt-queue',
|
||||||
content: async () =>
|
content: async () =>
|
||||||
'Hit Enter to queue up additional messages while Claude is working.',
|
'Hit Enter to queue up additional messages while OpenClaude is working.',
|
||||||
cooldownSessions: 5,
|
cooldownSessions: 5,
|
||||||
async isRelevant() {
|
async isRelevant() {
|
||||||
const config = getGlobalConfig()
|
const config = getGlobalConfig()
|
||||||
@@ -264,14 +264,14 @@ const externalTips: Tip[] = [
|
|||||||
{
|
{
|
||||||
id: 'enter-to-steer-in-relatime',
|
id: 'enter-to-steer-in-relatime',
|
||||||
content: async () =>
|
content: async () =>
|
||||||
'Send messages to Claude while it works to steer Claude in real-time',
|
'Send messages to OpenClaude while it works to steer OpenClaude in real-time',
|
||||||
cooldownSessions: 20,
|
cooldownSessions: 20,
|
||||||
isRelevant: async () => true,
|
isRelevant: async () => true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'todo-list',
|
id: 'todo-list',
|
||||||
content: async () =>
|
content: async () =>
|
||||||
'Ask Claude to create a todo list when working on complex tasks to track progress and remain on track',
|
'Ask OpenClaude to create a todo list when working on complex tasks to track progress and remain on track',
|
||||||
cooldownSessions: 20,
|
cooldownSessions: 20,
|
||||||
isRelevant: async () => true,
|
isRelevant: async () => true,
|
||||||
},
|
},
|
||||||
@@ -304,7 +304,7 @@ const externalTips: Tip[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'ide-upsell-external-terminal',
|
id: 'ide-upsell-external-terminal',
|
||||||
content: async () => 'Connect Claude to your IDE · /ide',
|
content: async () => 'Connect OpenClaude to your IDE · /ide',
|
||||||
cooldownSessions: 4,
|
cooldownSessions: 4,
|
||||||
async isRelevant() {
|
async isRelevant() {
|
||||||
if (isSupportedTerminal()) {
|
if (isSupportedTerminal()) {
|
||||||
@@ -324,13 +324,13 @@ const externalTips: Tip[] = [
|
|||||||
{
|
{
|
||||||
id: 'install-github-app',
|
id: 'install-github-app',
|
||||||
content: async () =>
|
content: async () =>
|
||||||
'Run /install-github-app to tag @claude right from your Github issues and PRs',
|
'Run /install-github-app to enable GitHub issue and PR tagging from OpenClaude',
|
||||||
cooldownSessions: 10,
|
cooldownSessions: 10,
|
||||||
isRelevant: async () => !getGlobalConfig().githubActionSetupCount,
|
isRelevant: async () => !getGlobalConfig().githubActionSetupCount,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'install-slack-app',
|
id: 'install-slack-app',
|
||||||
content: async () => 'Run /install-slack-app to use Claude in Slack',
|
content: async () => 'Run /install-slack-app to use OpenClaude in Slack',
|
||||||
cooldownSessions: 10,
|
cooldownSessions: 10,
|
||||||
isRelevant: async () => !getGlobalConfig().slackAppInstallCount,
|
isRelevant: async () => !getGlobalConfig().slackAppInstallCount,
|
||||||
},
|
},
|
||||||
@@ -354,7 +354,7 @@ const externalTips: Tip[] = [
|
|||||||
{
|
{
|
||||||
id: 'paste-images-mac',
|
id: 'paste-images-mac',
|
||||||
content: async () =>
|
content: async () =>
|
||||||
'Paste images into Claude Code using control+v (not cmd+v!)',
|
'Paste images into OpenClaude using control+v (not cmd+v!)',
|
||||||
cooldownSessions: 10,
|
cooldownSessions: 10,
|
||||||
isRelevant: async () => getPlatform() === 'macos',
|
isRelevant: async () => getPlatform() === 'macos',
|
||||||
},
|
},
|
||||||
@@ -375,7 +375,7 @@ const externalTips: Tip[] = [
|
|||||||
{
|
{
|
||||||
id: 'continue',
|
id: 'continue',
|
||||||
content: async () =>
|
content: async () =>
|
||||||
'Run claude --continue or claude --resume to resume a conversation',
|
'Run openclaude --continue or openclaude --resume to resume a conversation',
|
||||||
cooldownSessions: 10,
|
cooldownSessions: 10,
|
||||||
isRelevant: async () => true,
|
isRelevant: async () => true,
|
||||||
},
|
},
|
||||||
@@ -434,7 +434,7 @@ const externalTips: Tip[] = [
|
|||||||
{
|
{
|
||||||
id: 'desktop-app',
|
id: 'desktop-app',
|
||||||
content: async () =>
|
content: async () =>
|
||||||
'Run Claude Code locally or remotely using the Claude desktop app: clau.de/desktop',
|
'Run OpenClaude locally or remotely with /desktop',
|
||||||
cooldownSessions: 15,
|
cooldownSessions: 15,
|
||||||
isRelevant: async () => getPlatform() !== 'linux',
|
isRelevant: async () => getPlatform() !== 'linux',
|
||||||
},
|
},
|
||||||
@@ -442,7 +442,7 @@ const externalTips: Tip[] = [
|
|||||||
id: 'desktop-shortcut',
|
id: 'desktop-shortcut',
|
||||||
content: async ctx => {
|
content: async ctx => {
|
||||||
const blue = color('suggestion', ctx.theme)
|
const blue = color('suggestion', ctx.theme)
|
||||||
return `Continue your session in Claude Code Desktop with ${blue('/desktop')}`
|
return `Continue your session with ${blue('/desktop')}`
|
||||||
},
|
},
|
||||||
cooldownSessions: 15,
|
cooldownSessions: 15,
|
||||||
isRelevant: async () => {
|
isRelevant: async () => {
|
||||||
@@ -456,21 +456,21 @@ const externalTips: Tip[] = [
|
|||||||
{
|
{
|
||||||
id: 'web-app',
|
id: 'web-app',
|
||||||
content: async () =>
|
content: async () =>
|
||||||
'Run tasks in the cloud while you keep coding locally · clau.de/web',
|
'Run tasks in the cloud while you keep coding locally · /web',
|
||||||
cooldownSessions: 15,
|
cooldownSessions: 15,
|
||||||
isRelevant: async () => true,
|
isRelevant: async () => true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'mobile-app',
|
id: 'mobile-app',
|
||||||
content: async () =>
|
content: async () =>
|
||||||
'/mobile to use Claude Code from the Claude app on your phone',
|
'/mobile to continue from your phone',
|
||||||
cooldownSessions: 15,
|
cooldownSessions: 15,
|
||||||
isRelevant: async () => true,
|
isRelevant: async () => true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'opusplan-mode-reminder',
|
id: 'opusplan-mode-reminder',
|
||||||
content: async () =>
|
content: async () =>
|
||||||
`Your default model setting is Opus Plan Mode. Press ${getShortcutDisplay('chat:cycleMode', 'Chat', 'shift+tab')} twice to activate Plan Mode and plan with Claude Opus.`,
|
`Your default model setting is Opus Plan Mode. Press ${getShortcutDisplay('chat:cycleMode', 'Chat', 'shift+tab')} twice to activate Plan Mode and plan with Opus.`,
|
||||||
cooldownSessions: 2,
|
cooldownSessions: 2,
|
||||||
async isRelevant() {
|
async isRelevant() {
|
||||||
const config = getGlobalConfig()
|
const config = getGlobalConfig()
|
||||||
@@ -517,7 +517,7 @@ const externalTips: Tip[] = [
|
|||||||
'off' | 'copy_a' | 'copy_b'
|
'off' | 'copy_a' | 'copy_b'
|
||||||
>('tengu_tide_elm', 'off')
|
>('tengu_tide_elm', 'off')
|
||||||
return variant === 'copy_b'
|
return variant === 'copy_b'
|
||||||
? `Use ${cmd} for better one-shot answers. Claude thinks it through first.`
|
? `Use ${cmd} for better one-shot answers. OpenClaude thinks it through first.`
|
||||||
: `Working on something tricky? ${cmd} gives better first answers`
|
: `Working on something tricky? ${cmd} gives better first answers`
|
||||||
},
|
},
|
||||||
cooldownSessions: 3,
|
cooldownSessions: 3,
|
||||||
@@ -546,8 +546,8 @@ const externalTips: Tip[] = [
|
|||||||
'off' | 'copy_a' | 'copy_b'
|
'off' | 'copy_a' | 'copy_b'
|
||||||
>('tengu_tern_alloy', 'off')
|
>('tengu_tern_alloy', 'off')
|
||||||
return variant === 'copy_b'
|
return variant === 'copy_b'
|
||||||
? `For big tasks, tell Claude to ${blue('use subagents')}. They work in parallel and keep your main thread clean.`
|
? `For big tasks, tell OpenClaude to ${blue('use subagents')}. They work in parallel and keep your main thread clean.`
|
||||||
: `Say ${blue('"fan out subagents"')} and Claude sends a team. Each one digs deep so nothing gets missed.`
|
: `Say ${blue('"fan out subagents"')} and OpenClaude sends a team. Each one digs deep so nothing gets missed.`
|
||||||
},
|
},
|
||||||
cooldownSessions: 3,
|
cooldownSessions: 3,
|
||||||
isRelevant: async () => {
|
isRelevant: async () => {
|
||||||
@@ -589,7 +589,7 @@ const externalTips: Tip[] = [
|
|||||||
const claude = color('claude', ctx.theme)
|
const claude = color('claude', ctx.theme)
|
||||||
const reward = getCachedReferrerReward()
|
const reward = getCachedReferrerReward()
|
||||||
return reward
|
return reward
|
||||||
? `Share Claude Code and earn ${claude(formatCreditAmount(reward))} of extra usage · ${claude('/passes')}`
|
? `Share OpenClaude and earn ${claude(formatCreditAmount(reward))} of extra usage · ${claude('/passes')}`
|
||||||
: `You have free guest passes to share · ${claude('/passes')}`
|
: `You have free guest passes to share · ${claude('/passes')}`
|
||||||
},
|
},
|
||||||
cooldownSessions: 3,
|
cooldownSessions: 3,
|
||||||
|
|||||||
@@ -262,7 +262,7 @@ export async function checkRecordingAvailability(): Promise<RecordingAvailabilit
|
|||||||
return {
|
return {
|
||||||
available: false,
|
available: false,
|
||||||
reason:
|
reason:
|
||||||
'Voice mode requires microphone access, but no audio device is available in this environment.\n\nTo use voice mode, run Claude Code locally instead.',
|
'Voice mode requires microphone access, but no audio device is available in this environment.\n\nTo use voice mode, run OpenClaude locally instead.',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -282,7 +282,7 @@ export async function checkRecordingAvailability(): Promise<RecordingAvailabilit
|
|||||||
}
|
}
|
||||||
|
|
||||||
const wslNoAudioReason =
|
const wslNoAudioReason =
|
||||||
'Voice mode could not access an audio device in WSL.\n\nWSL2 with WSLg (Windows 11) provides audio via PulseAudio — if you are on Windows 10 or WSL1, run Claude Code in native Windows instead.'
|
'Voice mode could not access an audio device in WSL.\n\nWSL2 with WSLg (Windows 11) provides audio via PulseAudio — if you are on Windows 10 or WSL1, run OpenClaude in native Windows instead.'
|
||||||
|
|
||||||
// On Linux (including WSL), probe arecord. hasCommand() is insufficient:
|
// On Linux (including WSL), probe arecord. hasCommand() is insufficient:
|
||||||
// the binary can exist while the device open() fails (WSL1, Win10-WSL2,
|
// the binary can exist while the device open() fails (WSL1, Win10-WSL2,
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ export async function setup(
|
|||||||
// biome-ignore lint/suspicious/noConsole:: intentional console output
|
// biome-ignore lint/suspicious/noConsole:: intentional console output
|
||||||
console.error(
|
console.error(
|
||||||
chalk.bold.red(
|
chalk.bold.red(
|
||||||
'Error: Claude Code requires Node.js version 18 or higher.',
|
'Error: OpenClaude requires Node.js version 18 or higher.',
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ export function registerDebugSkill(): void {
|
|||||||
|
|
||||||
Debug logging was OFF for this session until now. Nothing prior to this /debug invocation was captured.
|
Debug logging was OFF for this session until now. Nothing prior to this /debug invocation was captured.
|
||||||
|
|
||||||
Tell the user that debug logging is now active at \`${debugLogPath}\`, ask them to reproduce the issue, then re-read the log. If they can't reproduce, they can also restart with \`claude --debug\` to capture logs from startup.
|
Tell the user that debug logging is now active at \`${debugLogPath}\`, ask them to reproduce the issue, then re-read the log. If they can't reproduce, they can also restart with \`openclaude --debug\` to capture logs from startup.
|
||||||
`
|
`
|
||||||
|
|
||||||
const prompt = `# Debug Skill
|
const prompt = `# Debug Skill
|
||||||
|
|||||||
@@ -439,7 +439,7 @@ If a hook isn't running:
|
|||||||
3. **Check the matcher** - Does it match the tool name? (e.g., "Bash", "Write", "Edit")
|
3. **Check the matcher** - Does it match the tool name? (e.g., "Bash", "Write", "Edit")
|
||||||
4. **Check hook type** - Is it "command", "prompt", or "agent"?
|
4. **Check hook type** - Is it "command", "prompt", or "agent"?
|
||||||
5. **Test the command** - Run the hook command manually to see if it works
|
5. **Test the command** - Run the hook command manually to see if it works
|
||||||
6. **Use --debug** - Run \`claude --debug\` to see hook execution logs
|
6. **Use --debug** - Run \`openclaude --debug\` to see hook execution logs
|
||||||
`
|
`
|
||||||
|
|
||||||
export function registerUpdateConfigSkill(): void {
|
export function registerUpdateConfigSkill(): void {
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import { makeSecondaryModelPrompt } from './prompt.js'
|
|||||||
// Custom error classes for domain blocking
|
// Custom error classes for domain blocking
|
||||||
class DomainBlockedError extends Error {
|
class DomainBlockedError extends Error {
|
||||||
constructor(domain: string) {
|
constructor(domain: string) {
|
||||||
super(`Claude Code is unable to fetch from ${domain}`)
|
super(`OpenClaude is unable to fetch from ${domain}`)
|
||||||
this.name = 'DomainBlockedError'
|
this.name = 'DomainBlockedError'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1989,8 +1989,8 @@ export async function validateForceLoginOrg(): Promise<OrgValidationResult> {
|
|||||||
`Unable to verify organization for the current authentication token.\n` +
|
`Unable to verify organization for the current authentication token.\n` +
|
||||||
`This machine requires organization ${requiredOrgUuid} but the profile could not be fetched.\n` +
|
`This machine requires organization ${requiredOrgUuid} but the profile could not be fetched.\n` +
|
||||||
`This may be a network error, or the token may lack the user:profile scope required for\n` +
|
`This may be a network error, or the token may lack the user:profile scope required for\n` +
|
||||||
`verification (tokens from 'claude setup-token' do not include this scope).\n` +
|
`verification (tokens from 'openclaude setup-token' do not include this scope).\n` +
|
||||||
`Try again, or obtain a full-scope token via 'claude auth login'.`,
|
`Try again, or obtain a full-scope token via 'openclaude auth login'.`,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2020,7 +2020,7 @@ export async function validateForceLoginOrg(): Promise<OrgValidationResult> {
|
|||||||
message:
|
message:
|
||||||
`Your authentication token belongs to organization ${tokenOrgUuid},\n` +
|
`Your authentication token belongs to organization ${tokenOrgUuid},\n` +
|
||||||
`but this machine requires organization ${requiredOrgUuid}.\n\n` +
|
`but this machine requires organization ${requiredOrgUuid}.\n\n` +
|
||||||
`Please log in with the correct organization: claude auth login`,
|
`Please log in with the correct organization: openclaude auth login`,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ export function calculateOptimalLeftWidth(
|
|||||||
*/
|
*/
|
||||||
export function formatWelcomeMessage(username: string | null): string {
|
export function formatWelcomeMessage(username: string | null): string {
|
||||||
if (!username || username.length > MAX_USERNAME_LENGTH) {
|
if (!username || username.length > MAX_USERNAME_LENGTH) {
|
||||||
return 'Welcome to Open Claude'
|
return 'Welcome to OpenClaude'
|
||||||
}
|
}
|
||||||
return `Welcome back, ${username}`
|
return `Welcome back, ${username}`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ export async function generateSessionTitle(
|
|||||||
|
|
||||||
// Fallback: When using 3P providers without a compatible schema,
|
// Fallback: When using 3P providers without a compatible schema,
|
||||||
// default to the application name.
|
// default to the application name.
|
||||||
return 'Open Claude'
|
return 'OpenClaude'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ const apiKeyConflictNotice: StatusNoticeDefinition = {
|
|||||||
<Text color="warning">{figures.warning}</Text>
|
<Text color="warning">{figures.warning}</Text>
|
||||||
<Text color="warning">
|
<Text color="warning">
|
||||||
Auth conflict: Using {apiKeySource} instead of Anthropic Console key.
|
Auth conflict: Using {apiKeySource} instead of Anthropic Console key.
|
||||||
Either unset {apiKeySource}, or run `claude /logout`.
|
Either unset {apiKeySource}, or run `openclaude /logout`.
|
||||||
</Text>
|
</Text>
|
||||||
</Box>;
|
</Box>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -466,7 +466,7 @@ export async function teleportResumeCodeSession(sessionId: string, onProgress?:
|
|||||||
});
|
});
|
||||||
// Include host for GHE users so they know which instance the repo is on
|
// Include host for GHE users so they know which instance the repo is on
|
||||||
const notInRepoDisplay = repoValidation.sessionHost && repoValidation.sessionHost.toLowerCase() !== 'github.com' ? `${repoValidation.sessionHost}/${repoValidation.sessionRepo}` : repoValidation.sessionRepo;
|
const notInRepoDisplay = repoValidation.sessionHost && repoValidation.sessionHost.toLowerCase() !== 'github.com' ? `${repoValidation.sessionHost}/${repoValidation.sessionRepo}` : repoValidation.sessionRepo;
|
||||||
throw new TeleportOperationError(`You must run claude --teleport ${sessionId} from a checkout of ${notInRepoDisplay}.`, chalk.red(`You must run claude --teleport ${sessionId} from a checkout of ${chalk.bold(notInRepoDisplay)}.\n`));
|
throw new TeleportOperationError(`You must run openclaude --teleport ${sessionId} from a checkout of ${notInRepoDisplay}.`, chalk.red(`You must run openclaude --teleport ${sessionId} from a checkout of ${chalk.bold(notInRepoDisplay)}.\n`));
|
||||||
}
|
}
|
||||||
case 'mismatch':
|
case 'mismatch':
|
||||||
{
|
{
|
||||||
@@ -478,7 +478,7 @@ export async function teleportResumeCodeSession(sessionId: string, onProgress?:
|
|||||||
const hostsDiffer = repoValidation.sessionHost && repoValidation.currentHost && repoValidation.sessionHost.replace(/:\d+$/, '').toLowerCase() !== repoValidation.currentHost.replace(/:\d+$/, '').toLowerCase();
|
const hostsDiffer = repoValidation.sessionHost && repoValidation.currentHost && repoValidation.sessionHost.replace(/:\d+$/, '').toLowerCase() !== repoValidation.currentHost.replace(/:\d+$/, '').toLowerCase();
|
||||||
const sessionDisplay = hostsDiffer ? `${repoValidation.sessionHost}/${repoValidation.sessionRepo}` : repoValidation.sessionRepo;
|
const sessionDisplay = hostsDiffer ? `${repoValidation.sessionHost}/${repoValidation.sessionRepo}` : repoValidation.sessionRepo;
|
||||||
const currentDisplay = hostsDiffer ? `${repoValidation.currentHost}/${repoValidation.currentRepo}` : repoValidation.currentRepo;
|
const currentDisplay = hostsDiffer ? `${repoValidation.currentHost}/${repoValidation.currentRepo}` : repoValidation.currentRepo;
|
||||||
throw new TeleportOperationError(`You must run claude --teleport ${sessionId} from a checkout of ${sessionDisplay}.\nThis repo is ${currentDisplay}.`, chalk.red(`You must run claude --teleport ${sessionId} from a checkout of ${chalk.bold(sessionDisplay)}.\nThis repo is ${chalk.bold(currentDisplay)}.\n`));
|
throw new TeleportOperationError(`You must run openclaude --teleport ${sessionId} from a checkout of ${sessionDisplay}.\nThis repo is ${currentDisplay}.`, chalk.red(`You must run openclaude --teleport ${sessionId} from a checkout of ${chalk.bold(sessionDisplay)}.\nThis repo is ${chalk.bold(currentDisplay)}.\n`));
|
||||||
}
|
}
|
||||||
case 'error':
|
case 'error':
|
||||||
throw new TeleportOperationError(repoValidation.errorMessage || 'Failed to validate session repository', chalk.red(`Error: ${repoValidation.errorMessage || 'Failed to validate session repository'}\n`));
|
throw new TeleportOperationError(repoValidation.errorMessage || 'Failed to validate session repository', chalk.red(`Error: ${repoValidation.errorMessage || 'Failed to validate session repository'}\n`));
|
||||||
|
|||||||
Reference in New Issue
Block a user