Use the programmatic API
The package's main entry point exports the code the cosyte command runs on: format detection, the
commands themselves, and the exit and diagnostic codes. Use it to drive the same logic from your own
program without starting a process. Most programs that parse messages should import the format's
own library, such as @cosyte/hl7, instead; this API is for code that wants the command's
behavior: detection, the exit-code contract, and output that carries no values on stderr.
Detect a format
detectFormat reads the start of the input and names one format, or says it could not decide. It
never guesses:
import { detectFormat } from "@cosyte/cli";
const enc = new TextEncoder();
detectFormat(enc.encode("MSH|^~\\&|SENDINGAPP|SENDINGFAC\r")).format; // => "hl7"
detectFormat(enc.encode('{"resourceType":"Patient","id":"example"}')).format; // => "fhir"
detectFormat(enc.encode("not a healthcare message")).confidence; // => "none"
Run a command on bytes you hold
run takes the arguments that would follow cosyte and an object that supplies the input. It
returns what the command would have printed and its exit code, and writes nothing itself:
import { run, EXIT } from "@cosyte/cli";
const files: Record<string, string> = {
"patient.json": '{"resourceType":"Patient","id":"example","gender":"m"}',
};
const deps = {
readFile: async (path: string) => new TextEncoder().encode(files[path] ?? ""),
readStdin: async () => new Uint8Array(),
};
const result = await run(["validate", "patient.json"], deps);
result.exit === EXIT.INVALID; // => true
result.stdout; // => ""
result.stderr.split("\n")[0]; // => "cosyte: validate: error CODE_INVALID at Patient.gender"
To read real files, pass readFileBytes as readFile: it applies the same size limit as the
command, and turns a missing file into CLI_NO_INPUT (exit 66). A readFile of your own that
throws anything other than a CliError ends the run as CLI_INTERNAL (exit 70).
import { readFileBytes, run } from "@cosyte/cli";
const deps = { readFile: readFileBytes, readStdin: async () => new Uint8Array() };
const result = await run(["inspect", "no-such-file.hl7"], deps);
result.exit; // => 66
result.stderr.startsWith("cosyte: CLI_NO_INPUT: "); // => true
Branch on the codes
EXIT holds the exit codes and CLI_CODES the diagnostic codes, by name, so code does not repeat
the numbers:
import { CLI_CODES, EXIT, run } from "@cosyte/cli";
const deps = {
readFile: async () => new TextEncoder().encode("hello"),
readStdin: async () => new Uint8Array(),
};
const { exit, stderr } = await run(["parse", "note.txt"], deps);
exit === EXIT.DATAERR; // => true
stderr.includes(CLI_CODES.CLI_FORMAT_UNDETECTED); // => true
Ask which formats support an operation
import { formatsSupporting, supportsOp } from "@cosyte/cli";
formatsSupporting("fmt"); // => ["astm", "ccda", "fhir", "hl7", "ncpdp", "x12"]
supportsOp("mllp", "validate"); // => false
Call an MCP tool without a server
@cosyte/cli/mcp exports the MCP server and the function behind each tool call. dispatchTool
runs one call and returns the result the server would send:
import { dispatchTool } from "@cosyte/cli/mcp";
const reply = await dispatchTool("validate", {
content: '{"resourceType":"Patient","id":"example","gender":"m"}',
});
reply.isError; // => false
reply.structuredContent.status; // => "verdict"
reply.structuredContent.exit; // => 1
The @cosyte/cli/mcp entry point loads @modelcontextprotocol/sdk, an optional dependency; the main
entry point does not.
Reference
The whole API is in the generated reference: the main entry point and
@cosyte/cli/mcp. The functions used here are
detectFormat, run,
readFileBytes, EXIT,
CLI_CODES, formatsSupporting,
supportsOp, and dispatchTool.