`sct` - a fast, free set of local SNOMED-CT tools

Hi SNOMED forums

I’m a clinical informatician, software developer and clinician based in the UK, and although I’ve had a lot of exposure to SNOMED-CT over the years, I’ve always found the tooling for local development, exploration, and learning of SNOMED to be quite sparse. I decided to see if I could build simple SNOMED tools that use files on disk - no Java, no Docker, no REST API, just simple deterministic tooling, modern file-based formats, normal developer workflows.

Here’s what I made.

Feedback most welcome.

Here’s a video which walks through the key features of the sct toolset.

Hi @pacharanero ,

this is really interesting, thank you for submitting this. I’ve not had a chance to set it up and have a play, but will definitely be doing so after our conference. It’s good to see other open source tools to make access to SNOMED CT more accessible, especially ones that take a different approach from others we have seen.

Thanks,
Rory

1 Like

Thanks @rdavidson - at this stage it’s been as much a learning and experimentation tool for me, but I’m trying to build it to be performant and robust, such that it could be included in my other software projects to give me fast, local-first SNOMED autocomplete, searches, etc.

Please do feed back here with anything you notice such as bugs etc. And feature requests!

Does anyone here know if it would be acceptable for sct to include the IPS SNOMED-CT subset, which has been openly released under Creative Commons license?

I would like sct to have some SNOMED terms in the repo, to make it easier for new people to get started with SNOMED, without having to separately obtain a SNOMED Edition from somewhere else (eg TRUD in UK or MLDS)

Is the IPS subset actually openly published anywhere? Having to register on the SNOMED website in order to be emailed a link to download it is not actually what the technology world considers ‘open’.

Hi all - a massive and belated update on sct, the local-first SNOMED CT toolkit I posted in April. You can now run it on a Raspberry Pi :rofl:

sct is now at v0.23.1. It’s getting close to what I’d consider a reasonable 1.0 release. It will always be a free, open-source, single-binary toolchain that works from RF2 data stored locally. There is no hosted service dependency at runtime: it creates NDJSON (newline delimited JSON), SQLite, Parquet, Markdown, FST, and optional embedding artefacts on your own machine.

It’s particularly useful for giving the power of SNOMED to your AI agents via CLI or MCP.

I benchmarked the sct terminology server against a number of other termservers, and, well, it’s not slower, put it that way… At this stage I’m not getting into ‘mine is faster than yours’ but I did want to at least know that a file-backed system doesn’t perform worse than a Java/DB stack.

Getting hold of SNOMED CT and building local artefacts

  • sct trud can authenticate with NHS TRUD, download the UK Monolith release, verify its SHA-256 checksum, and run the build pipeline. It now supports storing the API key with sct trud auth, avoiding secrets in shell history and process listings.
  • The pipeline can carry through inactive concepts, reference sets, and locale selection rather than forcing a separate manual build for those needs.
  • The canonical sct ndjson artefact now preserves release provenance, language-refset-aware preferred terms, simple and payload reference-set data, inactive concepts, and layered RF2 input correctly.
  • RF2 loading and NDJSON writing are now streamed. In a documented UK Monolith comparison, this reduced peak memory from 6.42 GiB to 3.73 GiB and allowed the full pipeline to complete on an 8 GB Raspberry Pi 5. The exact figures are workload and machine specific, but the method and measurements are published.
  • Every build records enough provenance to identify the source release later from SQLite-backed commands, codelists, embeddings, and MCP results.

Local exploration, search, and hierarchy work

  • sct lookup now validates SNOMED CT identifiers using the Verhoeff check digit, and shows inactive-concept context where the loaded data supports it.
  • sct history is a new focused view for retired concepts: why a concept was inactivated and the appropriate historical-association target(s), rather than leaving users to reconstruct that story themselves.
  • sct ecl now provides a local ECL parser and evaluator for hierarchy, refset membership, boolean operations, and attribute refinement. It can feed results straight into codelist workflows.
  • The optional transitive closure table accelerates hierarchy-heavy work. Commands remain correct without it by falling back to recursive SQL, and explain how to build or repair it when appropriate.
  • sct size estimates a concept’s hierarchy/subtree size, including when a closure table is unavailable.
  • sct diagram (experimental) renders hierarchy and definition views, making stated relationships easier to inspect than raw RF2 rows.
  • sct fst index supports compact memory-mappable exact, prefix, typo-tolerant, and word-intersection search.
  • sct sayt adds search-as-you-type over that FST index: as an interactive terminal UI, a line-based standard-input protocol, or an HTTP autocomplete endpoint for a web interface.
  • sct proximal-primitives and the SDK can find a concept’s proximal primitive supertypes.

Reference sets and reproducible codelists

  • sct refset gained compare and profile commands to show differences between reference sets and group their members by hierarchy.
  • .codelist files are now composable: one list can include others, with explicit exclusions and provenance retained in readable, version-controllable text.
  • sct codelist gained an interactive concept picker, imports from CSV, OpenCodelists CSV, and FHIR ValueSets, and can export FHIR R4 ValueSets.
  • It can now export an active codelist as a compact, exact ECL expression, so a selected list can round-trip between explicit concepts and a semantic rule where that is possible.
  • Codelist export can include cross-terminology mappings for downstream reporting or migration work.
  • The background and rationale for treating codelists as reviewable source material is in Why code lists?.

Legacy coding and cross-terminology mapping

  • sct map unifies mapping previously split across transcode and crosswalk: SNOMED CT can be mapped to and from ICD-10, OPCS-4, CTV3, and Read v2 when the relevant source data has been loaded.
  • SNOMED CT RF2 map refsets are retained natively, including map metadata and historical forwarding from inactivated concepts.
  • ICD-10 input accepts both dotted and undotted forms, for example I21.9 and I219.
  • sct read2 supports importing TRUD item 9 Read v2 material to provide the Read v2/CTV3 side of the mapping story.
  • sct dmwb can inspect DMWB .mdb files and supports the FHIR translation route used by the DMWB Excel add-in. This is not a claim of completed universal DMWB import support; the documented Read v2 import gate remains deliberately explicit about its limits.

FHIR terminology service

SDKs, AI, and integration

  • The public Rust SDK gives Rust applications typed, local read-only access to lookup, search, ECL, hierarchy, refsets, mappings, codelists, and lifecycle context without shelling out to the CLI.
  • The sct-py Python package makes the same local engine available to Python users through FFI.
  • sct mcp provides Model Context Protocol tools for local terminology lookup, hierarchy navigation, refset comparison/profile, and direct terminology mapping. Input sizes and in-flight work are bounded so an MCP client cannot make the server consume unbounded memory.
  • sct embed and sct semantic support local embedding and semantic search workflows. All of this is experimental. Embedding artefacts now record the model and text scheme used, and queries check that they are compatible instead of pretending a mismatched model is safe. The embeddings do work, but I was surprised at actually how unhelpful they were in real life usage.

Install, package, and deployment options

Performance, reliability, and documentation

  • Published benchmarks now cover a UK Monolith release on a Lenovo laptop, Raspberry Pi 5, and OnePlus 13 under Termux. The page states the measurement conditions and cautions against treating single runs as universal figures.
  • sct bench is a new user-facing self-benchmark for CLI and SDK query paths. It emits text, Markdown, JSON, or standalone HTML, and avoids putting host-identifying information into reports.
  • The performance and tuning guide explains the trade-offs between cold and warm storage, transitive closure, FTS, FST, and server pool sizing.
  • Read-side commands now open the SQLite database read-only; commands consistently keep machine-readable data on stdout and progress/warnings on stderr; and single lookup misses exit non-zero for reliable scripting.
  • ECL parsing, TRUD downloads, RF2 archive handling, FHIR request handling, MCP framing, and FST loading have all had explicit resource limits and validation work. These are less glamorous than new commands, but matter for running large terminology releases safely on ordinary machines.
  • The documentation has expanded into a task-focused walkthrough, a concise SNOMED CT primer, a UK edition guide, GPS and IPS notes, and detailed command references.

The project is licensed AGPL, and contributions, bug reports, and feedback from people who work with SNOMED CT in practice are very welcome, in fact you’re the very people who will be able to tell me what bugs are there, and what features are missing!