login fix + removed claude references

This commit is contained in:
x1xhlol
2026-04-01 18:02:41 +02:00
Unverified
parent b7c47216c7
commit cd9537eddf
9 changed files with 29 additions and 46 deletions

View File

@@ -1,6 +1,6 @@
{ {
"name": "better-clawd", "name": "better-clawd",
"version": "0.1.1", "version": "0.1.4",
"description": "Claude Code, but better.", "description": "Claude Code, but better.",
"type": "module", "type": "module",
"bin": { "bin": {

View File

@@ -13,7 +13,7 @@ const result = await Bun.build({
minify: false, minify: false,
naming: 'cli.mjs', naming: 'cli.mjs',
define: { define: {
'MACRO.VERSION': JSON.stringify('99.0.0'), 'MACRO.VERSION': JSON.stringify(version),
'MACRO.DISPLAY_VERSION': JSON.stringify(version), 'MACRO.DISPLAY_VERSION': JSON.stringify(version),
'MACRO.BUILD_TIME': JSON.stringify(new Date().toISOString()), 'MACRO.BUILD_TIME': JSON.stringify(new Date().toISOString()),
'MACRO.ISSUES_EXPLAINER': JSON.stringify( 'MACRO.ISSUES_EXPLAINER': JSON.stringify(

View File

@@ -2,6 +2,7 @@ import { c as _c } from "react/compiler-runtime";
import React, { useCallback, useEffect, useMemo, useState } from 'react'; import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, logEvent } from 'src/services/analytics/index.js'; import { type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, logEvent } from 'src/services/analytics/index.js';
import { setupTerminal, shouldOfferTerminalSetup } from '../commands/terminalSetup/terminalSetup.js'; import { setupTerminal, shouldOfferTerminalSetup } from '../commands/terminalSetup/terminalSetup.js';
import { Login } from '../commands/login/login.js';
import { useExitOnCtrlCDWithKeybindings } from '../hooks/useExitOnCtrlCDWithKeybindings.js'; import { useExitOnCtrlCDWithKeybindings } from '../hooks/useExitOnCtrlCDWithKeybindings.js';
import { Box, Link, Newline, Text, useTheme } from '../ink.js'; import { Box, Link, Newline, Text, useTheme } from '../ink.js';
import { useKeybindings } from '../keybindings/useKeybinding.js'; import { useKeybindings } from '../keybindings/useKeybinding.js';
@@ -13,7 +14,6 @@ import { isRunningOnHomespace } from '../utils/envUtils.js';
import { PreflightStep } from '../utils/preflightChecks.js'; import { PreflightStep } from '../utils/preflightChecks.js';
import type { ThemeSetting } from '../utils/theme.js'; import type { ThemeSetting } from '../utils/theme.js';
import { ApproveApiKey } from './ApproveApiKey.js'; import { ApproveApiKey } from './ApproveApiKey.js';
import { ConsoleOAuthFlow } from './ConsoleOAuthFlow.js';
import { Select } from './CustomSelect/select.js'; import { Select } from './CustomSelect/select.js';
import { WelcomeV2 } from './LogoV2/WelcomeV2.js'; import { WelcomeV2 } from './LogoV2/WelcomeV2.js';
import { PressEnterToContinue } from './PressEnterToContinue.js'; import { PressEnterToContinue } from './PressEnterToContinue.js';
@@ -134,7 +134,13 @@ export function Onboarding({
steps.push({ steps.push({
id: 'oauth', id: 'oauth',
component: <SkippableStep skip={skipOAuth} onSkip={goToNextStep}> component: <SkippableStep skip={skipOAuth} onSkip={goToNextStep}>
<ConsoleOAuthFlow onDone={goToNextStep} /> <Login
startingMessage="Choose which provider you want Better-Clawd to use for setup."
onDone={success => {
if (success) {
goToNextStep();
}
}} />
</SkippableStep> </SkippableStep>
}); });
} }

View File

@@ -25,10 +25,7 @@ export const CLAUDE_AI_STAGING_BASE_URL = ANTHROPIC_APP_STAGING_BASE_URL
export const CLAUDE_AI_LOCAL_BASE_URL = ANTHROPIC_APP_LOCAL_BASE_URL export const CLAUDE_AI_LOCAL_BASE_URL = ANTHROPIC_APP_LOCAL_BASE_URL
export function getConfiguredProductConfigDir(): string | undefined { export function getConfiguredProductConfigDir(): string | undefined {
return ( return process.env[PRODUCT_CONFIG_ENV_VAR]
process.env[PRODUCT_CONFIG_ENV_VAR] ??
process.env[LEGACY_PRODUCT_CONFIG_ENV_VAR]
)
} }
/** /**

View File

@@ -27,7 +27,11 @@ import pickBy from 'lodash-es/pickBy.js';
import uniqBy from 'lodash-es/uniqBy.js'; import uniqBy from 'lodash-es/uniqBy.js';
import React from 'react'; import React from 'react';
import { getOauthConfig } from './constants/oauth.js'; import { getOauthConfig } from './constants/oauth.js';
import { getRemoteSessionUrl } from './constants/product.js'; import {
CLI_BINARY_NAME,
getRemoteSessionUrl,
PRODUCT_NAME,
} from './constants/product.js';
import { getSystemContext, getUserContext } from './context.js'; import { getSystemContext, getUserContext } from './context.js';
import { init, initializeTelemetryAfterTrust } from './entrypoints/init.js'; import { init, initializeTelemetryAfterTrust } from './entrypoints/init.js';
import { addToHistory } from './history.js'; import { addToHistory } from './history.js';
@@ -952,7 +956,7 @@ async function run(): Promise<CommanderCommand> {
// terminal shell integration may mirror the process name to the tab. // terminal shell integration may mirror the process name to the tab.
// After init() so settings.json env can also gate this (gh-4765). // After init() so settings.json env can also gate this (gh-4765).
if (!isEnvTruthy(process.env.CLAUDE_CODE_DISABLE_TERMINAL_TITLE)) { if (!isEnvTruthy(process.env.CLAUDE_CODE_DISABLE_TERMINAL_TITLE)) {
process.title = 'claude'; process.title = CLI_BINARY_NAME;
} }
// Attach logging sinks so subcommand handlers can use logEvent/logError. // Attach logging sinks so subcommand handlers can use logEvent/logError.
@@ -997,7 +1001,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(CLI_BINARY_NAME).description(`${PRODUCT_NAME} 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) => {
@@ -1051,7 +1055,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 ${PRODUCT_NAME} with just \`${CLI_BINARY_NAME}\``));
prompt = undefined; prompt = undefined;
} }
@@ -3835,7 +3839,7 @@ async function run(): Promise<CommanderCommand> {
pendingHookMessages pendingHookMessages
}, renderAndRun); }, renderAndRun);
} }
}).version(`${MACRO.VERSION} (Claude Code)`, '-v, --version', 'Output the version number'); }).version(`${MACRO.VERSION} (${PRODUCT_NAME})`, '-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)');

View File

@@ -68,6 +68,7 @@ import { useSkillImprovementSurvey } from '../hooks/useSkillImprovementSurvey.js
import { useMoreRight } from '../moreright/useMoreRight.js'; import { useMoreRight } from '../moreright/useMoreRight.js';
import { SpinnerWithVerb, BriefIdleStatus, type SpinnerMode } from '../components/Spinner.js'; import { SpinnerWithVerb, BriefIdleStatus, type SpinnerMode } from '../components/Spinner.js';
import { getSystemPrompt } from '../constants/prompts.js'; import { getSystemPrompt } from '../constants/prompts.js';
import { PRODUCT_CONFIG_DIRNAME, PRODUCT_NAME } from '../constants/product.js';
import { buildEffectiveSystemPrompt } from '../utils/systemPrompt.js'; import { buildEffectiveSystemPrompt } from '../utils/systemPrompt.js';
import { getSystemContext, getUserContext } from '../context.js'; import { getSystemContext, getUserContext } from '../context.js';
import { getMemoryFiles } from '../utils/claudemd.js'; import { getMemoryFiles } from '../utils/claudemd.js';
@@ -1176,7 +1177,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 ?? 'Claude Code'; const terminalTitle = sessionTitle ?? agentTitle ?? haikuTitle ?? PRODUCT_NAME;
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
@@ -1692,7 +1693,7 @@ export function REPL({
if (wt.creationDurationMs < 15_000) return; if (wt.creationDurationMs < 15_000) return;
worktreeTipShownRef.current = true; worktreeTipShownRef.current = true;
const secs = Math.round(wt.creationDurationMs / 1000); const secs = Math.round(wt.creationDurationMs / 1000);
setMessages(prev => [...prev, createSystemMessage(`Worktree creation took ${secs}s. For large repos, set \`worktree.sparsePaths\` in .claude/settings.json to check out only the directories you need — e.g. \`{"worktree": {"sparsePaths": ["src", "packages/foo"]}}\`.`, 'info')]); setMessages(prev => [...prev, createSystemMessage(`Worktree creation took ${secs}s. For large repos, set \`worktree.sparsePaths\` in \`${PRODUCT_CONFIG_DIRNAME}/settings.json\` to check out only the directories you need — e.g. \`{"worktree": {"sparsePaths": ["src", "packages/foo"]}}\`.`, 'info')]);
}, [setMessages]); }, [setMessages]);
// Hide spinner when the only in-progress tool is Sleep // Hide spinner when the only in-progress tool is Sleep
@@ -4193,7 +4194,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(`\n${PRODUCT_NAME} has been suspended. Run \`fg\` to bring ${PRODUCT_NAME} back.\nNote: ctrl + z now suspends ${PRODUCT_NAME}, 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

View File

@@ -3,12 +3,11 @@ import { homedir } from 'os'
import { join } from 'path' import { join } from 'path'
import { import {
getConfiguredProductConfigDir, getConfiguredProductConfigDir,
LEGACY_PRODUCT_SLUG,
PRODUCT_SLUG, PRODUCT_SLUG,
} from '../constants/product.js' } from '../constants/product.js'
import { fileSuffixForOauthConfig } from '../constants/oauth.js' import { fileSuffixForOauthConfig } from '../constants/oauth.js'
import { isRunningWithBun } from './bundledMode.js' import { isRunningWithBun } from './bundledMode.js'
import { getClaudeConfigHomeDir, isEnvTruthy } from './envUtils.js' import { isEnvTruthy } from './envUtils.js'
import { findExecutable } from './findExecutable.js' import { findExecutable } from './findExecutable.js'
import { getFsImplementation } from './fsOperations.js' import { getFsImplementation } from './fsOperations.js'
import { which } from './which.js' import { which } from './which.js'
@@ -17,27 +16,15 @@ type Platform = 'win32' | 'darwin' | 'linux'
// Config and data paths // Config and data paths
export const getGlobalClaudeFile = memoize((): string => { export const getGlobalClaudeFile = memoize((): string => {
const configHomeDir = getClaudeConfigHomeDir()
const configDirOverride = getConfiguredProductConfigDir() const configDirOverride = getConfiguredProductConfigDir()
// Legacy fallback for backwards compatibility
const legacyConfigPath = join(configHomeDir, '.config.json')
if (getFsImplementation().existsSync(legacyConfigPath)) {
return legacyConfigPath
}
const suffix = fileSuffixForOauthConfig() const suffix = fileSuffixForOauthConfig()
const preferredFilename = `.${PRODUCT_SLUG}${suffix}.json` const preferredFilename = `.${PRODUCT_SLUG}${suffix}.json`
const legacyFilename = `.${LEGACY_PRODUCT_SLUG}${suffix}.json`
const preferredPath = join(configDirOverride || homedir(), preferredFilename) const preferredPath = join(configDirOverride || homedir(), preferredFilename)
const legacyPath = join(configDirOverride || homedir(), legacyFilename)
if (getFsImplementation().existsSync(preferredPath)) { if (getFsImplementation().existsSync(preferredPath)) {
return preferredPath return preferredPath
} }
if (getFsImplementation().existsSync(legacyPath)) {
return legacyPath
}
return preferredPath return preferredPath
}) })

View File

@@ -4,12 +4,11 @@ import { homedir } from 'os'
import { join } from 'path' import { join } from 'path'
import { import {
getConfiguredProductConfigDir, getConfiguredProductConfigDir,
LEGACY_PRODUCT_CONFIG_DIRNAME,
PRODUCT_CONFIG_DIRNAME, PRODUCT_CONFIG_DIRNAME,
} from '../constants/product.js' } from '../constants/product.js'
// Memoized: 150+ callers, many on hot paths. Keyed off CLAUDE_CONFIG_DIR so // Memoized: 150+ callers, many on hot paths. Keyed off BETTER_CLAWD_CONFIG_DIR
// tests that change the env var get a fresh value without explicit cache.clear. // so tests that change the env var get a fresh value without explicit cache.clear.
export const getClaudeConfigHomeDir = memoize( export const getClaudeConfigHomeDir = memoize(
(): string => { (): string => {
const configuredDir = getConfiguredProductConfigDir() const configuredDir = getConfiguredProductConfigDir()
@@ -18,14 +17,10 @@ export const getClaudeConfigHomeDir = memoize(
} }
const betterClawdDir = join(homedir(), PRODUCT_CONFIG_DIRNAME) const betterClawdDir = join(homedir(), PRODUCT_CONFIG_DIRNAME)
const legacyClaudeDir = join(homedir(), LEGACY_PRODUCT_CONFIG_DIRNAME)
if (existsSync(betterClawdDir)) { if (existsSync(betterClawdDir)) {
return betterClawdDir.normalize('NFC') return betterClawdDir.normalize('NFC')
} }
if (existsSync(legacyClaudeDir)) {
return legacyClaudeDir.normalize('NFC')
}
return betterClawdDir.normalize('NFC') return betterClawdDir.normalize('NFC')
}, },

View File

@@ -19,7 +19,6 @@ import { userInfo } from 'os'
import { getOauthConfig } from 'src/constants/oauth.js' import { getOauthConfig } from 'src/constants/oauth.js'
import { import {
getConfiguredProductConfigDir, getConfiguredProductConfigDir,
LEGACY_PRODUCT_NAME,
PRODUCT_NAME, PRODUCT_NAME,
} from 'src/constants/product.js' } from 'src/constants/product.js'
import { getClaudeConfigHomeDir } from '../envUtils.js' import { getClaudeConfigHomeDir } from '../envUtils.js'
@@ -33,7 +32,6 @@ export const CREDENTIALS_SERVICE_SUFFIX = '-credentials'
export function getMacOsKeychainStorageServiceName( export function getMacOsKeychainStorageServiceName(
serviceSuffix: string = '', serviceSuffix: string = '',
opts: { legacy?: boolean } = {},
): string { ): string {
const configDir = getClaudeConfigHomeDir() const configDir = getClaudeConfigHomeDir()
const isDefaultDir = !getConfiguredProductConfigDir() const isDefaultDir = !getConfiguredProductConfigDir()
@@ -43,18 +41,13 @@ export function getMacOsKeychainStorageServiceName(
const dirHash = isDefaultDir const dirHash = isDefaultDir
? '' ? ''
: `-${createHash('sha256').update(configDir).digest('hex').substring(0, 8)}` : `-${createHash('sha256').update(configDir).digest('hex').substring(0, 8)}`
const baseName = opts.legacy ? LEGACY_PRODUCT_NAME : PRODUCT_NAME return `${PRODUCT_NAME}${getOauthConfig().OAUTH_FILE_SUFFIX}${serviceSuffix}${dirHash}`
return `${baseName}${getOauthConfig().OAUTH_FILE_SUFFIX}${serviceSuffix}${dirHash}`
} }
export function getMacOsKeychainStorageServiceNames( export function getMacOsKeychainStorageServiceNames(
serviceSuffix: string = '', serviceSuffix: string = '',
): string[] { ): string[] {
const names = [ return [getMacOsKeychainStorageServiceName(serviceSuffix)]
getMacOsKeychainStorageServiceName(serviceSuffix),
getMacOsKeychainStorageServiceName(serviceSuffix, { legacy: true }),
]
return Array.from(new Set(names))
} }
export function getUsername(): string { export function getUsername(): string {