Command-line interface for the Open Concept Lab API. Search, browse, and manage concepts, mappings, sources, and collections from your terminal. Multi-server ready.
Designed for both humans and AI agents.
git clone https://github.com/OpenConceptLab/ocl-cli.git
cd ocl-cli
pip install .git clone https://github.com/OpenConceptLab/ocl-cli.git
cd ocl-cli
pip install -e ".[dev]"ocl --version
ocl --helpYou need an API token from app.openconceptlab.org:
# Store your token (prompts securely)
ocl login
# Verify authentication
ocl whoamiOr pass a token directly:
ocl --token YOUR_TOKEN whoamiOr set an environment variable:
export OCL_API_TOKEN=your_token_here
ocl whoami# Search for organizations
ocl org list WHO
# Search for sources
ocl repo list --owner CIEL --type source
# Search for concepts
ocl concept search malaria --owner CIEL --repo CIEL
# Get a specific concept with its cross-terminology mappings
ocl concept get CIEL CIEL 116128 --include-mappings
# Search for mappings (--owner/--repo scope the mapping's source)
ocl mapping search --owner CIEL --repo CIEL --to-concept 116128Use the -j flag (before the subcommand) for machine-readable JSON output:
ocl -j concept search malaria --owner CIEL --repo CIEL
ocl -j concept get CIEL CIEL 116128Search/list commands return a summary by default (compact, fast). Use --verbose to get full details (names, descriptions, extras, timestamps):
# Summary (default)
ocl concept search malaria --owner CIEL --repo CIEL
# Verbose — more columns, more data from API
ocl concept search malaria --owner CIEL --repo CIEL --verbose
# Debug — show HTTP requests on stderr
ocl -d concept search malaria --owner CIEL --repo CIELThe --verbose flag controls the OCL API's ?verbose=true parameter. With -j, it returns more fields in the JSON response.
ocl org list [QUERY] [--verbose] [--limit N] [--page N]
ocl org get ORG
ocl org members ORG [--limit N]
ocl org repos ORG [--type source|collection|all] [--verbose] [--limit N] [--page N]
# Organization management
ocl org create ORG_ID NAME [--company ...] [--website ...] [--location ...] [--public-access View|Edit|None]
ocl org delete ORG_ID [--yes]
ocl org add-member ORG USERNAME
ocl org remove-member ORG USERNAME [--yes]ocl user list [QUERY] [--verbose] [--limit N] [--page N]
ocl user get USERNAME
ocl user repos USERNAME [--type source|collection|all] [--verbose] [--limit N] [--page N]
ocl user orgs USERNAME [--limit N]Sources and collections are unified under ocl repo with a --type flag.
# Browse
ocl repo list [QUERY] [--owner OWNER] [--type source|collection|all] [--custom-validation-schema SCHEMA] [--updated-since YYYY-MM-DD] [--all-versions] [--verbose]
ocl repo get OWNER REPO [--type source|collection] [--repo-version VERSION]
ocl repo versions OWNER REPO [--type source|collection] [--updated-since YYYY-MM-DD]
# Create & update
ocl repo create OWNER REPO_ID NAME --type source|collection [options]
ocl repo update OWNER REPO [--name NAME] [--description DESC]
ocl repo version-create OWNER REPO VERSION_ID [--released/--no-released]
ocl repo version-update OWNER REPO VERSION_ID [--released/--no-released] [--match-algorithms es,llm]
# Enable vectorized matching on a new release
ocl repo version-update CIEL CIEL v2026-03-23 --match-algorithms es,llm
# Custom attributes
ocl repo extras OWNER REPO
ocl repo extra-set OWNER REPO KEY VALUE
ocl repo extra-del OWNER REPO KEY
Manage cached ZIP exports of repository versions (sources and collections). Exports contain the full JSON representation of a version — metadata, concepts, mappings, and references.
# Check if an export is available
ocl repo export status OWNER REPO VERSION --type source|collection
# Trigger export creation (if not already cached)
ocl repo export create OWNER REPO VERSION --type source|collection
# Download to a local file
ocl repo export download OWNER REPO VERSION --type source|collection -o FILENAME
# Delete a cached export
ocl repo export delete OWNER REPO VERSION --type source|collectionExample — download the latest CIEL release export:
ocl repo export status CIEL CIEL v2026-03-23 --type source
ocl repo export download CIEL CIEL v2026-03-23 --type source -o CIEL_v2026-03-23.zip# Search & browse
ocl concept search [QUERY] [--owner OWNER] [--repo REPO] [--concept-class CLASS]
ocl concept get OWNER SOURCE CONCEPT_ID [--repo-version VERSION] [--include-mappings] [--include-inverse-mappings]
ocl concept versions OWNER SOURCE CONCEPT_ID
ocl concept names OWNER SOURCE CONCEPT_ID [--verbose]
ocl concept descriptions OWNER SOURCE CONCEPT_ID [--verbose]
ocl concept extras OWNER SOURCE CONCEPT_ID
# Create & update
ocl concept create OWNER SOURCE CONCEPT_ID --concept-class CLASS --name NAME [--datatype TYPE]
ocl concept update OWNER SOURCE CONCEPT_ID [--concept-class CLASS] [--datatype TYPE]
ocl concept retire OWNER SOURCE CONCEPT_ID
ocl concept name-add OWNER SOURCE CONCEPT_ID NAME --locale LOCALE
ocl concept description-add OWNER SOURCE CONCEPT_ID TEXT --locale LOCALE
ocl concept extra-set OWNER SOURCE CONCEPT_ID KEY VALUE
ocl concept extra-del OWNER SOURCE CONCEPT_ID KEY
# Intelligent matching
ocl concept match TERM... --target-source SOURCE [--target-owner OWNER] [--verbose] [--limit N]
ocl concept match "glucose" --target-source CIEL --concept-class Diagnosis --limit 5
ocl concept match "malaria" "diabetes" --target-source CIEL --include-mappings --limit 1# Search & browse (--owner/--repo scope the mapping's source, not the concept sources)
ocl mapping search [QUERY] [--owner OWNER] [--repo REPO] [--map-type TYPE]
ocl mapping search --owner CIEL --repo CIEL --from-concept 138041 --verbose
ocl mapping search --owner CIEL --repo CIEL --to-concept 116128
ocl mapping get OWNER SOURCE MAPPING_ID [--repo-version VERSION]
ocl mapping versions OWNER SOURCE MAPPING_ID
# Create & update
ocl mapping create OWNER SOURCE --map-type TYPE --from-concept-url URL --to-concept-url URL
ocl mapping update OWNER SOURCE MAPPING_ID [--map-type TYPE]
ocl mapping retire OWNER SOURCE MAPPING_IDNavigate concept hierarchies and related mappings:
ocl cascade OWNER REPO CONCEPT_ID [--repo-version VERSION] [--levels N] [--reverse]ocl ref list OWNER COLLECTION [--collection-version VERSION]
ocl ref add OWNER COLLECTION EXPRESSION... [--cascade sourcemappings|sourcetoconcepts]
ocl ref remove OWNER COLLECTION EXPRESSION...ocl expansion list OWNER COLLECTION VERSION
ocl expansion get OWNER COLLECTION [--collection-version VERSION] [--expansion-id ID]
ocl expansion create OWNER COLLECTION VERSIONMonitor async operations on the server:
ocl task list [--state SUCCESS|FAILURE|PENDING|STARTED] [--verbose]
ocl task get TASK_IDOCL CLI supports multiple OCL server environments:
# List configured servers
ocl server list
# Add a custom server
ocl server add my-server https://api.my-ocl.org --name "My OCL Server"
# Switch default server
ocl server use ocl-dev
# Use a specific server for one command
ocl -s ocl-qa concept search malariaPre-configured servers: ocl-prod (default), ocl-dev, ocl-qa, ocl-staging
OCL resources are versioned. Use --repo-version (for sources/repos) or --collection-version (for collections) to access specific versions:
# Get latest released version of a source
ocl repo get CIEL CIEL --repo-version latest
# Get a named version
ocl repo get CIEL CIEL --repo-version v2026-01-26
# Get a concept as it existed in a specific source version
ocl concept get CIEL CIEL 116128 --repo-version v2026-01-26
# Omit --repo-version to get HEAD (working draft)
ocl concept get CIEL CIEL 116128Config is stored at ~/.ocl/config.json. It's created automatically on first use.
--tokenCLI flagOCL_API_TOKENenvironment variable- Server-specific env var (e.g.
OCL_API_TOKEN_PROD) - Token stored via
ocl login
--server/-sCLI flagOCL_SERVERenvironment variabledefault_serverin config file
The CLI is designed for use by AI agents via subprocess calls. Key features:
ocl reference --jsondumps the full command tree in one call — all commands, args, options-jflag outputs structured JSON on stdout- Exit codes: 0 = success, 1 = client error, 2 = server error, 3 = auth error
- Errors go to stderr, data goes to stdout
- Non-interactive: all parameters via flags/args (except
ocl login)
Example agent usage:
# Search and parse results
ocl -j concept search "diabetes" --owner CIEL --repo CIEL --limit 10
# Get a specific concept
ocl -j concept get CIEL CIEL 116128
# Create a mapping (with token via env var)
OCL_API_TOKEN=xxx ocl -j mapping create MYORG MYSOURCE \
--map-type SAME-AS \
--from-concept-url /orgs/CIEL/sources/CIEL/concepts/116128/ \
--to-concept-url /orgs/WHO/sources/ICD-10-WHO/concepts/B54/The CLI's --json output pairs naturally with jq for ad-hoc analytics that would otherwise require direct database access.
Count source versions, collection versions, distinct orgs, and distinct users with OpenMRS Validation Schema repos updated in the last 6 months (ocl_issues#2032):
ocl -j repo list --custom-validation-schema OpenMRS --updated-since 2025-09-27 \
--all-versions --limit 500 \
| jq '{
source_versions: [.results[] | select(.repo_type == "Source")] | length,
collection_versions: [.results[] | select(.repo_type == "Collection")] | length,
organizations: [.results[] | select(.owner_type == "Organization") | .owner] | unique | length,
users: [.results[] | select(.owner_type == "User") | .owner] | unique | length
}'Key flags used:
--custom-validation-schema OpenMRS— server-side filter via Elasticsearch--updated-since 2025-09-27— only repos updated in the last 6 months--all-versions— return one row per repo version (not just HEAD), so version counts are direct-j(before subcommand) — structured JSON output for piping tojq
- Python 3.10+
- Dependencies: click, httpx, tenacity, python-dotenv