783b7f4101
A script's claude -p in a temp folder (the SG Flow eval runner strips the pane's env) had no workspace, so its spend reached nobody's Today, the Users page or a spend quota — ~$57 of a $74 day was missing from the status bar. sessions.account records the Linux account a session ran as (the hook's peer uid, else its folder for poller-made and old rows); a session no workspace owns is owned by that account's user — a member's to them, the host's to the admin ticked 'Owns this server's host account' (or the only admin). Workspace ownership still wins.
453 lines
22 KiB
JSON
453 lines
22 KiB
JSON
{
|
||
"title": "Users",
|
||
"description": "Every account on this server, with its workspaces, sessions and recent usage.",
|
||
"name": "User",
|
||
"role": "Role",
|
||
"workspaces": "Workspaces",
|
||
"sessions": "Sessions",
|
||
"today": "Today",
|
||
"last7d": "7 days",
|
||
"last30d": "30 days",
|
||
"storage": "Storage",
|
||
"storageHint": "{{files}} files · measured {{at}}",
|
||
"storagePartial": "at least — part of the folder could not be read in time",
|
||
"storageNone": "No home folder of their own",
|
||
"storageMeasuring": "Measuring…",
|
||
"disabled": "disabled",
|
||
"you": "you",
|
||
"tokens": "{{n}} tokens",
|
||
"actions": "Actions",
|
||
"roles": {
|
||
"admin": "Admin",
|
||
"analyst": "Analyst",
|
||
"developer": "Developer"
|
||
},
|
||
"roleHint": {
|
||
"admin": "Everything, including this server's configuration and every user's data",
|
||
"analyst": "Sees every user's data; works only in their own workspaces, changes no settings",
|
||
"developer": "Only their own workspaces; changes no settings"
|
||
},
|
||
"add": "Add user",
|
||
"username": "Username",
|
||
"usernameHint": "Letters, digits, '.', '_' or '-'",
|
||
"password": "Password",
|
||
"passwordHint": "Any starting password — they choose their own at first sign-in",
|
||
"newPassword": "New password",
|
||
"changeRole": "Change role",
|
||
"disable": "Disable",
|
||
"enable": "Enable",
|
||
"resetPassword": "Reset password",
|
||
"assignWorkspace": "Give a workspace",
|
||
"workspace": "Workspace",
|
||
"noOwner": "no owner",
|
||
"ownedBy": "owned by {{name}}",
|
||
"noWorkspaces": "There are no workspaces yet.",
|
||
"yourPassword": "Your password",
|
||
"yourPasswordHint": "Type your own password to confirm this change.",
|
||
"save": "Save",
|
||
"dialog": {
|
||
"add": "Add a user",
|
||
"role": "Change {{name}}'s role",
|
||
"disable": "Disable {{name}}?",
|
||
"disableBody": "{{name}} is signed out everywhere and cannot sign in until enabled again. Their workspaces and history stay.",
|
||
"enable": "Enable {{name}}?",
|
||
"password": "Reset {{name}}'s password",
|
||
"passwordBody": "{{name}} is signed out everywhere and signs in with the new password.",
|
||
"workspace": "Give {{name}} a workspace",
|
||
"workspaceBody": "The workspace's sessions and costs move to {{name}}. A developer sees only their own workspaces."
|
||
},
|
||
"done": {
|
||
"created": "{{name}} added",
|
||
"role": "{{name}} is now {{role}}",
|
||
"disabled": "{{name}} disabled",
|
||
"enabled": "{{name}} enabled",
|
||
"password": "{{name}}'s password reset",
|
||
"workspace": "Workspace given to {{name}}",
|
||
"updated": "{{name}} updated",
|
||
"deleted": "{{name}} was deleted."
|
||
},
|
||
"errors": {
|
||
"EBADIMAGE": "Only a PNG, JPEG, GIF or WebP picture",
|
||
"ETOOBIG": "The picture must be at most 1 MB",
|
||
"EBADURL": "Enter an https:// link to a picture.",
|
||
"EPRIVATEURL": "That link points to a private or local address.",
|
||
"EFETCH": "Could not download the picture from that link.",
|
||
"EREAUTH": "Your password is wrong.",
|
||
"ETOOMANY": "Too many wrong passwords. Try again in 15 minutes.",
|
||
"ESELF": "You cannot change your own role or disable yourself.",
|
||
"EEXISTS": "That username is taken.",
|
||
"EBADUSER": "Username: letters, digits, '.', '_' or '-' (up to 64).",
|
||
"EBADPASSWORD": "Password cannot be empty.",
|
||
"EBADEMAIL": "That email address does not look valid.",
|
||
"ENAMETAKEN": "Another account already uses that name. Pick one that is yours.",
|
||
"EBADFIELD": "One of the values is not valid.",
|
||
"ENOLANE": "That workspace no longer exists.",
|
||
"ENOTOWNED": "That workspace is not this user's any more.",
|
||
"EOWNERFOLDER": "That workspace's folder belongs to another user's account.",
|
||
"EBADROLE": "Unknown role.",
|
||
"ELOCALMODE": "Accounts are managed in server mode only.",
|
||
"ELASTADMIN": "The last admin cannot be deleted, demoted or disabled.",
|
||
"EWEAKPASSWORD": "The new password does not meet every rule (or is the current one).",
|
||
"EPWCHANGE": "Choose your own password first.",
|
||
"EBADQUOTA": "Enter a positive dollar limit and a period of a day or 5 hours."
|
||
},
|
||
"readOnly": "Analysts can view accounts but not change them.",
|
||
"auditTitle": "Audit log",
|
||
"auditDescription": "Account changes made here, and each time an admin or analyst opened a session a developer owns.",
|
||
"auditEmpty": "Nothing recorded yet.",
|
||
"activeCount": "{{n}} active",
|
||
"cost30d": "Cost · 30 days",
|
||
"displayName": "Display name",
|
||
"displayNameHint": "Shown beside the username. Optional.",
|
||
"email": "Email",
|
||
"edit": {
|
||
"button": "Edit user",
|
||
"title": "Edit {{name}}",
|
||
"created": "Created",
|
||
"lastLogin": "Last sign-in",
|
||
"never": "Never",
|
||
"logins": "Active sign-ins",
|
||
"profile": "Profile",
|
||
"access": "Access",
|
||
"status": "Status",
|
||
"active": "Active",
|
||
"statusHint": "A disabled user cannot sign in; their workspaces and history stay.",
|
||
"hostAccount": "Owns this server's host account",
|
||
"hostAccountHint": "Sessions run as the server's own Linux account outside every workspace (a script's claude -p, a CLI in a plain terminal) count toward this admin's spend. At most one admin; with none marked, the only admin.",
|
||
"selfRole": "You cannot change your own role.",
|
||
"selfDisable": "You cannot disable yourself.",
|
||
"password": "Password",
|
||
"passwordHint": "Leave blank to keep the current one. A new one signs them out everywhere, and they choose their own at their next sign-in.",
|
||
"show": "Show password",
|
||
"hide": "Hide password",
|
||
"copy": "Copy password",
|
||
"generate": "Generate",
|
||
"loading": "Loading…",
|
||
"noOwned": "Owns no workspace.",
|
||
"undo": "Undo",
|
||
"removeWorkspace": "Remove {{name}}",
|
||
"removeWorkspaceHint": "The workspace is left with no owner",
|
||
"addWorkspace": "Add workspace",
|
||
"chooseWorkspace": "Choose a workspace…",
|
||
"sessions": "Sign-ins",
|
||
"signOut": "Sign out everywhere",
|
||
"signOutHint": "Ends this user's {{n}} active sign-in(s); they sign in again with their password.",
|
||
"noChanges": "No changes yet.",
|
||
"ownPasswordHint": "Leave blank to keep the current one. Your other sign-ins end."
|
||
},
|
||
"pool": {
|
||
"title": "Account pool",
|
||
"description": "Each pool holds accounts of every AI tool (Claude Code, Codex, Cursor) and the members who run on them. A member's new session takes the least-used account of their pool, so nobody signs in per user.",
|
||
"refresh": "Re-read quotas",
|
||
"add": "Add account",
|
||
"account": "Account",
|
||
"livePanes": "Live",
|
||
"quota": "Quota",
|
||
"spend": "5 hours",
|
||
"spend7d": "{{cost}} · {{tokens}} tokens in 7 days",
|
||
"tokens": "{{tokens}} tokens",
|
||
"added": "added {{at}}",
|
||
"expired": "expired",
|
||
"full": "full",
|
||
"name": "Name",
|
||
"nameHint": "Any label you will recognise: letters, digits, '.', '_' or '-'",
|
||
"remove": "Remove {{name}}",
|
||
"removeHint": "New sessions stop using this account. Sessions already running on it keep running.",
|
||
"removeButton": "Remove",
|
||
"done": {
|
||
"added": "{{name}} added to the pool",
|
||
"removed": "{{name}} removed from the pool"
|
||
},
|
||
"errors": {
|
||
"EREAUTH": "Your password is wrong.",
|
||
"ETOOMANY": "Too many wrong passwords. Try again in 15 minutes.",
|
||
"EBADNAME": "Name: 1–64 letters, digits, '.', '_' or '-'.",
|
||
"EBADTOKEN": "That is not a valid token for this tool.",
|
||
"EEXISTS": "An account with that name is already in the pool.",
|
||
"ENOACCOUNT": "That account is no longer in the pool.",
|
||
"ELOCALMODE": "In local mode the pool is changed from the host's shell (agenthub accounts).",
|
||
"EACTIVE": "This server's Claude Code keeps that login in the macOS Keychain. Switch it to another profile first.",
|
||
"ENOTFOUND": "That saved login no longer exists.",
|
||
"ESTALE": "That login was already refreshed elsewhere. Log in again and save it anew.",
|
||
"EUPSTREAM": "Anthropic could not be reached. Try again.",
|
||
"ENOUSER": "That user no longer exists.",
|
||
"ENOGROUP": "That group no longer exists."
|
||
},
|
||
"source": "From",
|
||
"sources": {
|
||
"profile": "A saved profile (Settings → AI tools → Profiles)",
|
||
"credentials": "Paste .credentials.json / Keychain",
|
||
"token": "claude setup-token"
|
||
},
|
||
"sourceHint": {
|
||
"profile": "The login is moved into the pool: the profile leaves the switcher, and the server writes it into each user's home when their session starts.",
|
||
"credentials": "From ~/.claude/.credentials.json, or on a Mac `security find-generic-password -s \"Claude Code-credentials\" -w`. Do not keep using that login where you copied it from — two copies log each other out.",
|
||
"token": "A one-year token from `claude setup-token`, given to every session as an environment variable.",
|
||
"codex": "An OpenAI API key (sk-…), or the whole ~/.codex/auth.json after `codex login` with a ChatGPT account.",
|
||
"cursor": "A Cursor API key from the Cursor dashboard (Integrations → API keys)."
|
||
},
|
||
"profile": "Profile",
|
||
"profileHint": "Saved in Settings → AI tools → Profiles. The one this server's own CLI is logged into can be moved too: the server keeps running on it.",
|
||
"chooseProfile": "Choose a saved login…",
|
||
"noProfiles": "No saved profiles — save one in Settings → AI tools → Profiles",
|
||
"loadingProfiles": "Loading…",
|
||
"activeHere": "in use on this server — keeps working",
|
||
"nameFromProfile": "Leave blank to use the profile's name",
|
||
"secret": {
|
||
"credentials": "Credentials JSON",
|
||
"token": "Token",
|
||
"codex": "API key or auth.json",
|
||
"cursor": "Cursor API key"
|
||
},
|
||
"secretHint": {
|
||
"credentials": "The whole file: {\"claudeAiOauth\": {…}}",
|
||
"token": "The sk-ant-… that `claude setup-token` printed.",
|
||
"codex": "An OpenAI API key (sk-…), or the whole ~/.codex/auth.json after `codex login` with a ChatGPT account.",
|
||
"cursor": "Create one in the Cursor dashboard under Integrations → API keys."
|
||
},
|
||
"refreshFailed": "refresh failed",
|
||
"pinned": "Used by: {{users}}",
|
||
"loadingUsers": "Loading…",
|
||
"pinDone": {
|
||
"own-login": "{{user}} signed in with their own login, which was left alone",
|
||
"expired": "{{account}} has expired — {{user}}'s new sessions fall back to the least-used account"
|
||
},
|
||
"edit": "Edit {{name}}",
|
||
"editHint": "Tick the users whose sessions run on this account instead of the least-used one — even when it is full. A user on another account moves here. A Claude login is written into their home at once: sessions already running move to it at their next login check, with no restart. A setup-token or Codex account applies to new sessions. Untick to send a user back to the least-used account.",
|
||
"save": "Save",
|
||
"users": "Users on this account",
|
||
"noUsers": "No users yet.",
|
||
"onAccount": "now on {{account}}",
|
||
"editDone": "{{name}} saved",
|
||
"profilesLink": "Profiles in Settings",
|
||
"addFor": "Add {{tool}} account",
|
||
"type": "Type",
|
||
"about": {
|
||
"claude": "New Claude Code sessions run on these accounts. A setup-token goes in as an environment variable; a real login is written into each user's home by the server and refreshed by it.",
|
||
"codex": "New Codex sessions (not on an AI Proxy) run on these accounts. An OpenAI API key goes in as an environment variable; a ChatGPT login is written into each user's own Codex home.",
|
||
"cursor": "New Cursor CLI sessions run on these Cursor API keys, given to the session as CURSOR_API_KEY — it outranks the user's own `cursor-agent login` for that session only. Cursor reports no usage or quota here, so the account with the fewest live sessions is picked."
|
||
},
|
||
"notInstalled": "{{tool}} is not installed on this server yet.",
|
||
"emptyFor": "No {{tool}} accounts yet. Until you add one, each user's {{tool}} session needs that user's own sign-in.",
|
||
"kindShort": {
|
||
"token": "setup-token",
|
||
"login": "Login",
|
||
"apikey": "API key",
|
||
"chatgpt": "ChatGPT login"
|
||
},
|
||
"omp": {
|
||
"badgeOn": "shared",
|
||
"about": "Oh My Pi has no account pool: it shares this server's own omp login instead. Sign the host account in with `omp` (then /login), turn sharing on, and every user's omp session runs on it through omp's own gateway — with a key that works only while its pane runs.",
|
||
"off": "Sharing is off: each user's omp session uses that user's own login.",
|
||
"unavailable": "Oh My Pi has no account pool. Its login can be shared only on a server where every user has their own Linux account (server mode with per-user accounts); here each user's omp session uses that user's own login."
|
||
},
|
||
"none": {
|
||
"title": "{{tool}} has no account pool",
|
||
"reason": {
|
||
"antigravity": "Antigravity signs in with a Google account and keeps that login in the system keyring; it takes no key AgentHub could hand a session. Each user signs in to agy themselves.",
|
||
"default": "AgentHub cannot hand {{tool}} a shared login, so each user signs in to it themselves."
|
||
}
|
||
},
|
||
"liveCount_one": "{{count}} live",
|
||
"liveCount_other": "{{count}} live",
|
||
"savedProfiles": {
|
||
"title": "Saved profiles you can share",
|
||
"empty": "No saved profiles for this tool. Save one in Settings → AI tools → Profiles, then share it here.",
|
||
"activeHere": "in use on this server",
|
||
"share": "Share to pool",
|
||
"shareNamed": "Share {{name}} to the pool"
|
||
},
|
||
"groups": {
|
||
"title": "Pools",
|
||
"description": "Members in no pool, and accounts in no pool, make up the shared pool.",
|
||
"new": "New pool",
|
||
"empty": "No groups yet — every user shares every account.",
|
||
"members_one": "{{count}} member",
|
||
"members_other": "{{count}} members",
|
||
"edit": "Edit group {{name}}",
|
||
"delete": "Delete pool {{name}}",
|
||
"deleteHint": "Its members and accounts go back to the shared pool. No account is removed.",
|
||
"noAccounts": "none — members sign in themselves",
|
||
"saved": "Group {{name}} saved",
|
||
"deleted": "Pool {{name}} deleted",
|
||
"hint": "Tick the members and the accounts they run on. A user belongs to one group, so ticking one moves them here. An account can serve several groups.",
|
||
"name": "Pool name",
|
||
"memberList": "Members",
|
||
"inGroup": "now in {{group}}",
|
||
"accountList": "Accounts",
|
||
"noneInPool": "No accounts of this tool in the pool.",
|
||
"shared": "Shared pool"
|
||
},
|
||
"window": {
|
||
"5h": "5 hours",
|
||
"wk": "Week"
|
||
},
|
||
"resetsIn": "resets in {{time}} · {{at}}",
|
||
"members": {
|
||
"title": "Members",
|
||
"filter": "Show members",
|
||
"all": "All",
|
||
"noGroup": "No pool",
|
||
"search": "Search members",
|
||
"tickShown": "Tick all {{count}}",
|
||
"noneShown": "No member matches."
|
||
},
|
||
"board": {
|
||
"howTo": "Drag an account or a member between pools; drop one on New pool to split it off, or drag a pool's only account into another pool to merge them. Nothing is saved until Save.",
|
||
"sharedHint": "Members and accounts in no pool",
|
||
"toShared": "Send {{name}} back to the shared pool",
|
||
"removeAccount": "Send {{name}} back to the shared pool",
|
||
"moveHere_one": "Move {{count}} here",
|
||
"moveHere_other": "Move {{count}} here",
|
||
"noMembers": "No members",
|
||
"noSharedAccounts": "No account is left for the shared pool.",
|
||
"dropMembers": "Drop members here",
|
||
"untitled": "New pool",
|
||
"new": "not saved yet",
|
||
"pick": "Pick members of {{name}}",
|
||
"pickHint": "Filter by role or by \"No pool\", tick who belongs here. A member is in one pool, so ticking one moves them here. Applied on the board — Save sends it.",
|
||
"apply": "Apply",
|
||
"addAccount": "Move an account into {{name}}",
|
||
"addAccountOption": "+ Move an account or saved profile here…",
|
||
"profilesOf": "Saved {{tool}} profiles — moved into the pool on Save",
|
||
"profilePending": "A saved profile: it is moved into the pool when you save",
|
||
"pending_one": "{{count}} unsaved change",
|
||
"pending_other": "{{count}} unsaved changes",
|
||
"needsName": "Every pool needs a name.",
|
||
"discard": "Discard",
|
||
"saveTitle": "Save the pools",
|
||
"saveHint": "Type your own password once to apply every change below.",
|
||
"summaryProfile": "Move the saved profile {{name}} into the pool",
|
||
"summaryNew": "Create {{name}}: {{count}} member(s), {{accounts}} account(s)",
|
||
"summaryGroup": "Set {{name}}: {{count}} member(s), {{accounts}} account(s)",
|
||
"saved": "Pools saved",
|
||
"dropAccounts": "Drag accounts here",
|
||
"noAccounts": "No accounts",
|
||
"accountsCount_one": "{{count}} account",
|
||
"accountsCount_other": "{{count}} accounts",
|
||
"mergeHint": "Drop to merge {{from}} into {{into}}",
|
||
"merged": "{{from}} merged into {{into}} — Save to apply",
|
||
"summaryMerge": "Merge {{from}} into {{into}}: pool {{from}} is deleted",
|
||
"newDrop": "Drop here to split it into a pool of its own",
|
||
"newHint": "Or drag an account or a member here to split it off"
|
||
},
|
||
"addAccount": "Add account",
|
||
"otherTools": "Other AI tools"
|
||
},
|
||
"delete": {
|
||
"button": "Delete user",
|
||
"title": "Delete {{name}}?",
|
||
"body": "This deletes {{name}} for good: their login, {{count}} workspace(s), and their Linux account with the whole home folder (/srv/agenthub/users/{{user}}) — every file and all source code in it. It cannot be undone. Session history and the audit log stay.",
|
||
"confirm": "Delete for good",
|
||
"needsPassword": "Enter your own password below first."
|
||
},
|
||
"tmux": {
|
||
"title": "Members' tmux",
|
||
"description": "Each member's own tmux server keeps the version it started with until its last pane closes. Installed: tmux {{version}}.",
|
||
"refresh": "Refresh",
|
||
"notMatched": "Run `agenthub server install-system` once: until then an older member server is asked with the installed tmux, which can leave it stuck at 100% CPU.",
|
||
"empty": "No member has a tmux server running.",
|
||
"user": "User",
|
||
"version": "tmux",
|
||
"sessions": "Sessions",
|
||
"agents": "Agents",
|
||
"stuck": "not answering",
|
||
"outdated": "older than installed",
|
||
"since": "since {{at}}",
|
||
"working_one": "{{count}} working",
|
||
"working_other": "{{count}} working",
|
||
"idle": "idle",
|
||
"restart": "Restart {{name}}'s tmux",
|
||
"restartIdle_one": "Restart {{count}} idle member",
|
||
"restartIdle_other": "Restart {{count}} idle members",
|
||
"restartIdleTitle": "Restart idle members' tmux",
|
||
"restartHint": "Every pane of {{name}} closes ({{count}} sessions). Their Claude sessions resume from the workspace, and the next start runs the installed tmux.",
|
||
"restartHintBusy": "An agent of {{name}} is working right now and will be stopped. Every pane of theirs closes ({{count}} sessions); their Claude sessions resume from the workspace.",
|
||
"restartIdleHint": "Restarts the tmux of every member on an older version with no agent working: {{names}}. Their panes close; their Claude sessions resume from the workspace.",
|
||
"restartButton": "Restart",
|
||
"done": "{{name}}'s tmux restarted",
|
||
"doneIdle": "Restarted: {{names}}",
|
||
"errors": {
|
||
"ETMUXSTUCK": "The server did not stop. Run the `sudo kill -9` command shown, as root, on the server."
|
||
},
|
||
"sessionsCount_one": "{{count}} session",
|
||
"sessionsCount_other": "{{count}} sessions"
|
||
},
|
||
"rowMenu": {
|
||
"openHome": "Open home in Files",
|
||
"copyUsername": "Copy username",
|
||
"copyEmail": "Copy email"
|
||
},
|
||
"mustChange": "New password due",
|
||
"mustChangeHint": "Signed in with a password an admin gave; must choose their own before using AgentHub",
|
||
"passwordRules": {
|
||
"length": "At least {{min}} characters",
|
||
"lower": "A lower-case letter",
|
||
"upper": "An upper-case letter",
|
||
"digit": "A digit",
|
||
"symbol": "A symbol (e.g. ! - _ @)",
|
||
"username": "Does not contain the username"
|
||
},
|
||
"detail": {
|
||
"open": "Open {{name}}'s details",
|
||
"lastLogin": "Last sign-in",
|
||
"lastSession": "Last activity",
|
||
"never": "never",
|
||
"spendDaily": "Spend · last 30 days",
|
||
"noUsage": "No spend in the last 30 days.",
|
||
"pool": "Account pool & quota",
|
||
"poolPinned": "pinned to {{account}}",
|
||
"poolChosen": "chose {{account}}",
|
||
"poolGroup": "group {{name}}",
|
||
"poolShared": "shared pool",
|
||
"poolNone": "No account in this tool's pool.",
|
||
"poolNotAllowed": "no longer allowed",
|
||
"poolTotal7d": "Account total 7 days: {{cost}}",
|
||
"noPanes": "Nothing running.",
|
||
"recentTitle": "Recent sessions",
|
||
"failed": "Could not load this user",
|
||
"activeLabel": "Running now",
|
||
"activeValue": "{{sessions}} sessions · {{panes}} panes",
|
||
"nowTitle": "Running now",
|
||
"poolTheirs7d": "theirs 7 d {{cost}}"
|
||
},
|
||
"activity": "Activity",
|
||
"spend": "Spend today",
|
||
"spendSub": "7 d {{week}} · 30 d {{month}}",
|
||
"sessionsN": "{{n}} sessions",
|
||
"workspacesN": "{{n}} workspaces",
|
||
"tmuxCol": "tmux",
|
||
"quota": {
|
||
"title": "Spend quota",
|
||
"limit": "Limit in dollars",
|
||
"period": "Period",
|
||
"periods": {
|
||
"day": "per day (from local midnight)",
|
||
"5h": "per 5 hours (sliding)"
|
||
},
|
||
"per": {
|
||
"day": "{{limit}} / day",
|
||
"5h": "{{limit}} / 5 h"
|
||
},
|
||
"used": "{{spend}} of {{limit}}",
|
||
"defaultTag": "(default)",
|
||
"none": "No quota",
|
||
"blockedUntil": "Used up — no new session and no prompt until {{at}}",
|
||
"cardTitle": "Default spend quota",
|
||
"cardDescription": "Every user without a quota of their own gets this one. Once it is used up they can start no session and their prompts are refused until it resets; a pane no hook can stop (Antigravity, Cursor, Codex without trusted hooks, omp on its own login) is ended.",
|
||
"noDefault": "No default — no limit",
|
||
"editDefault": "Edit",
|
||
"defaultDialog": "Default spend quota",
|
||
"defaultOn": "Limit what each user may spend",
|
||
"defaultSaved": "Default spend quota saved",
|
||
"enforceHint": "Over the quota: no new session, Claude Code and Codex prompts refused, other AI tools' panes ended — until it resets.",
|
||
"modes": {
|
||
"defaultOf": "Default ({{quota}})",
|
||
"defaultNone": "Default (no limit)",
|
||
"unlimited": "No limit",
|
||
"custom": "Their own limit"
|
||
},
|
||
"now": "Now: {{spend}} of {{limit}}"
|
||
}
|
||
}
|