UniPty v0.2.0: the translation layer from command text to argv
UniPty v0.2.0 adds two optional official parser packages. @unipty/shell-parser classifies shell command text and translates it into structured argv; @unipty/powershell-parser answers only to the official Parser.ParseInput. Nothing is executed at any point, and all 8 public packages appear on npm in complete form for the first time.
Esta publicación está escrita en inglés. Léela en chino →
$ npm view @unipty/shell-parser version
0.2.0
UniPty v0.2.0 is out (the GitHub Release was cut on 2026-08-20). This release adds two optional official parser packages that translate command text into structured data you can launch directly, without executing a single byte along the way. All 8 public packages appear on npm in complete form for the first time.
Background: one contract, three runtimes
Node, Bun, and Deno each expose an incompatible PTY substrate. Installation models, I/O representations, lifecycle semantics, and native deployment constraints all differ (the opening motivation of the v1 architecture proposal). UniPty absorbs those differences behind one public contract: Core owns every observable behavior, developers pick the Backend explicitly, and support claims are evidence-gated. The three official routes are Node over third-party node-pty, Bun over runtime-native Bun.Terminal, and Deno over self-contained @sigma/pty-ffi.
A runtime/platform pair is marked verified only when the public conformance suite passes in full against the installed package artifact (packed and installed into an isolated consumer, driven only through public exports). Everything else is declared-unverified or not-targeted. Failures stay CI diagnostics and never harden into permanent unsupported claims (see the conformance docs).
@unipty/shell-parser: reads command text, never runs it
Projects migrating from string-command tooling no longer have to write the text to argv translation themselves. @unipty/shell-parser reads a piece of command text and tells you which class it falls into and whether it can be launched directly:
import { parse } from "@unipty/shell-parser";
parse("git status --force");
// → { kind: "argv", argv: ["git", "status", "--force"] }
parse("ls *.txt | wc -l");
// → { kind: "script", language: "bash", source: "ls *.txt | wc -l" }
parse("echo 'unterminated");
// → { kind: "incomplete", diagnostics: [...] }
Core accepts only structured argv; there is no string-command overload. The implicit shell is exactly the class of accident it exists to eliminate, so what this package hands back is a classification, not an executor.
The five-way classification argv | script | incomplete | unsupported | invalid is the only stable boundary. argv means the text is lexically exactly one simple command (quoting and empty arguments preserved) and can go straight to unipty.spawn(argv). script means the text carries shell semantics, and launching only becomes a question after you explicitly accept the named shell policy. How executables resolve (PATH, builtins, functions, aliases) stays your decision; the parser never claims process-launch equivalence for a command name.
The classification policy is deliberately conservative: escaped metacharacters (echo \*) and unquoted bracket characters ([ -f x ]) classify as script too. The walker proves literalness from the raw word text, so anything ambiguous stops on the shell-request side rather than being guessed.
The package is a synchronous thin wrapper over unbash. Its only public surface is the classification result, and the unbash AST is never exposed. See the package docs.
@unipty/powershell-parser: only the official parser
PowerShell command text translates into structured argv as well. It does not guess at syntax; it calls PowerShell's own Parser.ParseInput, run by a host you name (pwsh by default):
import { parsePowershell } from "@unipty/powershell-parser";
await parsePowershell('dotnet build -c "My Config"');
// → { kind: "argv", argv: ["dotnet", "build", "-c", "My Config"] }
The adapter script travels as -EncodedCommand; your text travels as base64-encoded UTF-8 over stdin, never interpolated into a command line, and immune to Windows console code-page ambiguity.
Failures are typed in three parts, and none of them is silent: a missing host gives capability-unavailable and never falls back to Bash-style parsing; a host that starts but exits abnormally or returns an unknown result gives host-failure and never downgrades to script; an exceeded budget (15 seconds by default, configurable through timeoutMs) gives host-timeout.
Host selection is explicit too: isPowershellHostAvailable() probes first, and options.host can name another executable (for example powershell for Windows PowerShell 5.1, which also provides Parser.ParseInput). Official ParseError records serialize as { message, errorId, incomplete, range } with UTF-16 offsets; errors flagged IncompleteInput map to incomplete, everything else to invalid. See the package docs.
Example: probe the host first, then choose explicitly
import { isPowershellHostAvailable, PowershellParseError } from "@unipty/powershell-parser";
await isPowershellHostAvailable(); // → false when no pwsh exists
await parsePowershell("x", { host: "pwsh-preview" }); // explicit host choice
Other changes
All 8 packages publish in one release, so npm never keeps a half-published version: the release workflow publishes the two parser packages first, then the core and backends. The parsers are the newest package names and the least likely to have Trusted Publisher configured, so an authentication failure has to happen before the core package is already out. The npm timestamps confirm it:
@unipty/shell-parser@0.2.0landed at 11:00:13,unipty@0.2.0followed at 11:00:26, and GitHub Release v0.2.0 was cut at 11:01.shell-parser keeps locale strings (
$"...") and NUL-bearing ANSI-C words out of argv (5bcd7d2)powershell-parser moved text transport to stdin and enforced strict host failures (7f121ff)
the docs site consumes the real release-catalog schema and requires the aggregator (aggregation-check) suite's passing stamp (586e24c, e489776)
The full list is in compare v0.1.1...v0.2.0.
Upgrade
No breaking changes. The parser ecosystem is purely additive, with zero changes to Core / Backend / acquisition / helper / conformance code (the change proposal's Impact section, verbatim). Upgrading is:
npm i unipty@0.2.0
# optional: add the parsers as needed
npm i @unipty/shell-parser@0.2.0 @unipty/powershell-parser@0.2.0
Acknowledgements
@unipty/shell-parser is built on unbash; the three Backend routes respectively thank node-pty (via the @lydell/node-pty prebuilt distribution), Bun.Terminal, and @sigma/pty-ffi.
Links
Changelog: GitHub Release v0.2.0 · compare v0.1.1...v0.2.0
Docs: unipty.jixoai.com · architecture · capability specs
Upgrade: see the Upgrade section above (no breakage, one
npm i)Discussion: GitHub Issues
npm: unipty · @unipty/shell-parser · @unipty/powershell-parser
Chinese version: /zh/blog/2026-09-06-unipty-v0-2-0/
