New:Socket for Asana Is Now Available.Learn more
Get Started

@0disoft/laqu

Package Overview
Dependencies
Maintainers
1
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@0disoft/laqu - npm Package Compare versions

Comparing version
1.1.8
to
1.1.9
+43
CHANGELOG.md
# Changelog
Notable user-facing changes to `@0disoft/laqu` are recorded here. The project follows
[Semantic Versioning](docs/library/semver.md).
## [1.1.9] - 2026-08-13
### Added
- Added runnable examples for clean stdout, nested task trees, and versioned NDJSON events.
- Added a terminal preview and direct links to API, compatibility, migration, contribution, and
security documentation.
- Added contribution guidance, private vulnerability-reporting guidance, and structured GitHub
issue forms.
### Changed
- Reworked the README around the core workflow: human progress on stderr, caller-owned data on
stdout, and versioned events for machine consumers.
- Expanded the packed-package consumer check to execute all new examples and require the README
preview asset in the published tarball.
- Clarified npm search metadata and removed the misleading `tui` keyword.
- Added a blocking minimum-runtime job for Node.js 22.
### Compatibility
- No runtime API or event-schema changes.
- Lowered the minimum supported runtime from Node.js 24 to Node.js 22 after the full package and
packed-consumer checks passed on main.
## [1.1.8] - 2026-08-10
### Fixed
- Preserved updates that race an active output flush.
- Stabilized cross-platform PTY resize verification.
### Changed
- Adopted the TypeScript 7 toolchain.
[1.1.9]: https://github.com/0disoft/laqu/compare/v1.1.8...v1.1.9
[1.1.8]: https://github.com/0disoft/laqu/releases/tag/v1.1.8
import { createLaqu } from "@0disoft/laqu";
const progress = createLaqu();
const artifact = await progress.task("build release", { total: 3 }, async (task) => {
task.advance(1);
task.setMessage("types checked");
task.advance(1);
task.setMessage("bundle written");
task.advance(1);
return { artifact: "dist/laqu.js", status: "ready" };
});
await progress.close();
process.stdout.write(`${JSON.stringify(artifact)}\n`);
import { createLaqu } from "@0disoft/laqu";
const progress = createLaqu({ format: "ndjson" });
await progress.task("index files", { total: 2 }, async (task) => {
task.advance(1);
task.setMessage("sources indexed");
task.advance(1);
});
await progress.close();
import { createLaqu } from "@0disoft/laqu";
const progress = createLaqu();
await progress.task("release", async (release) => {
const checks = release.child("checks", { total: 2 });
checks.advance(1);
checks.setMessage("types passed");
checks.advance(1);
checks.succeed("all checks passed");
const publish = release.child("publish", { total: 2 });
publish.advance(1);
publish.setMessage("package uploaded");
publish.advance(1);
publish.succeed("release published");
});
await progress.close();
<svg xmlns="http://www.w3.org/2000/svg" width="960" height="420" viewBox="0 0 960 420" role="img" aria-labelledby="title description">
<title id="title">Laqu terminal progress preview</title>
<desc id="description">Three concurrent CLI tasks render progress on stderr while a JSON result remains clean on stdout.</desc>
<rect width="960" height="420" rx="20" fill="#0b1020"/>
<rect x="1" y="1" width="958" height="418" rx="19" fill="none" stroke="#26324a" stroke-width="2"/>
<circle cx="38" cy="35" r="7" fill="#ff6b6b"/>
<circle cx="62" cy="35" r="7" fill="#ffd166"/>
<circle cx="86" cy="35" r="7" fill="#4ade80"/>
<text x="480" y="41" fill="#8b9bb4" font-family="ui-monospace, SFMono-Regular, Consolas, monospace" font-size="15" text-anchor="middle">release · laqu</text>
<line x1="0" y1="64" x2="960" y2="64" stroke="#26324a"/>
<g font-family="ui-monospace, SFMono-Regular, Consolas, monospace" font-size="21">
<text x="36" y="112" fill="#7dd3fc">›</text>
<text x="70" y="112" fill="#e5edf8">install packages</text>
<text x="292" y="112" fill="#4ade80">[███████████████</text>
<text x="508" y="112" fill="#35425a">░░░░░]</text>
<text x="608" y="112" fill="#e5edf8">76%</text>
<text x="676" y="112" fill="#8b9bb4">downloading · 76/100</text>
<text x="36" y="158" fill="#7dd3fc">›</text>
<text x="70" y="158" fill="#e5edf8">build artifacts</text>
<text x="292" y="158" fill="#4ade80">[██████████</text>
<text x="450" y="158" fill="#35425a">░░░░░░░░░░]</text>
<text x="608" y="158" fill="#e5edf8">49%</text>
<text x="676" y="158" fill="#8b9bb4">bundling</text>
<text x="36" y="204" fill="#64748b">·</text>
<text x="70" y="204" fill="#e5edf8">publish preview</text>
<text x="292" y="204" fill="#35425a">[░░░░░░░░░░░░░░░░░░░░]</text>
<text x="608" y="204" fill="#e5edf8">0%</text>
<text x="676" y="204" fill="#8b9bb4">waiting</text>
</g>
<line x1="36" y1="242" x2="924" y2="242" stroke="#26324a"/>
<text x="36" y="280" fill="#8b9bb4" font-family="ui-monospace, SFMono-Regular, Consolas, monospace" font-size="16">stderr · live progress</text>
<text x="36" y="325" fill="#8b9bb4" font-family="ui-monospace, SFMono-Regular, Consolas, monospace" font-size="16">stdout · caller-owned result</text>
<rect x="36" y="344" width="888" height="48" rx="8" fill="#111a2d" stroke="#26324a"/>
<text x="56" y="375" fill="#f8fafc" font-family="ui-monospace, SFMono-Regular, Consolas, monospace" font-size="18">{"artifact":"dist/laqu.js","status":"ready"}</text>
</svg>
+13
-5
{
"name": "@0disoft/laqu",
"version": "1.1.8",
"description": "Reliable terminal progress and live CLI rendering primitives for TypeScript.",
"version": "1.1.9",
"description": "Reliable CLI progress on stderr with clean stdout and versioned events.",
"keywords": [
"ci",
"cli",
"library",
"live-rendering",
"ndjson",
"nodejs",
"progress-bar",
"stderr",
"terminal",
"tui",
"typescript"

@@ -26,2 +29,4 @@ ],

"examples",
"media",
"CHANGELOG.md",
"README.md"

@@ -58,2 +63,5 @@ ],

"example:basic": "bun run build && node examples/basic.mjs",
"example:clean-stdout": "bun run build && node examples/clean-stdout.mjs",
"example:nested-tasks": "bun run build && node examples/nested-tasks.mjs",
"example:ndjson": "bun run build && node examples/ndjson-events.mjs",
"format": "oxfmt --write .",

@@ -68,3 +76,3 @@ "format:check": "oxfmt --check .",

"devDependencies": {
"@types/node": "24.x",
"@types/node": "22.x",
"oxfmt": "0.x",

@@ -75,5 +83,5 @@ "oxlint": "1.x",

"engines": {
"node": ">=24.0.0"
"node": ">=22.0.0"
},
"packageManager": "bun@1.3.14"
}
+101
-10
# laqu
`laqu` is a strict TypeScript runtime for reliable terminal progress and live CLI rendering on Node.js 24+.
[![npm version](https://img.shields.io/npm/v/@0disoft/laqu?logo=npm)](https://www.npmjs.com/package/@0disoft/laqu)
[![Node.js 22+](https://img.shields.io/badge/Node.js-22%2B-5FA04E?logo=nodedotjs&logoColor=white)](package.json)
[![MIT license](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
It treats stdout as the caller-owned data channel and sends progress, status, logs, human rendering,
and JSON/NDJSON progress events to stderr by default. The runtime keeps output format, status-stream
capability, output target, and progress policy as separate decisions instead of hiding them behind
one mode enum.
**Progress for humans. Events for machines. stdout stays clean.**
`laqu` gives Node.js and TypeScript CLIs live progress without corrupting piped JSON, CSV, file
lists, or other caller-owned output. Human status goes to stderr by default; CI-safe text and
versioned JSON/NDJSON events use the same task model when a terminal UI is not appropriate.
![Laqu rendering concurrent CLI tasks while stdout stays available for JSON](media/terminal-preview.svg)
```text
› install packages [███████████████░░░░░] 76% downloading 76/100
› build artifacts [██████████░░░░░░░░░░] 49% bundling
· publish preview [░░░░░░░░░░░░░░░░░░░░] 0% waiting
```
stdout remains available for the result:
```json
{ "artifact": "dist/laqu.js", "status": "ready" }
```
## Install
```sh
npm install @0disoft/laqu
```
```sh
pnpm add @0disoft/laqu
```
```sh
bun add @0disoft/laqu
```
The published package targets Node.js 24+ and does not require Bun, Deno, Rust, native addons, WASM, or C++ bindings at runtime.
The published package targets Node.js 22+ and does not require Bun, Deno, Rust, native addons, WASM, or C++ bindings at runtime.
## Quick Start
```ts
import { createLaqu } from "@0disoft/laqu";
const progress = createLaqu();
const result = await progress.task("build", { total: 3 }, async (task) => {
task.advance(1);
task.setMessage("typecheck passed");
task.advance(1);
task.setMessage("bundle written");
task.advance(1);
return { artifact: "dist/laqu.js", status: "ready" };
});
await progress.close();
process.stdout.write(`${JSON.stringify(result)}\n`);
```
When this command runs interactively, progress animates on stderr. When stdout is redirected, the
redirected file contains only the JSON result. In CI or a pipe, human progress automatically falls
back to stable append-only lines.
## Pick The Output Your Consumer Needs
| Consumer | Configuration | Output behavior |
| ----------------------------- | --------------------------------- | ------------------------------ |
| Person in a terminal | default | live progress on stderr |
| CI log or redirected terminal | default | append-only progress on stderr |
| Event collector | `{ format: "ndjson" }` | versioned events on stderr |
| Data pipeline | default plus caller writes stdout | clean caller-owned stdout |
The output format, terminal capability, output target, and progress policy remain independent. You
can change one without pretending that terminal detection, serialization, and destination are the
same decision.
## Runnable Examples
- [`examples/basic.mjs`](examples/basic.mjs): animated multi-task terminal demo
- [`examples/nested-tasks.mjs`](examples/nested-tasks.mjs): parent and child task hierarchy
- [`examples/clean-stdout.mjs`](examples/clean-stdout.mjs): progress on stderr with a JSON result on stdout
- [`examples/ndjson-events.mjs`](examples/ndjson-events.mjs): versioned NDJSON task and summary events
Run an example after installing dependencies:
```sh
bun run example:clean-stdout > result.json
```
The progress remains visible in the terminal while `result.json` stays parseable JSON.
## Scoped Tasks

@@ -222,2 +299,14 @@

## Documentation And Support
- [Public API](docs/library/public-api.md)
- [Compatibility policy](docs/library/compatibility.md)
- [SemVer policy](docs/library/semver.md)
- [Migration guide](docs/library/migration-guide.md)
- [Changelog](CHANGELOG.md)
- [Architecture and operating documentation](docs/README.md)
- [Contributing](CONTRIBUTING.md)
- [Security policy](SECURITY.md)
- [Issues](https://github.com/0disoft/laqu/issues)
## Development

@@ -235,2 +324,4 @@

CI runs both checks on Ubuntu, Windows, and macOS. The real PTY resize harness runs on Unix hosts; Windows runs the full stream, process-signal, renderer, and package suite without claiming ConPTY coverage.
An additional blocking Ubuntu job runs the same package and packed-consumer checks on the minimum
supported runtime, Node.js 22. The three-platform matrix runs on Node.js 24.
`bun run example:basic` builds the package and runs a small live progress demo. Terminal scrollback keeps the final frame; watch the command while it runs to see the bar animate in place.

@@ -240,7 +331,7 @@

GitHub Actions publishes npm releases from maintainer-created version tags. The tag must match `package.json` exactly, for example `v1.1.8` for version `1.1.8`.
GitHub Actions publishes npm releases from maintainer-created version tags. The tag must match `package.json` exactly, for example `v1.1.9` for version `1.1.9`.
```sh
git tag -a v1.1.8 -m "v1.1.8"
git push origin main v1.1.8
git tag -a v1.1.9 -m "v1.1.9"
git push origin main v1.1.9
```

@@ -250,2 +341,2 @@

On a matching tag push, the workflow first verifies the tag, package metadata, tests, build, and installed-tarball consumer checks with read-only repository permissions. The publish job then waits on the `npm` environment gate, repeats package verification on the tagged commit, packs the release tarball, uploads that exact tarball as a retained workflow artifact, publishes the same tarball to npm with provenance through OIDC, and creates a GitHub Release with generated notes.
On a matching tag push, the workflow first verifies the tag, package metadata, tests, build, and installed-tarball consumer checks with read-only repository permissions. The publish job then waits on the `npm` environment gate, repeats package verification on the tagged commit, packs the release tarball, uploads that exact tarball as a retained workflow artifact, publishes the same tarball to npm with provenance through OIDC, and creates a GitHub Release from the matching `CHANGELOG.md` section.