
Research
/Security News
OpenAPI React Query Codegen Compromised in Mini Shai-Hulud npm Supply Chain Attack
Ten malicious OpenAPI React Query Codegen versions were published to npm in the Mini Shai-Hulud attack, all with valid provenance.
@0disoft/laqu
Advanced tools
laqu is a strict TypeScript runtime for reliable terminal progress and live CLI rendering on Node.js 24+.
It treats stdout as the data channel and sends progress, status, logs, human rendering, and JSON/NDJSON progress events to stderr by default. The runtime keeps output format, stream capability, channel role, and progress policy as separate decisions instead of hiding them behind one mode enum.
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.
import { createLaqu } from "@0disoft/laqu";
const progress = createLaqu();
await progress.task("download", { total: 100 }, async (task) => {
task.setMessage("starting");
task.advance(25);
task.setDetail("chunk 1/4");
task.advance(75);
});
await progress.close();
Scoped tasks mark themselves as succeeded when the callback resolves. If the callback throws, the task is marked failed and the original error is rethrown. If the task receives an aborted AbortSignal, it is marked cancelled and cleanup still runs.
import { createProgressRuntime } from "@0disoft/laqu";
const progress = createProgressRuntime();
const build = progress.createTask("build", { total: 3 });
build.advance(1);
build.setMessage("typecheck");
build.advance(1);
build.setMessage("bundle");
build.advance(1);
build.succeed("done");
await progress.close();
The API avoids ambiguous calls such as update(42). Use setCompleted(42) for absolute progress and advance(42) for a delta.
const progress = createLaqu();
progress.log("cache hit");
await progress.close();
Logs are separate scrollback records. They are not rendered as task rows and they pass through the same output coordinator as progress frames so live regions and log lines do not corrupt each other.
The root import exposes the stable runtime API and common helpers:
import { createLaqu, displayWidth } from "@0disoft/laqu";
Focused subpath exports are available for narrower consumers:
import { LAQU_EVENT_SCHEMA_VERSION } from "@0disoft/laqu/events";
import { compileTheme } from "@0disoft/laqu/theme";
import { displayWidth } from "@0disoft/laqu/width";
By default:
const progress = createLaqu({
format: "json",
progressPolicy: "jsonl",
stderr: process.stderr,
});
Machine-readable progress events use a versioned schema:
{
"schema": "laqu.event",
"version": 1,
"type": "task",
"task": {
"id": "task-1",
"title": "download",
"status": "running",
"progress": {
"kind": "ratio",
"ratio": 0.5,
"overrun": false
}
}
}
Event schema version 1 is exported as LAQU_EVENT_SCHEMA_VERSION.
The selection axes are independent:
format: human, json, or ndjsonstreamCapability: tty, ci, pipe, or dumbprogressPolicy: auto, always, never, plain, jsonl, or silentThemes are token-first:
const progress = createLaqu({
theme: {
successSymbol: "ok",
runningSymbol: ">",
progressComplete: "=",
overflowMarker: "...",
},
});
Theme tokens are semantic: success symbols, running symbols, progress glyphs, indentation, gaps, and overflow markers. Slot-level formatting should return safe renderable segments rather than raw strings with cursor movement.
dangerouslyRawAnsi() exists as an escape hatch for callers that need raw ANSI. It can break width measurement, fallback rendering, and reset guarantees if used incorrectly, so keep it isolated.
laqu includes a pure TypeScript width engine:
import { displayWidth, truncateToColumns, wrapToColumns } from "@0disoft/laqu";
displayWidth("\u001b[31m한글\u001b[0m"); // 4
truncateToColumns("👩💻 building", 8, { overflowMarker: "..." });
wrapToColumns("abcd한글", 4);
ANSI/control sequences are tokenized as zero-width. Text is segmented by grapheme, CJK/fullwidth characters are treated as two columns, combining marks as zero columns, emoji/ZWJ clusters as two columns, and ambiguous width defaults to one column unless overridden.
Do not mix child process output with live rendering through stdio: "inherit". Pipe child output through the parent process and write it with runtime.log(), or close/pause the live renderer and run the child command in plain/log mode.
bun install
bun run check
bun run pack:check
bun run example:basic
bun run check runs strict typecheck, OXC lint, OXC format check, Node.js built-in tests, and build output generation.
bun run pack:check builds the package, runs an ESM consumer fixture through package self-reference imports, and verifies the package contents with npm pack --dry-run --json.
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.
GitHub Actions publishes npm releases from maintainer-created version tags. The tag must match package.json exactly, for example v1.0.2 for version 1.0.2.
git tag -a v1.0.2 -m "v1.0.2"
git push origin main v1.0.2
The npm package must define a Trusted Publisher connection for GitHub Actions with organization/user 0disoft, repository laqu, workflow filename release.yml, no environment name, and npm publish allowed. On a matching tag push, the workflow installs dependencies, checks the package, runs a dry pack verification, publishes @0disoft/laqu to npm through OIDC, and creates a GitHub Release with generated notes.
FAQs
Reliable CLI progress on stderr with clean stdout and versioned events.
The npm package @0disoft/laqu receives a total of 103 weekly downloads. As such, @0disoft/laqu popularity was classified as not popular.
We found that @0disoft/laqu demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Research
/Security News
Ten malicious OpenAPI React Query Codegen versions were published to npm in the Mini Shai-Hulud attack, all with valid provenance.

Security News
Socket joins more than 100 technology, cybersecurity, and financial organizations calling for a global surge in cyber defense.

Product
Enterprise security teams can now detect malware, credential theft, suspicious network activity, and risky updates across Microsoft Edge extensions.