Skip to main content
Version: v0.1.6

cosyte command reference

A man-page-style reference for every cosyte command, its arguments, and its flags. This mirrors cosyte --help; the API Reference documents the programmatic (. subpath) surface. Every command reads a <file> argument or - for stdin, autodetects the format by content unless --format overrides it, and resolves to a code in the exit-code contract.

Synopsis​

cosyte <command> [options]
cosyte-mcp # the stdio MCP server (also: cosyte mcp)

Global options​

FlagEffect
-h, --helpPrint help and exit 0.
-V, --versionPrint the CLI version and exit 0.
--unsafe-show-valuesPermit a bounded input excerpt in a failure diagnostic on stderr. PHI-exposing; off by default; the single door to a value on a secondary surface.

Common options (parse / validate / inspect / fmt)​

FlagEffect
--format <fmt>Override autodetection: hl7 | fhir | dicom | x12 | ccda | ncpdp | astm | mllp. Support is per (format, operation): see Limitations.
--jsonMachine-readable JSON output.
--quietSuppress value-free notes on stderr (the exit code becomes the whole signal).
--no-colorDisable ANSI color.

Commands​

cosyte parse <file\|->​

Parse a healthcare message to typed JSON on stdout (the data channel). Autodetects the format. --ndjson treats each non-empty input line as a record and emits NDJSON; an MLLP stream is parsed one record per frame with per-record isolation (a failed record becomes a value-free { record, error } line and the stream continues; any failure → exit 65).

Multi-record output is written record by record, as each record is parsed, so the first line reaches stdout long before the last byte of input has been read and a large batch can be piped straight into another process.

cosyte parse adt.hl7
cat adt.hl7 | cosyte parse -
cosyte parse --ndjson bulk.ndjson | jq .

Input size limit​

parse reads at most 67108864 bytes (64 MiB) of input per invocation. A larger input is refused with a value-free CLI_INPUT_TOO_LARGE diagnostic naming that limit and the data-error exit code (65), never the internal-error code (70): a large input is not a bug in the tool. Split the input and re-run. The same number is printed by cosyte --help.

Because records are emitted as they are parsed, a refusal can arrive after some records have already been written to stdout. The exit code, not the output, is the signal that the run did not complete: a partial record stream always carries a non-zero exit, never 0.

cosyte validate <file\|-> [--profile <name>]​

Validate a message; the exit code carries the verdict: 0 valid, 1 invalid (parseable but non-conformant), 65 unparseable. Findings are value-free (a code + a positional location). --profile is reserved but gated to CLI_NOT_IMPLEMENTED (exit 69), no profiles are bundled.

cosyte validate patient.json && echo "valid" # branches on exit 0/1

cosyte inspect <file\|->​

Print a value-free structural summary: the message/resource type, segment/entry counts, and a warning/issue count. Never emits a field value on either channel.

cosyte fmt <file\|->​

Canonically re-serialize via the wrapped library's spec-clean serializer. stdout is the data channel; an unparseable input is a data error (65) with no partial emit.

cosyte convert <file\|-> --to fhir​

Convert an HL7 v2 message to a FHIR R4 Bundle via @cosyte/transform. --to fhir is required (the only target today). An error-severity conversion issue drives exit 1; a non-HL7 source is CLI_FORMAT_UNSUPPORTED (65).

cosyte map-codes <conceptmap\|-> --code <code> [--system <uri>] [--version <v>] [--display <d>]​

Translate a code through a bring-your-own FHIR ConceptMap via @cosyte/terminology ($translate). A match prints the target coding(s) and exits 0; an unmapped code is TERM_TRANSLATE_UNMAPPED (exit 1); an unloadable map is CLI_MAP_INVALID (65). The positional is reference data, and a code is not PHI.

cosyte redact <file\|-> (alias: deid)​

De-identify a message. The whole de-identification policy is @cosyte/deid's; the CLI adds no locus map, no transform, and no fallback scrub, so it either delegates or refuses. The covered formats are ccda, fhir, hl7, x12.

stdout is the de-identified document, serialized exactly as cosyte fmt serializes that format. stderr carries the library's own value-free manifest, one line per locus it acted on (category, transform, the structural path, the count, the disposition, and its stable code), plus the library's own published output label and version. The CLI claims no de-identification standard of its own.

Anything short of a clean, fully-handled pass emits nothing on stdout:

OutcomeDiagnosticExit
Every locus handledthe manifest0
The library reports a locus it could not handleCLI_DEID_INCOMPLETE1
astm, mllp, ncpdp: the library ships no adapter for themCLI_NOT_IMPLEMENTED69
dicom: covered by the library, but its de-identified form is a binary stream this text stdout cannot carryCLI_FORMAT_UNSUPPORTED65
@cosyte/deid is not installed (it is an optional dependency)CLI_PARSER_UNAVAILABLE69

An absent library is decided before the input is read.

What the library's default policy does, applied unmodified (the CLI passes it no policy, profile, or retention set of its own):

  • Medical record, account, and member numbers are removed, not replaced by a surrogate. Their manifest lines carry the disposition removed and the code DEID_CATEGORY_REMOVED.
  • A visit or order number is blocked, and the run is refused. An HL7 visit number (PV1-19) and a placer or filler order number (ORC-2/ORC-3, OBR-2/OBR-3) fall to the library's catch-all identifier category, which its default policy blocks. The run ends CLI_DEID_INCOMPLETE with exit 1 and nothing on stdout, and stderr names each blocked locus with the library's DEID_LOCUS_BLOCKED code. An ADT message that carries PV1-19 therefore produces no output.

The CLI keys every run with a per-invocation ephemeral key and discloses it on stderr: any identifier surrogate is consistent within one output and deliberately not stable across runs, so two runs cannot be linked by their surrogates.

cosyte redact adt.hl7 > clean.hl7 # stdout is the document (or nothing, on exit 1), stderr is the manifest
cosyte redact adt.hl7 2>/dev/null # the manifest suppressed; the exit code still carries the verdict

cosyte completion <bash\|zsh\|fish>​

Print a static, value-free shell-completion script generated from the command tree.

cosyte mcp / cosyte-mcp​

Start the stdio MCP server: the agent front door, exposing parse/validate/inspect/convert as tools over the same core. See MCP server. The server needs @modelcontextprotocol/sdk, an optional dependency: without it, both forms exit 69 with CLI_PARSER_UNAVAILABLE instead of starting.

Exit codes​

CodeMeaning
0success / validate found the input valid
1operation-level failure: validate found the input invalid, or redact could not de-identify every locus (a real CI signal)
2usage error: unknown command, bad flag, missing argument
65data error: input could not be parsed / format not detected / (format, op) unsupported / input larger than the size limit
66no input: the file does not exist or is unreadable
69unavailable: a capability is not wired here (e.g. redact on a format @cosyte/deid has no adapter for, --profile), or an optional library it needs is not installed (CLI_PARSER_UNAVAILABLE, e.g. cosyte-mcp without @modelcontextprotocol/sdk)
70internal error: an unexpected exception (a bug)
74output error: the output stream closed before the CLI had finished writing to it, the shape a downstream consumer that exits early produces (cosyte parse bulk.ndjson --ndjson | head -3, a pager you quit). Never a bug in the CLI, and never a silent 0: the answer did not reach the consumer

A closed output stream terminates the run quietly under 74 with the stable CLI_OUTPUT_WRITE_FAILED code on stderr: no stack trace, no platform error text, and no byte of the input. It reads the same whether the output was a record stream or a single write.

The contract is a stability surface: renaming a code or a stable CLI_* diagnostic is a breaking change, and it is locked by an exit-code golden matrix in the test suite.