CLI

CLI

Manage LangSync from the terminal with norcube / nrc. Namespaces, terms, translations, languages, prompts, the glossary, API keys, CSV import, the audit log and project sync.

Not verified yet

The Norcube CLI (norcube, or its short alias nrc) covers all of LangSync from the terminal. It has two layers:

  • Resource commands: namespaces, terms, translations, languages, prompts, glossary, api-keys and audit, for direct management. Covered on this page. (The older names namespace, mark and lang keep working.)
  • Project sync — init, sync, pull — pin a Git repository to one or more namespaces and reconcile local JSON translation files against the server. Covered in Project sync.

Every flag of every command is in the generated CLI reference.

Every command supports --org <slug> to override the organization, --profile <name> to use another profile (for example a second account), --output table|json|yaml|text for scripting-friendly output and --query to pick fields (see output and scripting). Commands that would prompt interactively (pickers, confirmations) accept flags instead, so everything works in CI — destructive commands require --yes when there's no TTY to confirm on.

Setup

nrc login                 # OAuth login in your browser
nrc org use <slug>        # set the profile's organization
nrc langsync namespaces list   # sanity check

Authentication uses your user session (tokens are stored per profile in the OS keyring and refreshed automatically) — the CLI does not use API keys; those are for the read-only Public API. If commands start failing with authentication errors, re-run nrc login.

Namespaces

# list namespaces in the profile's organization
nrc langsync namespaces list

# create (name + default language required non-interactively)
nrc langsync namespaces create web --default-language en
nrc langsync namespaces create marketing --default-language cs --context "Marketing site copy"

# partial update: only pass what you want to change
nrc langsync namespaces update web --rename web-app
nrc langsync namespaces update web --context "New description"
nrc langsync namespaces update web --default-language de
nrc langsync namespaces update web --default-prompt <prompt-id>   # "none" removes it

# delete — permanent, removes every mark and translation in it
nrc langsync namespaces delete web        # prompts; --yes to skip

namespace also answers to namespaces and ns. The list output shows name, default language, attached languages, context, and ID.

Marks (terms)

The CLI calls terms marks, matching the dashboard's dialogs. Where --namespace/-n is omitted in a terminal, a picker opens; in scripts, pass it explicitly.

# add a mark, optionally with its source value and AI translation
nrc langsync terms add -n web "Save changes"
nrc langsync terms add -n web "Email" --context "form label" --default-value "E-mail"
nrc langsync terms add -n web "Welcome" --default-value "Welcome" --auto-translate

# list marks, with the same filters the dashboard has
nrc langsync terms list -n web
nrc langsync terms list -n web --search Save
nrc langsync terms list -n web --has-untranslated
nrc langsync terms list -n web --untranslated-lang 17    # missing a specific language (by ID)

# pagination for big namespaces
nrc langsync terms list -n web --page-size 100 --cursor <cursor>
nrc langsync terms list -n web --all-pages --max-items 5000

# change a term's source text or context (translations are kept)
nrc langsync terms update 1234 -n web --mark "Save all changes"
nrc langsync terms update 1234 -n web --context "button in the settings dialog"

# delete by term ID (shown in list output); permanent
nrc langsync terms delete 1234 -n web --yes

The list's AI column counts the translations that are still exactly what AI translation produced; a person editing one clears its label. With -o json each translation carries the same flag as aiGenerated.

Import a CSV file

nrc langsync terms import strings.csv -n web --dry-run     # show the column mapping only
nrc langsync terms import strings.csv -n web
nrc langsync terms import export.csv -n web --column "String ID=mark" --column "Notes=ignore"
nrc langsync terms import strings.csv -n web --overwrite --auto-translate
nrc langsync terms import strings.csv -n web --wait        # wait until the server has finished

# check on an import later (the id is printed when it starts)
nrc langsync terms import status <import-id> -n web
nrc langsync terms import status <import-id> -n web --wait

The file needs a header row. Columns are matched by header: mark, key, term or source is the mark; context, description, comment or note is the context; a language code or name attached to the namespace (cs, Czech) holds that language's translations. Any other header must be mapped with --column "<header>=<mark|context|ignore|language code>"; the CLI refuses to guess and uploads nothing until every column is placed. Existing terms with the same mark are skipped unless --overwrite is set, and --auto-translate lets AI fill in the languages the file leaves empty. The import finishes on the server after the command returns: --wait waits for it, and terms import status shows how it's doing (prechecked, processing, completed or failed). With --wait, both exit 1 with the error code job_failed when the import failed, so a script can stop there. The dashboard's version is bulk import.

Translations

Languages are named by code (cs) or numeric ID and must be attached to the namespace.

# one term with its translation into each of the namespace's languages
nrc langsync translations get 1234 -n web
nrc langsync translations get 1234 -n web -o json --query "translations[?lang.code=='cs'].value | [0]"

# set one translation (clears the AI label: a person wrote it)
nrc langsync translations set 1234 cs "Uložit změny" -n web
nrc langsync translations set 1234 de --file welcome.de.txt -n web   # - reads stdin

# ask AI for a suggestion; --save stores it with its AI label
nrc langsync translations suggest 1234 cs -n web
nrc langsync translations suggest 1234 de -n web --from en --prompt <prompt-id> --save

# AI-translate everything still missing, in all or some languages
nrc langsync translations translate-missing -n web
nrc langsync translations translate-missing -n web --languages cs,de

get takes the numeric term ID from terms list; (AI) after a language marks a translation that is still exactly what AI produced (aiGenerated with -o json). suggest and translate-missing count towards your AI translation usage. translate-missing runs on the server after the command returns; follow it with nrc langsync terms list -n web --has-untranslated.

Custom prompts

nrc langsync prompts list
nrc langsync prompts get <prompt-id>           # full text
nrc langsync prompts create "Friendly tone" --text "Use an informal, friendly tone."
nrc langsync prompts create "Legal" --file prompts/legal.txt --private
nrc langsync prompts update <prompt-id> --name "Friendly, informal"
nrc langsync prompts update <prompt-id> --private=false   # share it with the organization
nrc langsync prompts delete <prompt-id> --yes

See custom prompts for how a namespace's default prompt and a per-run --prompt combine.

Glossary

nrc langsync glossary get
nrc langsync glossary items list
nrc langsync glossary items get <item-id>
nrc langsync glossary items create Norcube --keep --case-sensitive
nrc langsync glossary items create invoice --type noun --context "a bill sent to a customer"
nrc langsync glossary items translate <item-id> cs faktura
nrc langsync glossary items delete <item-id> --yes

# add a language the glossary covers (code or numeric ID)
nrc langsync glossary languages attach cs

--keep marks a term that is never translated (a product or brand name). --type is the word class: noun, verb, adjective, adverb, pronoun, preposition, conjunction, interjection, phrase, idiom or other (the default). other is what the API calls n/a: the CLI sends n/a, accepts --type n/a too, and shows other in tables and -o text, while -o json keeps the API's n/a.

glossary languages attach adds a language so entries can get an agreed translation into it with glossary items translate. Removing a language, creating the glossary and choosing its default language happen in the dashboard; see glossaries.

API keys

nrc langsync api-keys list
nrc langsync api-keys create --name production-web            # the value is printed once
nrc langsync api-keys create --name production-web -o text | gh secret set LANGSYNC_API_KEY
nrc langsync api-keys revoke <key-id> --yes

These are the API keys your applications use for the Public API, not credentials for the CLI. Revocation is immediate.

Audit log

nrc langsync audit list --since 7d
nrc langsync audit list --action apikey.created,apikey.deleted
nrc langsync audit list --target-type namespace --all-pages -o json

--since and --until take an RFC 3339 timestamp, a date (2026-10-28) or an age (24h, 7d). See audit log for the recorded actions.

--auto-translate asks the backend to AI-translate the new mark into every other language attached to the namespace — the same engine as auto-translate in the dashboard.

Languages

# list every language available to the org (KIND: shared | custom)
nrc langsync languages list
# or only what's attached to one namespace
nrc langsync languages list -n web

# attach / detach a language on a namespace (code or numeric ID)
nrc langsync languages add de -n web
nrc langsync languages remove de -n web --yes   # deletes that language's translations in the namespace

# org-scoped custom languages
nrc langsync languages create internal-en "Internal English"
nrc langsync languages delete <id> --yes        # refused while still attached anywhere

Detaching a language deletes its translations in that namespace (the marks themselves are untouched) — same behaviour as removal in the dashboard.

Organization resolution

Which organization a command hits is resolved in this order:

  1. --org <slug> — explicit override, always wins.
  2. NORCUBE_ORG, the same override from the environment.
  3. The organization pinned in the project's .langsync.json, when you're inside a project tree.
  4. The selected profile's organization (nrc org use).

The project pin (3) is what makes multi-org development safe: inside a client's repo, langsync commands hit that client's org no matter which organization your profile points at.

Errors you'll actually see

MessageFix
"no active organization. Run norcube org use <slug> or pass --org <slug>"Set the profile's organization or pass --org.
"namespace 'X' is not accessible to the active organization"Check the org (nrc whoami), the namespace's existence, and the exact case-sensitive spelling.
"no .langsync.json found in … — run norcube langsync init"You're running sync/pull outside an initialised project.
"config version N is newer than this CLI supports"norcube upgrade.
  • Project sync — init, sync, pull, and the .langsync.json reference.
  • Sync jobs — what the server does with a sync.

On this page