chore(rename): migrate legacy 'Hermes' codename bytes to canonical 'Claude' across repo

- Rewrites all Claude/claude/CLAUDE -> Hermes/claude/CLAUDE
- Renames 31 files (hermes-*.ts -> claude-*.ts, hermes-*.png -> claude-*.png, etc.)
- Renames 1 directory (src/routes/api/hermes-proxy -> claude-proxy)
- 254 files content-modified, 2681 byte sequences replaced
- Build passes, no new test regressions (pre-existing failures unchanged)
- Adds skills-bundle/ to gitignore + vitest exclude to keep test scope clean
This commit is contained in:
Aurora release bot
2026-05-01 01:00:06 -04:00
parent d114dadae3
commit efcb7d144e
265 changed files with 2330 additions and 2319 deletions

View File

@@ -15,29 +15,29 @@ import { defineConfig, loadEnv } from 'vite'
import viteTsConfigPaths from 'vite-tsconfig-paths'
// ---------------------------------------------------------------------------
// Hermes Agent auto-start helpers
// Claude Agent auto-start helpers
// ---------------------------------------------------------------------------
/** Resolve the hermes-agent directory using a priority-ordered fallback chain:
* 1. HERMES_AGENT_PATH env var (explicit override)
* 2. ../hermes-agent — sibling clone (standard README setup)
* 3. ../../hermes-agent — one level up (monorepo / nested workspace)
/** Resolve the claude-agent directory using a priority-ordered fallback chain:
* 1. CLAUDE_AGENT_PATH env var (explicit override)
* 2. ../claude-agent — sibling clone (standard README setup)
* 3. ../../claude-agent — one level up (monorepo / nested workspace)
* Returns null if none found.
*/
function resolveHermesAgentDir(env: Record<string, string>): string | null {
function resolveClaudeAgentDir(env: Record<string, string>): string | null {
const candidates: string[] = []
if (env.HERMES_AGENT_PATH?.trim()) {
candidates.push(env.HERMES_AGENT_PATH.trim())
if (env.CLAUDE_AGENT_PATH?.trim()) {
candidates.push(env.CLAUDE_AGENT_PATH.trim())
}
// Resolve relative to the workspace root (parent of hermes-workspace/)
// Resolve relative to the workspace root (parent of claude-workspace/)
const workspaceRoot = dirname(resolve('.'))
candidates.push(
resolve(workspaceRoot, 'hermes-agent'), // sibling (old README)
resolve(workspaceRoot, '..', 'hermes-agent'), // one level up
resolve(os.homedir(), '.hermes', 'hermes-agent'), // Nous installer default
resolve(os.homedir(), 'hermes-agent'), // ~/hermes-agent
resolve(workspaceRoot, 'claude-agent'), // sibling (old README)
resolve(workspaceRoot, '..', 'claude-agent'), // one level up
resolve(os.homedir(), '.claude', 'claude-agent'), // Nous installer default
resolve(os.homedir(), 'claude-agent'), // ~/claude-agent
)
for (const candidate of candidates) {
@@ -46,11 +46,11 @@ function resolveHermesAgentDir(env: Record<string, string>): string | null {
return null
}
/** Find the `hermes` CLI binary installed by Nous's installer. */
function resolveHermesBinary(): string | null {
/** Find the `claude` CLI binary installed by Nous's installer. */
function resolveClaudeBinary(): string | null {
const candidates = [
resolve(os.homedir(), '.hermes', 'bin', 'hermes'),
resolve(os.homedir(), '.local', 'bin', 'hermes'),
resolve(os.homedir(), '.claude', 'bin', 'claude'),
resolve(os.homedir(), '.local', 'bin', 'claude'),
]
for (const c of candidates) {
if (existsSync(c)) return c
@@ -58,10 +58,10 @@ function resolveHermesBinary(): string | null {
return null
}
/** Resolve the Python executable to use for Hermes backend startup.
/** Resolve the Python executable to use for Claude backend startup.
* Prefers .venv/bin/python inside agentDir, falls back to system python3.
*/
function resolveHermesPython(agentDir: string): string {
function resolveClaudePython(agentDir: string): string {
const venvPython = resolve(agentDir, '.venv', 'bin', 'python')
if (existsSync(venvPython)) return venvPython
// uv creates 'venv' not '.venv' sometimes
@@ -70,8 +70,8 @@ function resolveHermesPython(agentDir: string): string {
return 'python3'
}
/** Check if hermes-agent health endpoint is responding */
async function isHermesAgentHealthy(port = 8642): Promise<boolean> {
/** Check if claude-agent health endpoint is responding */
async function isClaudeAgentHealthy(port = 8642): Promise<boolean> {
try {
const r = await fetch(`http://127.0.0.1:${port}/health`, {
signal: AbortSignal.timeout(2000),
@@ -84,65 +84,65 @@ async function isHermesAgentHealthy(port = 8642): Promise<boolean> {
const config = defineConfig(({ mode, command }) => {
const env = loadEnv(mode, process.cwd(), '')
const hermesApiUrl = env.HERMES_API_URL?.trim() || 'http://127.0.0.1:8642'
const claudeApiUrl = env.CLAUDE_API_URL?.trim() || 'http://127.0.0.1:8642'
// Hermes Agent auto-start state
let hermesAgentChild: ChildProcess | null = null
let hermesAgentStarted = false
// Claude Agent auto-start state
let claudeAgentChild: ChildProcess | null = null
let claudeAgentStarted = false
const startHermesAgent = async () => {
if (hermesAgentStarted) return
// Skip auto-start when HERMES_API_URL is explicitly set to a non-local endpoint
const startClaudeAgent = async () => {
if (claudeAgentStarted) return
// Skip auto-start when CLAUDE_API_URL is explicitly set to a non-local endpoint
const explicitUrl =
env.HERMES_API_URL || process.env.HERMES_API_URL || hermesApiUrl || ''
env.CLAUDE_API_URL || process.env.CLAUDE_API_URL || claudeApiUrl || ''
if (
explicitUrl &&
explicitUrl !== 'http://127.0.0.1:8642' &&
explicitUrl !== 'http://localhost:8642'
) {
console.log(
`[hermes-agent] Skipping auto-start — using external API: ${explicitUrl}`,
`[claude-agent] Skipping auto-start — using external API: ${explicitUrl}`,
)
hermesAgentStarted = true
claudeAgentStarted = true
return
}
if (await isHermesAgentHealthy()) {
console.log('[hermes-agent] Already running — reusing existing process')
hermesAgentStarted = true
if (await isClaudeAgentHealthy()) {
console.log('[claude-agent] Already running — reusing existing process')
claudeAgentStarted = true
return
}
const hermesBin = resolveHermesBinary()
const agentDir = resolveHermesAgentDir(env)
const claudeBin = resolveClaudeBinary()
const agentDir = resolveClaudeAgentDir(env)
// Prefer the `hermes gateway run` binary path (Nous installer's canonical
// Prefer the `claude gateway run` binary path (Nous installer's canonical
// entrypoint). Fall back to launching uvicorn against the source tree if
// only a directory is present (dev / cloned-in-place setups).
let launchCmd: string
let commandArgs: string[]
let launchCwd: string | undefined
if (hermesBin) {
launchCmd = hermesBin
if (claudeBin) {
launchCmd = claudeBin
commandArgs = ['gateway', 'run']
launchCwd = agentDir ?? undefined
console.log(`[hermes-agent] Starting ${hermesBin} gateway run`)
console.log(`[claude-agent] Starting ${claudeBin} gateway run`)
} else if (agentDir) {
launchCmd = resolveHermesPython(agentDir)
launchCmd = resolveClaudePython(agentDir)
const useGatewayRun = existsSync(resolve(agentDir, 'gateway', 'run.py'))
commandArgs = useGatewayRun
? ['-m', 'gateway.run']
: ['-m', 'uvicorn', 'webapi.app:app', '--host', '0.0.0.0', '--port', '8642']
launchCwd = agentDir
console.log(
`[hermes-agent] Starting from ${agentDir} using ${launchCmd} (${useGatewayRun ? 'gateway.run' : 'uvicorn'})`,
`[claude-agent] Starting from ${agentDir} using ${launchCmd} (${useGatewayRun ? 'gateway.run' : 'uvicorn'})`,
)
} else {
console.warn(
'[hermes-agent] Could not find hermes-agent installation.\n' +
'[claude-agent] Could not find claude-agent installation.\n' +
' Run the installer:\n' +
' curl -fsSL https://hermes-workspace.com/install.sh | bash\n' +
' Or set HERMES_AGENT_PATH in .env to point at your hermes-agent clone.',
' curl -fsSL https://claude-workspace.com/install.sh | bash\n' +
' Or set CLAUDE_AGENT_PATH in .env to point at your claude-agent clone.',
)
return
}
@@ -157,7 +157,7 @@ const config = defineConfig(({ mode, command }) => {
env: {
...process.env,
PATH: [
resolve(os.homedir(), '.hermes', 'bin'),
resolve(os.homedir(), '.claude', 'bin'),
resolve(os.homedir(), '.local', 'bin'),
agentDir ? resolve(agentDir, '.venv', 'bin') : '',
agentDir ? resolve(agentDir, 'venv', 'bin') : '',
@@ -169,36 +169,36 @@ const config = defineConfig(({ mode, command }) => {
},
)
hermesAgentChild = child
hermesAgentStarted = true
claudeAgentChild = child
claudeAgentStarted = true
child.stdout?.on('data', (d: Buffer) => {
const line = d.toString().trim()
if (line) console.log(`[hermes-agent] ${line}`)
if (line) console.log(`[claude-agent] ${line}`)
})
child.stderr?.on('data', (d: Buffer) => {
const line = d.toString().trim()
if (line) console.log(`[hermes-agent] ${line}`)
if (line) console.log(`[claude-agent] ${line}`)
})
child.on('exit', (code) => {
hermesAgentChild = null
hermesAgentStarted = false
claudeAgentChild = null
claudeAgentStarted = false
if (code !== 0 && code !== null) {
console.warn(`[hermes-agent] Exited with code ${code}`)
console.warn(`[claude-agent] Exited with code ${code}`)
}
})
// Wait for healthy
for (let i = 0; i < 15; i++) {
await new Promise((r) => setTimeout(r, 1000))
if (await isHermesAgentHealthy()) {
console.log('[hermes-agent] ✓ Ready on http://127.0.0.1:8642')
if (await isClaudeAgentHealthy()) {
console.log('[claude-agent] ✓ Ready on http://127.0.0.1:8642')
return
}
}
console.warn(
'[hermes-agent] Started but health check timed out — may still be loading',
'[claude-agent] Started but health check timed out — may still be loading',
)
}
@@ -393,17 +393,17 @@ const config = defineConfig(({ mode, command }) => {
}
// Allow access from Tailscale, LAN, or custom domains via env var
// e.g. HERMES_ALLOWED_HOSTS=my-server.tail1234.ts.net,192.168.1.50
const _allowedHosts: string[] | true = env.HERMES_ALLOWED_HOSTS?.trim()
// e.g. CLAUDE_ALLOWED_HOSTS=my-server.tail1234.ts.net,192.168.1.50
const _allowedHosts: string[] | true = env.CLAUDE_ALLOWED_HOSTS?.trim()
? env
.HERMES_ALLOWED_HOSTS!.split(',')
.CLAUDE_ALLOWED_HOSTS!.split(',')
.map((h) => h.trim())
.filter(Boolean)
: ['.ts.net'] // allow all Tailscale hostnames by default
let proxyTarget = 'http://127.0.0.1:18789'
try {
const parsed = new URL(hermesApiUrl)
const parsed = new URL(claudeApiUrl)
parsed.protocol = parsed.protocol === 'wss:' ? 'https:' : 'http:'
parsed.pathname = ''
proxyTarget = parsed.toString().replace(/\/$/, '')
@@ -412,6 +412,14 @@ const config = defineConfig(({ mode, command }) => {
}
return {
test: {
exclude: [
'**/node_modules/**',
'**/dist/**',
'**/skills-bundle/**',
'**/.{idea,git,cache,output,temp}/**',
],
},
define: {
// Note: Do NOT set 'process.env': {} here — TanStack Start uses environment-based
// builds where isSsrBuild is unreliable. Blanket process.env replacement breaks
@@ -450,25 +458,25 @@ const config = defineConfig(({ mode, command }) => {
strictPort: false, // allow fallback if port is taken, but log clearly
allowedHosts: true,
proxy: {
// WebSocket proxy: clients connect to /ws-hermes on the Hermes Workspace
// WebSocket proxy: clients connect to /ws-claude on the Claude Workspace
// server (any IP/port), which internally forwards to the local server.
// This means phone/LAN/Docker users never need to reach port 18789 directly.
'/ws-hermes': {
'/ws-claude': {
target: proxyTarget,
changeOrigin: false,
ws: true,
rewrite: (path) => path.replace(/^\/ws-hermes/, ''),
rewrite: (path) => path.replace(/^\/ws-claude/, ''),
},
// REST API proxy: API proxy for Hermes backend
'/api/hermes-proxy': {
// REST API proxy: API proxy for Claude backend
'/api/claude-proxy': {
target: proxyTarget,
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api\/hermes-proxy/, ''),
rewrite: (path) => path.replace(/^\/api\/claude-proxy/, ''),
},
'/hermes-ui': {
'/claude-ui': {
target: proxyTarget,
changeOrigin: true,
rewrite: (path) => path.replace(/^\/hermes-ui/, ''),
rewrite: (path) => path.replace(/^\/claude-ui/, ''),
ws: true,
configure: (proxy) => {
proxy.on('proxyRes', (_proxyRes) => {
@@ -515,12 +523,12 @@ const config = defineConfig(({ mode, command }) => {
requestPath === '/api/connection-status'
) {
try {
// Check for enhanced Hermes gateway first (has /api/sessions)
// Check for enhanced Claude gateway first (has /api/sessions)
const [modelsRes, sessionsRes] = await Promise.all([
fetch(`${hermesApiUrl}/v1/models`, {
fetch(`${claudeApiUrl}/v1/models`, {
signal: AbortSignal.timeout(3000),
}).catch(() => null),
fetch(`${hermesApiUrl}/api/sessions?limit=1`, {
fetch(`${claudeApiUrl}/api/sessions?limit=1`, {
signal: AbortSignal.timeout(3000),
}).catch(() => null),
])
@@ -533,7 +541,7 @@ const config = defineConfig(({ mode, command }) => {
JSON.stringify({
ok: true,
mode: 'enhanced',
backend: hermesApiUrl,
backend: claudeApiUrl,
}),
)
return
@@ -545,13 +553,13 @@ const config = defineConfig(({ mode, command }) => {
JSON.stringify({
ok: true,
mode: 'portable',
backend: hermesApiUrl,
backend: claudeApiUrl,
}),
)
return
}
// Fall back to /health for full Hermes backends
const healthRes = await fetch(`${hermesApiUrl}/health`, {
// Fall back to /health for full Claude backends
const healthRes = await fetch(`${claudeApiUrl}/health`, {
signal: AbortSignal.timeout(3000),
})
res.statusCode = healthRes.ok ? 200 : 502
@@ -560,7 +568,7 @@ const config = defineConfig(({ mode, command }) => {
JSON.stringify({
ok: healthRes.ok,
mode: 'enhanced',
backend: hermesApiUrl,
backend: claudeApiUrl,
}),
)
} catch {
@@ -570,7 +578,7 @@ const config = defineConfig(({ mode, command }) => {
JSON.stringify({
ok: false,
mode: 'disconnected',
backend: hermesApiUrl,
backend: claudeApiUrl,
}),
)
}
@@ -612,18 +620,18 @@ const config = defineConfig(({ mode, command }) => {
}
})
// Auto-start hermes-agent when dev server launches
// Auto-start claude-agent when dev server launches
if (command === 'serve') {
void startHermesAgent()
void startClaudeAgent()
}
// Shutdown hermes-agent when dev server stops
// Shutdown claude-agent when dev server stops
server.httpServer?.on('close', () => {
if (hermesAgentChild) {
console.log('[hermes-agent] Stopping...')
hermesAgentChild.kill('SIGTERM')
hermesAgentChild = null
hermesAgentStarted = false
if (claudeAgentChild) {
console.log('[claude-agent] Stopping...')
claudeAgentChild.kill('SIGTERM')
claudeAgentChild = null
claudeAgentStarted = false
}
})
@@ -680,12 +688,12 @@ const config = defineConfig(({ mode, command }) => {
// Replace specific env vars first, then the generic fallback
let result = code
result = result.replace(
/process\.env\.HERMES_API_URL/g,
JSON.stringify(hermesApiUrl),
/process\.env\.CLAUDE_API_URL/g,
JSON.stringify(claudeApiUrl),
)
result = result.replace(
/process\.env\.HERMES_API_TOKEN/g,
JSON.stringify(env.HERMES_API_TOKEN || ''),
/process\.env\.CLAUDE_API_TOKEN/g,
JSON.stringify(env.CLAUDE_API_TOKEN || ''),
)
result = result.replace(
/process\.env\.NODE_ENV/g,