85187dfc78
The Memory tab could only show this machine's user memory and the
dashboard's own project file. Setting up a project you had not run
through the dashboard meant opening a terminal — `PUT /file`'s
"project" scope always resolves against the server's cwd, on purpose.
Add one narrow route per tool that writes into the directory you name:
CLAUDE.md for Claude Code, AGENTS.md for Codex, both through the same
`project-memory.js`. Being the only write path that honours a
caller-supplied directory, it pays for that:
- the directory must be absolute and already exist — nothing is
created for you;
- the filename comes from the route, never from the body;
- an existing file, symlink included, is a 409 — this can only
create, never overwrite;
- it sits behind the loopback-Origin guard /api/run uses, so a page
in the user's browser cannot plant agent instructions in a project
directory. That guard moves to lib/same-origin.js to be shared.
The modal takes the dashboard's known project dirs as suggestions on a
free-text input rather than a closed list: a project it has never seen
is exactly the case this exists for.
Mutation-checked: dropping the origin guard, and swapping lstat for
stat, each fail a test.
369 lines
17 KiB
JSON
369 lines
17 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"
|
|
},
|
|
"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": {
|
|
"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"
|
|
},
|
|
"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}}"
|
|
}
|
|
}
|