Files
AgentHub/client/src/i18n/locales/en/ccConfig.json
T
nntrivi2001 969b06253c feat: per-tool settings, persistent settings file, Codex and Antigravity sessions, tokens and hooks (#40 B, C1, C2, D)
Part B: Model Pricing, Hook Configuration and CLAUDE_HOME move from
Settings → Dashboard to the Claude Code tab's AgentHub sub-tab
(ClaudeAgentHubSettings.tsx); CODEX_HOME is editable in Codex → AgentHub.
A home that is or contains the OS home is refused (EBADHOME).

Settings persistence: dashboard-saved settings go to
~/.config/agenthub/settings.env (AGENTHUB_SETTINGS_FILE), outside the plugin
cache an update wipes. Load order: real env > the checkout's .env > that file.
The first CLAUDE_HOME change pins DASHBOARD_DATA_DIR so the DB stays put.

C1: codex-usage.js reads Codex rollout journals into sessions (new column
tool) and token_usage, tracked per file in codex_rollouts; forks deduped by
total vector, sub-agent threads folded into the root; pricing-sync also
prices OpenAI models; PricingSettings with a vendor filter.

C2: codex-hooks.js installs AgentHub's hooks into $CODEX_HOME/hooks.json on
a click, through a stable forwarder; Codex trust is never written. The hook
route creates tool='codex' sessions and folds sub-agent hooks into the root.

D: antigravity-usage.js reads agy's per-conversation SQLite files (tokens
from ModelUsageStats) into tool='antigravity' sessions; antigravity-hooks.js
installs the named hook `agenthub` (PreInvocation, PostToolUse, Stop — never
PreToolUse) into ~/.gemini/config/hooks.json; Settings → Antigravity tab;
Gemini pricing.

Whole-change review fixes: sameOriginGuard on both home PUTs, routers.missing
on a CLAUDE_HOME change, reset-pricing scope, GET /api/sessions?tool=,
clear-data covering the new tables, Codex child-thread events moving no
status, hooks owning status only while current, EFOREIGN for a forwarder
that is not ours, agy quiet window and turn rules, AGENTHUB_SETTINGS_FILE
honoured from .env.

Docs, OpenAPI and the CLAUDE.md marker updated. Server 2141, client 779.
2026-09-29 16:09:19 +07:00

393 lines
18 KiB
JSON

{
"title": "Claude Config Explorer",
"subtitle": "Your Claude Code setup at a glance - plugins, skills, subagents, MCP servers, hooks, and settings.",
"refresh": "Refresh",
"refreshing": "Refreshing…",
"lastUpdated": "Last updated {{time}}",
"loadError": "Failed to load: {{message}}",
"scope": {
"all": "All scopes",
"user": "User",
"project": "Project",
"projectLocal": "Project (local)",
"home": "Home"
},
"tabs": {
"overview": "Overview",
"skills": "Skills",
"agents": "Subagents",
"commands": "Slash commands",
"outputStyles": "Output styles",
"plugins": "Plugins",
"marketplaces": "Marketplaces",
"mcp": "MCP servers",
"hooks": "Hooks",
"keybindings": "Keybindings",
"settings": "Settings",
"memory": "Memory",
"agenthub": "AgentHub"
},
"overview": {
"rootsTitle": "Roots",
"claudeHome": "Claude home",
"projectClaudeDir": "Project .claude",
"projectRoot": "Project root",
"claudeJson": "claude.json",
"summary": "Quick summary",
"user": "user",
"project": "project",
"items": "items"
},
"common": {
"search": "Search by name…",
"clearSearch": "Clear search",
"empty": "Nothing here yet.",
"viewSource": "View source",
"close": "Close",
"copyPath": "Copy path",
"copied": "Copied",
"truncated": "(truncated for preview)",
"size": "Size",
"modified": "Modified",
"scopeLabel": "Scope",
"noFrontmatter": "No frontmatter",
"redactedNotice": "Values matching /token|secret|password|key|auth/i are redacted server-side."
},
"skills": {
"name": "Name",
"description": "Description"
},
"agents": {
"name": "Name",
"model": "Model",
"tools": "Tools"
},
"plugins": {
"manifest": "Manifest",
"marketplace": "Marketplace",
"version": "Version",
"installedAt": "Installed",
"lastUpdated": "Updated",
"installPath": "Install path",
"missing": "Install path missing",
"manifestMissing": "No installed_plugins.json found at {{path}}",
"enabled": "Enabled",
"disabled": "Disabled",
"contributes": "Contributes",
"skills_one": "{{count}} skill",
"skills_other": "{{count}} skills",
"agents_one": "{{count}} agent",
"agents_other": "{{count}} agents",
"commands_one": "{{count}} command",
"commands_other": "{{count}} commands",
"outputStyles_one": "{{count}} output style",
"outputStyles_other": "{{count}} output styles",
"hooks_one": "{{count}} hook script",
"hooks_other": "{{count}} hook scripts",
"author": "Author",
"homepage": "Homepage",
"license": "License",
"description": "Description"
},
"marketplaces": {
"manifest": "Known marketplaces manifest",
"noMarketplaces": "No marketplaces registered.",
"source": "Source",
"lastUpdated": "Last synced",
"pluginCount": "Plugins",
"owner": "Owner",
"installLocation": "Install path",
"addCmd": "claude plugin marketplace add <repo>"
},
"keybindings": {
"file": "Source file",
"missing": "No keybindings.json found at {{path}}",
"context": "Context",
"key": "Key",
"action": "Action",
"docsLink": "View keybindings docs",
"contextPlaceholder": "Context (e.g. Global, Chat)",
"addContext": "Add context",
"removeContext": "Remove context",
"addBinding": "Add binding",
"removeBinding": "Remove binding",
"errContext": "Every context needs a name.",
"errDupContext": "Duplicate context: {{context}}",
"errEmpty": "Every binding in \"{{context}}\" needs both a key and an action.",
"errDupKey": "Duplicate key \"{{key}}\" in context \"{{context}}\"."
},
"statusline": {
"title": "Statusline",
"configured": "Configured statusline command",
"scripts": "Statusline scripts found in CLAUDE_HOME",
"noStatusline": "No statusline configured."
},
"hookScripts": {
"title": "~/.claude/hooks/ scripts",
"subtitle": "Helper scripts referenced by your hook commands. These run when settings.json `hooks.<event>.hooks[].command` invokes them.",
"empty": "No scripts in ~/.claude/hooks/."
},
"mcp": {
"userScope": "User-scoped servers",
"projectScope": "Project-scoped servers",
"name": "Name",
"scope": "Scope",
"scopeUser": "User",
"scopeLocal": "This project",
"command": "Command",
"args": "Args",
"env": "Env names",
"url": "URL",
"headers": "Header names",
"kind": "Kind",
"source": "Source",
"noServers": "No MCP servers found.",
"notRemovable": "Configured in settings.json — remove it there; no CLI scope addresses this entry."
},
"hooks": {
"noHooks": "No hooks configured.",
"matcher": "Matcher",
"command": "Command",
"type": "Type",
"timeout": "Timeout",
"fileMissing": "(no settings file at this scope)"
},
"settings": {
"fileMissing": "(no settings file at this scope)"
},
"memory": {
"userScope": "User memory",
"projectScope": "Project memory",
"missing": "No CLAUDE.md found.",
"autoTitle": "Project memory store",
"autoSubtitle": "Per-project file-based memory under ~/.claude/projects/<project>/memory/ — a MEMORY.md index plus one file per remembered fact. Read-only here.",
"noMatches": "No memory files match your search.",
"indexFiles": "Index",
"jumpTo": "Jump to file",
"fileCount_one": "{{count}} file",
"fileCount_other": "{{count}} files",
"factFiles_one": "{{count}} fact",
"factFiles_other": "{{count}} facts",
"newFile": "New file",
"newFileTitle": "New memory file in {{project}}",
"namePlaceholder": "e.g. my_fact.md",
"nameHelp": "Filename ending in .md (.md is added if you omit it).",
"projectLabel": "Project",
"projectHelp": "Created in this project's memory dir."
},
"projectMemory": {
"newButton": "New project memory",
"title": "Create {{file}} for another project",
"dirLabel": "Project directory",
"dirHelp": "Absolute path to a project that already exists on this machine. {{file}} is created inside it; an existing one is never overwritten.",
"dirRequired": "A project directory is required",
"createButton": "Create",
"created": "Created {{path}}",
"template": "# Project memory\n\nWhat this project is, and anything an agent should know before touching it.\n\n## Stack\n\n## Conventions\n\n## Commands\n",
"contentLabel": "Content",
"cancel": "Cancel",
"saving": "Creating…",
"close": "Close"
},
"edit": {
"newButton": "New",
"editButton": "Edit",
"deleteButton": "Delete",
"save": "Save",
"cancel": "Cancel",
"saving": "Saving…",
"deleting": "Deleting…",
"newTitle": "Create new {{type}}",
"editTitle": "Edit {{name}}",
"namePlaceholder": "name (kebab-case, no spaces)",
"nameLabel": "Name",
"nameHelp": "Letters, digits, dot, dash, underscore. Max 64 chars.",
"contentLabel": "Content",
"scopePicker": "Scope",
"writeError": "Save failed: {{message}}",
"deleteError": "Delete failed: {{message}}",
"saveSuccess": "Saved · backup at {{path}}",
"saveSuccessNew": "Created.",
"deleteSuccess": "Deleted · backup at {{path}}",
"confirmDelete": "Delete this item?",
"confirmDeleteBody": "This will move the file (or skill folder, including bundled assets) to a timestamped backup before removing it. The backup lives outside the directories the CLI scans, so the entry will disappear from your CLI.",
"confirmDeletePath": "Path: {{path}}",
"confirmDeleteAction": "Yes, back up and delete",
"templates": {
"skills": "---\nname: my-skill\ndescription: One-line description (shown when Claude picks the skill)\n---\n\nBody - what the skill does, when to use it, examples.\n",
"agents": "---\nname: my-agent\ndescription: When to invoke this subagent\ntools: Read, Grep\nmodel: sonnet\n---\n\nSystem prompt for the subagent.\n",
"commands": "---\ndescription: One-line description shown in the slash menu\n---\n\nWhat /my-command does.\n",
"output-styles": "---\nname: my-style\ndescription: Output style description\n---\n\nStyle instructions.\n",
"memory": "# Project memory\n\nClaude reads this on session start.\n",
"auto-memory": "---\nname: my-fact\ndescription: One-line summary of the remembered fact\nmetadata:\n type: feedback\n---\n\nThe fact to remember.\n"
}
},
"backups": {
"title": "Backups",
"empty": "No backups yet - every edit or delete creates a timestamped backup that lands here.",
"viewLink": "Show backup history",
"openButton": "Backups",
"subtitle": "Every save / delete in the editor writes a copy here first. Backup folders live outside the directories Claude Code scans, so they don't reappear as ghosts in your CLI.",
"restoreHint": "Restore by renaming the backup back into place:",
"size": "Size",
"created": "Created",
"type": "Type",
"scopeLabel": "Scope",
"filterAll": "All types"
},
"profiles": {
"usageCheck": "Check quota",
"usageChecking": "Checking…",
"usageRefresh": "Refresh",
"usageRetry": "Try again",
"usageFiveHour": "5h",
"usageSevenDay": "7d",
"usageResets": "Resets {{time}}",
"usageHint": "Asks Anthropic what this account has spent. Refreshes this profile's stored login token to do it.",
"title": "Claude Code profiles",
"openButton": "Switch profile",
"subtitle": "A profile is one Anthropic account - its own quota. Switching swaps only the login (credentials + account identity); skills, subagents, memory, plugins, marketplaces, MCP servers and settings all stay exactly as they are.",
"warning": "Close your running Claude Code sessions before switching - a live session rewrites the config on exit and would put the old account back.",
"activeLabel": "Logged in now",
"noActive": "No Claude account is logged in on this machine.",
"unsavedActive": "This account is not saved as a profile yet - save it, otherwise you cannot switch away without losing its credentials.",
"saveButton": "Save this account as a profile",
"saveSuccess": "Saved the account you are logged in as. Click its name to rename it.",
"empty": "No profiles saved yet - save the account you are logged in as to get started.",
"activeBadge": "active",
"switchButton": "Switch to",
"switching": "Switching…",
"switchSuccess": "Switched to profile \"{{name}}\". Start a new Claude Code session to pick it up.",
"deleteButton": "Delete profile",
"deleteSuccess": "Deleted profile \"{{name}}\".",
"savedAt": "Saved {{time}}",
"loginHint": "Add another account by logging in from a terminal first:",
"saving": "Saving…",
"renameLabel": "Profile name",
"renameHint": "Click to rename",
"renameSuccess": "Renamed to \"{{name}}\"."
},
"explain": {
"hooks": {
"title": "Editing hooks writes settings.json",
"body": "Hooks live in the `hooks` block of the `settings.json` files Claude Code writes to constantly. Edit saves only the event you changed, backs the file up first, and leaves every other key alone — but a `claude` session already running keeps its old hooks until it restarts. Take care with the dashboard`s own ingestion entries (the `hook-handler.js` commands below).",
"howTo": "You can also edit them with:",
"cmd1": "claude config /hooks",
"cmd1Note": "Interactive hook editor inside Claude Code",
"cmd2": "$EDITOR ~/.claude/settings.json",
"cmd2Note": "Hand-edit the user-level hooks block",
"cmd3": "$EDITOR .claude/settings.json",
"cmd3Note": "Hand-edit the project-level hooks block"
},
"settings": {
"title": "Editing settings merges one key at a time",
"body": "These JSON files are rewritten by the live `claude` CLI on every model change, theme toggle, plugin enable, etc. Saving here re-reads the file and writes only the keys you changed (after a timestamped backup), so a concurrent CLI write loses nothing else — but a running session may not pick the change up until it restarts.",
"howTo": "You can also edit them with:",
"cmd1": "claude config set <key> <value>",
"cmd1Note": "Set an individual key safely",
"cmd2": "/config",
"cmd2Note": "Open the interactive config UI inside the CLI",
"cmd3": "$EDITOR ~/.claude/settings.json",
"cmd3Note": "Hand-edit (only when no `claude` process is running)"
},
"plugins": {
"title": "Plugins run through the `claude` CLI",
"body": "Plugins are bundles with their own registry — `installed_plugins.json` plus install paths under `plugins/cache/`. The buttons here run the matching `claude plugin …` command on this machine, so the registry stays consistent. Installing a plugin means running third-party code: only add marketplaces you trust.",
"install": "Install a plugin:",
"installCmd": "claude plugin install <marketplace>/<plugin>",
"uninstall": "Uninstall this plugin:",
"uninstallButton": "Copy uninstall command"
},
"mcp": {
"title": "MCP servers are managed by the CLI",
"body": "MCP server config lives inside `~/.claude.json`, the same file the live CLI writes to constantly. Concurrent writes from the dashboard would corrupt project state, so add/remove flow goes through Claude Code itself.",
"list": "List configured servers:",
"listCmd": "claude mcp list",
"add": "Add a server:"
},
"marketplaces": {
"title": "Marketplaces are where plugins come from",
"body": "A marketplace is a git repo (or local folder) with a `.claude-plugin/marketplace.json` listing the plugins it offers. Adding one registers it in `known_marketplaces.json` and clones it locally; its plugins then appear on the Plugins tab, ready to install. Removing one does not uninstall plugins you already installed from it."
}
},
"snippet": {
"copy": "Copy",
"copied": "Copied"
},
"updateAll": {
"title": "Update everything",
"help": "Refreshes every marketplace, then updates all installed plugins, then tells the Claude Code sessions this dashboard has open to pick up the changes. AgentHub itself goes last, because updating it restarts this dashboard.",
"button": "Update all",
"working": "Updating…",
"started": "Update-all started for {{count}} plugin(s).",
"failed": "Could not start the update.",
"reloadButton": "Reload sessions",
"reloaded": "Reload sent to {{count}} open session(s).",
"reloadedNone": "No open Claude Code session to reload.",
"reloadedCount": "— {{count}} session(s)",
"restartWarning": "Keep this tab open. If AgentHub itself is updated, the dashboard restarts at the end and this page reconnects on its own.",
"abandoned": "The previous batch stopped without finishing — most likely the machine restarted. Run it again.",
"bootstrapFailed": "The dashboard was stopped but did not come back: {{error}}. Run /agenthub-update to recover."
},
"manage": {
"installTitle": "Install a plugin",
"installPlaceholder": "owner/repo, https://… or plugin@marketplace",
"installButton": "Add",
"installHelp": "Paste a GitHub repo, URL or local path to register its marketplace, or type <plugin>@<marketplace> to install a plugin directly. Runs the `claude plugin` CLI on this machine.",
"install": "Install",
"installed": "Installed {{name}}.",
"availableTitle": "Available from your marketplaces",
"cliUnavailable": "Could not list available plugins: {{message}}",
"working": "Working…",
"enable": "Enable",
"enabled": "Enabled {{name}}.",
"disable": "Disable",
"disabled": "Disabled {{name}}.",
"update": "Update",
"updated": "Updated {{name}}.",
"uninstall": "Uninstall",
"confirmUninstall": "Click again to uninstall",
"uninstalled": "Uninstalled {{name}}.",
"remove": "Remove",
"confirmRemove": "Click again to remove",
"addMarketplaceTitle": "Add a marketplace",
"addMarketplacePlaceholder": "owner/repo, https://github.com/… or /absolute/path",
"addMarketplaceButton": "Add",
"addMarketplaceHelp": "Registers the marketplace with `claude plugin marketplace add`; its plugins then show up on the Plugins tab.",
"marketplaceAdded": "Added marketplace {{name}}.",
"marketplaceUpdated": "Updated marketplace {{name}}.",
"marketplaceRemoved": "Removed marketplace {{name}}.",
"addMcpTitle": "Add an MCP server",
"addMcpNamePlaceholder": "name",
"addMcpTransportStdio": "Command (stdio)",
"addMcpTransportHttp": "URL (http)",
"addMcpCommandPlaceholder": "npx -y @modelcontextprotocol/server-github",
"addMcpUrlPlaceholder": "https://mcp.example.com",
"addMcpButton": "Add",
"addMcpHelp": "Runs `claude mcp add`. \"This project\" scopes the server to the current checkout — the CLI's separate `project` scope (a shared `.mcp.json`) isn't offered here because this dashboard can't see servers stored there.",
"mcpAdded": "Added MCP server {{name}}.",
"mcpRemoved": "Removed MCP server {{name}}.",
"hookEvent": "Event name (e.g. PreToolUse)",
"hookAddEvent": "Add event",
"hookRemoveEvent": "Remove event",
"hookAddEntry": "Add hook",
"hookRemoveEntry": "Remove hook",
"hookBadEvent": "“{{event}}” is not a valid event name.",
"hookDupEvent": "Event {{event}} is listed twice.",
"hookEmptyCommand": "Every hook in {{event}} needs a command.",
"hooksSaved": "Hooks saved to {{file}}.",
"hookUneditable": "Left untouched (not in the editable shape): {{events}}",
"settingsKey": "Key",
"settingsKeyPlaceholder": "key or dotted.path",
"settingsValue": "Value (JSON)",
"settingsAddKey": "Add key",
"settingsRemoveKey": "Remove key",
"settingsEmptyKey": "A key name cannot be empty.",
"settingsDupKey": "Key {{key}} is listed twice.",
"settingsBadJson": "Value of {{key}} is not valid JSON.",
"settingsSaved": "Settings saved to {{file}}.",
"settingsHelp": "Values are JSON: \"opus\", true, 42, [\"a\"], {\"k\":1}. Only the keys you change are written; the rest of the file is left as-is.",
"settingsRedactedKeys": "Not editable here because their values are redacted: {{keys}}"
}
}