Skip to main content
Version: v0.0.2

Core Concepts

@cosyte/cli is a thin, honest skin over the @cosyte/* parsers. Understanding its three load-bearing disciplines (the wrapper boundary, the exit-code contract, and the PHI posture) tells you exactly what to trust it for.

The wrapper boundary

The CLI's correctness surface is narrow by design, because most correctness lives one layer down.

The CLI owns: format autodetection routing, the exit-code contract, the value-free PHI posture, argument/stdin handling, output shaping, and faithful pass-through of the wrapped library's warnings.

The CLI does not re-do: any wire-format parsing, tolerance, or warning semantics. That is the wrapped parser's job, graded by its own conformance gate. cosyte parse equals the library's programmatic parse; a bug in a value is the library's, while a mis-route, a wrong exit code, or a leaked value is the CLI's.

Fail-safe autodetection

Detection sniffs content, never the file extension, and is conservative: a single confident signature match parses; zero or more than one match is a typed data error asking for --format, never a guess. A wrong sniff would route bytes to the wrong parser and yield confident garbage, so the CLI refuses to guess, mirroring the parsers' "never a confident wrong value" rule at the routing layer.

The exit-code contract

Exit codes are a designed surface CI depends on, grounded in the Unix sysexits.h conventions: 0 success, 2 usage error, 65 data error (unparseable / undetected), 66 no input, 70 internal error. The load-bearing rule: the CLI never prints a reassuring line and exits 0 on input it could not handle.

The PHI posture

A CLI operates on real files a developer points at: the moment cosyte code touches un-synthetic PHI. So the channels are split:

  • stdout is the data channel. parse emits the parsed model there because that is your explicit request, going to the sink you chose (a pipe, a redirect, your screen).
  • Every other surface is value-free. stderr, errors, and diagnostics carry only positional context (a segment/field index, a byte offset, a file path, a stable code), never a name, DOB, MRN, or result value. An error never echoes the offending bytes.

Diagnostic codes are stable (CLI_CODES): scripts branch on them, so renaming one is a breaking change.

--unsafe-show-values: the single door to a value

Value-free-by-default has one explicit escape hatch: --unsafe-show-values. With it set, a CLI_PARSE_FAILED diagnostic appends a bounded excerpt of the offending input to aid local debugging. It is off by default, PHI-exposing by design (the flag name carries the warning), and it is the only configuration under which a value reaches a secondary surface: resolved once, globally, and funnelled through a single chokepoint so the "a value appears on stderr iff the flag is set" property is provable in one place. A successful parse never puts values on stderr regardless of the flag.

redact / deid: honest, not faked

The one command whose job is to strip PHI is deliberately gated. De-identification belongs to @cosyte/deid, which the CLI does not wire yet; the wrapped parsers expose no de-id API. Rather than ship a partial Safe-Harbor scrub that would leave PHI behind while looking de-identified (a false-safety impression), redact/deid is a typed CLI_NOT_IMPLEMENTED (exit 69) that never reads the input and never emits a partial scrub. It becomes real when that integration lands. This is the same discipline the wrapper boundary rests on: the CLI never invents a capability its ground layer lacks.