[Changelog]
Release notes for HOOX packages (CLI and related).
All notable changes to @hoox-sh/hoox-cli are documented here.
This project adheres loosely to Semantic Versioning.
Unreleased
[0.13.0] — 2026-08-13
Added
- Workers mesh security hardening (ships with current worker submodules +
@hoox-sh/[email protected]):- Gateway two-phase idempotency (reserve / commit / release), sharded DO keys, fail-closed missing DO
- Atomic rate-limit Durable Object (
RATE_LIMITER) with KV/memory fallback - Telegram notify chatId allowlists (hoox + telegram-worker), 64 KiB body caps
- Named D1 RPCs: list-signals, list-system-logs, list-open-positions
- Env-first AI provider secrets on agent-worker; Google key via header
- Mesh-wide
safeWaitUntil(including DO lifecycle on trade-worker) - report-worker body gate, chatId policy, auth fail-closed tests
- Deploy checklist:
workers/hoox-worker/DEPLOY.md(DO migrations v1/v2 + allowlist secrets)
Changed
- Parallel KV bulk gets (
kvGetMany), dashboard parallel settings/secrets probes - Trade HTTP idempotency stores only after success; REST-only order placement
- Time-bucketed auto fingerprints; softer trade log sampling
[0.11.9] — 2026-08-11
Fixed
- TUI global install crash (
@hoox-sh/[email protected]): remove@opentui-ui/dialog(nested second OpenTUI core →OPENTUI_FORCE_WCWIDTHdual-register). In-houseDialogProvider/showConfirmonly.
[0.11.8] — 2026-08-11
Fixed
- TUI startup crash (
@hoox-sh/[email protected]): remove dual-OpenTUI toast mount that re-registeredOPENTUI_FORCE_WCWIDTHand crashed globalhoox-tuiinstalls. Toast helpers are fail-closed; status bar + alerts remain.
[0.11.7] — 2026-08-11
Added
- TUI quality release (ships with
@hoox-sh/[email protected]+@hoox-sh/[email protected]): reconnect controller, overlay-safe keyboard, Service Manager/Dashboard keyboard ops, fail-closed prefs path, auth/Access parity, diagnostics palette.
Notes
- CLI surface unchanged; monorepo release tag for TUI/shared publish + Docker.
[0.11.6] — 2026-08-11
Added
- Monorepo auto-detect & remember: on startup resolve root via
HOOX_REPO→ walk-up from cwd →~/.hoox/config/monorepo.json→~/.hoox/repo, persist the path, set sessionHOOX_REPO, andchdirsohxworks from any directory (e.g.~/Videos). - Doctor: shows Remembered monorepo path and accurate resolution Source.
- Docs: installation, quick-start, CLI reference, glossary, cli-features, monorepo README updated for any-cwd usage.
Fixed
isHooxSetupRoot: accept fresh-clone markers (wrangler.jsonc.example,workers/,.gitmodules) without requiring gitignoredwrangler.jsonc.
[0.11.5] — 2026-08-10
Added
- Linear Rail banner: default CLI banner is compact
◆ H · O · O · Xwith tagline/version; TTY assemble → pulse → settle animation; polishedhorizon/signalvariants; compact◆ Hoox · v…line.
Fixed
hoox check setupsecrets UX: no longer warns for healthy local secrets or “remote listed OK”; remote check parses secret names and only fails when declared secrets are missing on Cloudflare® (withhoox secrets synchints).
[0.11.4] — 2026-08-10
Fixed / hardened
- Onboard: do not run setup when init cancels/incomplete (require
wrangler.jsoncafter step 1). - ensurePackages: detect built packages via
dist/*.jsdirectory scan (no more always-rebuild). - Workers gate: abort setup when worker trees are still missing after submodule clone.
--skip-keys: load mesh keys from.keys/setup.envso secrets can still push.hoox keys generate: also writesetup.env+ chmod0700/0600on key material.- Secret files: chmod
0600on.dev.vars/.env.localwriters (init, env, secrets, setup). - formatError: emit on stderr (mirrored to stdout for compatibility).
- Secrets missing config: recovery text points to
hoox onboard/hoox init. - Release workflow: idempotent TUI re-publish; fail only when CLI/auth fails.
- Docs:
logs worker/check setup(removed stalelogs tail/check-setup).
[0.11.3] — 2026-08-10
Fixed / ship-readiness (CLI bootstrap & exit codes)
verifyRepoRoot: accept pre-init monorepo markers (packages/cli+wrangler.jsonc.example/workers//.gitmodules) so fresh clones can runhoox init/onboardwithout a gitignored root config.- Init cancel / risk decline / bad token: always
returnafter cancel or failed non-interactive validation (no fall-through config write). - Onboard: do not run setup when init fails; keep
CLOUDFLARE_API_TOKEN/CLOUDFLARE_ACCOUNT_IDfor setup; auth gate with actionable hints. - Setup
generateKeys: merge mesh keys into existing.dev.vars(preserve integration secrets); honor--skip-secrets; chmod.keys0700and secret files0600. - Exit codes: Commander
exitOverriderethrows so process exit matches card codes; unknown command / missing args → exit2; help/version stay0. - Double error print: suppress Commander default lines when we emit a formatted card; completion footer respects
--json/--quiet. - Wrangler preAction: check-only by default (set
HOOX_AUTO_UPDATE_WRANGLER=1to auto-install). - Bun guard in
bin/hoox.jsbefore imports; recovery text useshoox onboard/hoox init(notconfig init). - Defaults / hints: D1 fallback
trade-data-db; schema unknown worker throws with known list; next-step map onboard → check setup → deploy. - Docs: CLI command tree, installation flow, README no-args behavior aligned with code.
[0.11.2] — 2026-08-10
Fixed / hardened (mesh)
- Signal path hardening (workers + shared): unified kill-switch helper (
@hoox-sh/hoox-shared/kill-switch), trade-worker entry idempotency, pyne→trade mesh auth + safe event mapping, exchange↔D1 position reconciliation on agent housekeeping. - Idempotency alignment: gateway forwards resolved
Idempotency-Keyto trade-worker (binding + queue); queue consumer stores dedupe keys only after successful execute. - Operator SSE:
/v1/trades/streamand/v1/logs/streampoll live trade-worker feeds (no longer one-shot stubs). - Depends on
@hoox-sh/hoox-shared@^1.2.1.
[0.11.1] — 2026-08-09
Fixed
hoox secrets sync: always pass-c <worker wrangler config>(and--name) so wrangler does not walk up to the monorepo root meta-config. Falls back towrangler.jsonc.examplewhen the real config is gitignored (e.g. hoox-worker).- Worker wrangler configs: remove invalid
smart_placementand monorepo-onlysecretsarrays that madewrangler secret putfail validation.
[0.11.0] — 2026-08-09
Added
hoox pynecommand group for the Python pyne-worker isolate:health— probeGET /health(JSON/table)run— evaluate a.pinescript viaPOST /runscripts list|get|deploy|delete— R2 script registrycron jobs|run,feed refresh— bar-close scheduler helpersingest— wrapscripts/fetch_and_ingest.pysync-vendor/deploy— vendor pynescript thenwrangler deploy
- pyne-worker in deploy order, env catalog (
API_KEY,ALERT_WEBHOOK_URL,PYNE_API_KEY,PYNE_WORKER_URL), worker manifest registry, interactive menu Tools, and shell completions. - Configurable agent cron (1–1440 min) and setup secrets UX improvements.
- TUI 0.2.0 (optional
@hoox-sh/hoox-tui): dashboard PYNE health, full 16-view session restore, Ctrl+digit / Ctrl+Alt navigation coverage, broader operator views polish.
Fixed / hardened
- TUI reliability: SSE
stopStreams()teardown, stalefetchWorkersdrop, safe-mode skip of network/CLI/SSE, stable global keyboard handler. - Remote auth fail-closed: Bearer (
HOOX_API_TOKEN) and/or Cloudflare® Access service-token pair; CLI fallback never used in remote mode. - CLI bridge: abort signals, timeout kill escalation, noise-tolerant JSON parse, argv secret redaction in logs/status.
- State paths: session path resolves at call time; TUI state path traversal rejected; atomic JSON state writes.
Dependencies
- Requires
@hoox-sh/hoox-shared@^1.2.0(workspace-aligned). Optional TUI:@hoox-sh/hoox-tui@^0.2.0.
[0.10.1] — 2026-07-26
Added
- Outside-repo TUI resolution: global
@hoox-sh/hoox-tuiinstall, bun/npm global paths,hoox-tuion PATH. hoox doctor --fix-runtimeclonesgithub.com/hoox-sh/hoox(auto-removes broken~/.hoox/reposymlinks).
Fixed
- Clearer TUI missing-entry guidance (
bun add -g @hoox-sh/hoox-tuior fix-runtime).
[0.10.0] — 2026-07-26
Operator security plane for remote TUI/CLI. Requires matching @hoox-sh/[email protected] and a gateway deploy that includes authenticated /v1/* routes (OPERATOR_API_KEY).
Added
hoox tui --remote/--api-url/--token/--debug/--allow-insecure- Fail-closed remote launch: requires Bearer (
HOOX_API_TOKEN/--token), Access service-token env (CF_ACCESS_CLIENT_ID+CF_ACCESS_CLIENT_SECRET), or explicit--allow-insecure. - Forwards
HOOX_TUI_MODE, operator token, debug flags, and optionalHOOX_TRANSPORTfrom~/.hoox/config.json.
- Fail-closed remote launch: requires Bearer (
- Operator transport profile (via shared package):
public|access|mtls|tunnel- Client attaches
Authorization: Bearer …and optional Cloudflare® Access service-token headers. HOOX_TRANSPORTenv overrides; config fallbacks viahoox config transport.
- Client attaches
hoox doctor --security— hygiene checks + optional anonymous/authedGET /v1/healthprobes (Access gate vs open surface).hoox tunnel check— detectcloudflared, print private-ingress guidance, optional management probes.hoox config transport/transport set— show/persist operator transport preference (0600config file).- Management API contract (gateway):
GET /v1/health,/v1/workers, SSE/v1/trades/stream&/v1/logs/streambehindrequireOperatorAuth(OPERATOR_API_KEYpreferred,INTERNAL_API_KEYlegacy). - Docs: private ingress runbook, zero-trust CLI section, TUI security posture, open-core vs Enterprise split updates.
Security
- Config writes use owner-only modes (
~/.hoox0700,config.json0600). - TUI debug log redacts nested secret keys, Bearer strings, and env-style token assignments.
- Doctor/tunnel output never prints secret values.
Changed
- TUI HTTP/SSE paths use versioned operator routes:
/v1/workers,/v1/trades/stream,/v1/logs/stream. - Completion script includes
doctorandtunnel.
Upgrade notes
# Worker (once per environment)
wrangler secret put OPERATOR_API_KEY # same value as client token
# Client
export HOOX_API_TOKEN=…
# optional Access:
export CF_ACCESS_CLIENT_ID=…
export CF_ACCESS_CLIENT_SECRET=…
export HOOX_TRANSPORT=access
hoox doctor --security --api-url https://mgmt.example.com
hoox tui --remote --api-url https://mgmt.example.com
Prefer a mgmt hostname behind Cloudflare® Access; keep TradingView® /webhook separate. See docs/devops/deployment/private-ingress.mdx.
[0.9.5] — 2026-07-20
Removed
hoox pinecommand group and all pine-worker / pyne-worker submodule requirements. Pine Script™ tooling is no longer part of the open-core CLI.
Fixed
-
hoox monitor queue-depth— wrangler ≥4.x removedqueues list --json. The command now runs the human table form and parses it for--jsonoutput. -
hoox monitor kill-switch/ KV resolve — wrangler version banners on stdout brokeJSON.parseand polluted KV values. Namespace list usesextractJsonArray;kv getstrips banners so kill-switch reportson/offcorrectly. -
hoox check health— no longer uses long-livedwrangler tail(hung ~50s+ per worker). Probes each worker with HTTPGET /health(8s timeout) and reports latency. -
hoox db list(local) — root monorepowrangler.jsoncis a Hoox meta-config without D1 bindings. Local D1 ops now pass-c workers/d1-worker/wrangler.jsoncwhen present (HOOX_WRANGLER_CONFIGoverride supported). -
hoox repair check— prints a per-step status table (and full JSON with--json) instead of only"N check(s) failed". -
hoox trace destinations— defaults to listing destinations when no subcommand is given (was help + exit 1).
[0.9.3] — 2026-07-11
Added
-
Dramatically extended hop-level tracing and observability for performance measurement (key for the HOOX arXiv paper):
hoox perf fastpathnow emits and reports much finer-grained hops (e.g.hoox:hoox-gateway,trade-worker:trade-worker-receive, preflight, DO mutex, binding dispatch, etc.).ObservabilityReaderimproved to parse explicithopfields in addition to legacy per-service timings.- Structured JSON logs (
probe_id,hop,duration_ms) for easy correlation withhoox traceand Analytics Engine. hoox perf fastpath reportandhoox tracenow support detailed per-hop reconstruction and full trace timelines.- Added rich hop breakdown tables and trace collection guidance in the paper's evaluation + reproducibility sections.
-
Updated reproducibility commands and documentation to highlight the new extended tracing capabilities.
Changed
- Minor internal improvements to fast-path probe handling and observability parsing for richer measurement data.
Documentation
- Updated
hoox-arxiv-paper*(core + full),arxiv-submission.md,A-reproducibility.tex, and related sections to reference the richer hop/traces support and Smart Placement rationale. - Implementation table now lists CLI v0.9.3.
[0.9.2] — 2026-06-26
Fixed
-
formatBadge now matches the v0.9.0 CHANGELOG claim (which the code hadn't implemented): the badge style is now "colored glyph + colored text" (Vercel / Linear style) — e.g.
✓ ok,✗ fail,⚠ warn,ℹ info— instead of high-contrast background chips.BADGE_STYLErestructured to{ icon, color, defaultLabel }; default labels are lowercase to match the modern-minimal palette. -
5 previously-failing tests now pass (CI was red on v0.9.1):
formatBadge > pads short custom text to 4 chars— moot after the rewrite.formatHint > emits a dimmed hint line in rich mode— test now clearsprocess.env.NO_COLORin itsbeforeEach(the local shell env hadNO_COLOR=1, which madeisRichMode()return false and the function bail).formatCompletion > renders success + message + duration in human mode— same NO_COLOR fix.formatCompletion > renders a 'next: ...' line when a suggestion is provided— same NO_COLOR fix.ConfigService > load() falls back to current directory when home config missing— test now creates a realwrangler.jsoncin a tmp cwd andprocess.chdirs into it before callingload(). The code's "fall back to cwd" branch was never being exercised by the test.
-
Dev test suite no longer hangs
bun test/bun test --coverage. Root cause:withErrorHandlingwas callingprocess.exit(1)on caught errors, which killed the test runner mid-suite. The fix is the bigger one in "Changed" below — the wrapper now setsprocess.exitCodeonly. -
3 pre-existing test bugs surfaced by the now-functional coverage summary:
registerConfigCommand > registers the 'config' command on the program— assertion matched an outdated summary string.registerRepairCommand > repair worker <name> > calls deploy for the specified worker— test was missingConfigServiceprototype mocks forload()andgetWorker().registerFastpathCommand > rejects invalid --action values with exit code 2/rejects --n > 1000 with exit code 2— tests mockedprocess.exitdirectly; the wrapper no longer calls it.
-
format-mode.test.tsORIGINAL_ENV snapshot is now describe-scoped (withbeforeAll/afterAllsymmetry) so cross-file test pollution fromprocess.envmutations doesn't leak. -
Coverage for
trace-service.ts(1.79% → 100%) — added 29 unit tests covering the constructor/credentials validation,query(events/calculations/invocations views),queryEvents,queryMetrics,listKeys,listValues, destinations CRUD,getUsage, live tail, and thecfApierror paths (HTTP error, network error, Auth header). -
Coverage for
setup-service.ts(35% → 99.89%) — added 14 unit tests covering the actual execution paths:generateKeys(with real file writes),applySchema(spawn success/failure/missing schema),setSecrets(success and CloudflareService.putSecret failure),rebuildDashboard(build + deploy + missing dir), andrunAllorchestration (all-flags, skip flags, failure path). -
Coverage for
error-handler.ts(44% → ~95%) andprerequisites-command.ts(30% → ~95%) — added tests forwithErrorHandling(all error branches + service name prefix) andsuggestForCommand(short input, no match, close match, nested subcommand walk).
Changed
-
Removed all 13
process.exit()calls fromsrc/index.tsandsrc/utils/error-handler.ts. Every error path now setsprocess.exitCode = Xinstead. A singleprocess.exit(process.exitCode)inmain()'sfinallyblock is the only exit point. This is what fixes the dev test hang, and it also lets test runners intercept via Commander'sexitOverridewithout monkey-patchingprocess.exit. -
Refactored
src/index.ts(411 → 320 lines):- All 36 imports moved to a single block at the top of the file.
hoox completionextracted into its own folder:src/commands/completion/{index.ts,completion-command.ts,completion-command.test.ts}(5 new tests).- Dev/deploy preAction update hooks moved into
src/commands/dev/register.tsandsrc/commands/deploy/register.ts, gated by a sharedsrc/utils/update-check.ts > attachUpdateCheck()helper (4 new tests). Subcommand renames can no longer silently disable the check. (thisCmd as Command & { _hooxStartedAt?: number })casts replaced with a module-levelWeakMap<Command, number>.
-
Replaced dead
theme.cornerexport with atheme.boxfamily of named primitives (topLeft,topRight,bottomLeft,bottomRight,horizontal,vertical).src/ui/banner.tsnow usestheme.box.*for its box-drawing characters instead of hand-rolling them withtheme.textFaint(the Horizon variant keeps its inline rounded corners since those aren't in the square-corner set). -
bin/hoox.jsnow falls back tosrc/index.tswhendist/index.jsis missing. The fallback lets contributors and CI jobs that haven't yet runbun run buildstill execute the CLI directly viabun bin/hoox.jsor abun link-based install. Production releases continue to build first (theprepublishOnlyscript enforces this). -
ConfigService.loadsplit into two methods. NewtryLoad(configPath?)returnsConfigResult— a typedResult<HooxConfig, ConfigError>with a discriminatedConfigErrorunion (not-found | invalid-jsonc | not-object). The oldload(configPath?)is preserved as a thin wrapper that throws with a clear English message — backward-compatible with the 15+ existing callers, but new code can usetryLoad()for explicit error handling.ConfigErroris exported fromsrc/services/config/index.ts.
Added
- Per-file coverage gate:
bun run coverage:checkrunsscripts/check-coverage.ts, which parsescoverage/lcov.infoand fails on anypackages/cli/src/**file (excluding tests, barrelindex.tsre-exports, and files < 10 source lines) below the 50% line-coverage floor. The floor is intentionally low so future PRs can ratchet it up incrementally as more files get tests. Wired into the rootpackage.jsonscripts.
Verification
| Check | Before (0.9.1) | After (0.9.2) |
|---|---|---|
bun run typecheck (all 14 workspaces) | ✅ | ✅ |
bun run lint (CLI) | ✅ | ✅ |
bun test (CLI) | ❌ 5 fail / 728 total | ✅ 0 fail / 794 total |
bun test --coverage (CLI) | ❌ hangs (no summary) | ✅ completes, prints table |
bun run coverage:check | ❌ no gate | ✅ 8 src/ offenders (down from 16) |
process.exit() in handlers | 13 | 0 |
src/index.ts line count | 411 | 320 |
Audit
Full audit at .opencode/audit/2026-06-26-full-audit.md. Task tree at .opencode/tasks/cli-audit-2026-06-26/. Coverage gate script at scripts/check-coverage.ts.
[0.9.1] — 2026-06-25
Fixed
- Banner version lookup broken in global install:
ui/banner.tsused a relative path (../../package.json) that works from source but not from the bundleddist/index.jsin a globally-installed package. When the user ranhooxwith no args, the banner tried to read/path/to/install/@hoox-sh/package.json(which doesn't exist) and threwENOENT. The fix walks up fromimport.meta.urllooking for the hoox-clipackage.jsonby name, working in both layouts.
[0.9.0] — 2026-06-24
Added
- New
--no-colorglobal flag to disable all ANSI color output (alongside--jsonand--quiet). NO_COLORenv var honored (https://no-color.org standard).formatCompletion(message, { durationMs, suggestion })— new formatter that prints a "✓ Done in 1.2s" footer with an optional "→ next: hoox …" suggestion. Wired into the globalprogrampostAction hook.- "Did you mean …" suggestions for unknown commands via Levenshtein distance. A typo like
hoox deplpynow suggestshoox deploy. - Custom help formatter —
hoox --helpand per-command--helprender with sectioned layout (Usage / Options / Examples / See also) and refined colors. formatNumber(n)— compact notation (1.2K, 1.5M, 2.5B) used byformatTablenumber auto-alignment and by perf/monitor/trace.formatBytes(n, { binary? })— SI (KB/MB) or binary (KiB/MiB).
Changed
- Theme palette refined to a modern-minimal aesthetic (zinc/slate base, single indigo-400 accent, de-saturated status colors). Visual change ripples through every command; information content unchanged.
- Badge style —
formatBadge()no longer uses high-contrast background chips; now renders colored glyph + colored text (Vercel / Linear style). - Spinner — uses braille dots (
⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏) instead of plain ASCII. formatTableoptions — now supportszebra,alignNumbers,colorizeStatus,compact(all default to on, exceptcompactwhich defaults to off). Backward compatible.formatErroroptions — now acceptssuggestions: string[]andinCard: boolean. JSON output includes a newsuggestionsfield.- Banner default — now
minimal(waslegacy).
Fixed
- Banner version drift:
ui/banner.tswas hardcoded tov0.3.0while the package was atv0.8.0. Now reads dynamically frompackage.json.