HQL Dependencies And Publishing

The normal HQL workflow has one tool and, when project metadata is needed, one manifest: hql.json. Generated JavaScript ecosystem files are implementation details; do not edit them.

Use A Dependency

For a script, write a versioned import and run the file:

(import [default as ms] from "npm:ms@2.1.3")
(print (ms "2s"))
hql app.hql

No project, install command, or manifest is required. In an HQL project, hql add npm:ms@2.1.3 records the dependency in hql.json, installs it, and updates the HQL-owned hql.lock. hql dev and hql build also install a missing dependency automatically.

Supported source forms are:

FormMeaning
./local.hql, .ts, or .jsLocal mixed-language module
npm:pkg@versionVersioned npm package
jsr:@scope/pkg@versionVersioned JSR package
https://example.com/module.tsExplicit remote ESM module
bare pkg@version with hql addNormalized to an npm dependency

Versions are required for registry dependencies. HQL never silently publishes or locks an implicit latest version.

Publish One HQL File

A single mod.hql is enough:

hql publish --dry-run
hql publish

Without hql.json, HQL infers the entry, a scoped name from the current user and directory, version 0.1.0, and both registries. The dry run performs the real npm and JSR validations without uploading.

Select one registry when wanted:

hql publish --target npm
hql publish --target jsr
hql publish --target all

Use hql.json only when inference is insufficient—for example, to choose a public name, version, description, license, multiple exports, or a permanent registry selection:

{
  "kind": "library",
  "name": "@example/math",
  "version": "1.0.0",
  "exports": {
    ".": "./mod.hql",
    "./stats": "./stats.hql"
  },
  "publish": ["npm", "jsr"]
}

hql init can materialize the inferred values, but it is not required:

hql init . --name @example/math --version 1.0.0

What Publish Guarantees

hql publish performs this sequence:

  1. Strictly compile every exported HQL module.
  2. Run the package's *_test.hql and *.test.hql tests.
  3. Emit ordinary ESM JavaScript and .d.ts declarations into dist/.
  4. Validate every selected registry before the first upload.
  5. Upload only after all local and registry dry-run checks pass.

The npm package has "type": "module", an ESM export map, and declaration paths. The JSR package is also ESM. Consumers do not install HQL; Node, Bun, JSR runtimes, bundlers, and browsers consume the generated JavaScript.

Two registries cannot provide one atomic cross-registry transaction. HQL preflights both to avoid preventable partial releases, but a network or service failure during the second upload can still leave the first registry published. Published versions are immutable, so recovery means fixing the external issue and publishing the same still-missing target—not overwriting a version.

Authentication is interactive when supported. Automation may provide HQL_NPM_TOKEN, HQL_NPM_OTP, and HQL_JSR_TOKEN; HQL never writes these secrets into the package.

Generated Output

hql pack writes:

dist/
  esm/             portable ESM for npm and browsers
  jsr/esm/         JSR-oriented ESM
  types/           TypeScript declarations
  package.json     generated npm metadata
  jsr.json         generated JSR metadata
  README.md
  LICENSE          when the selected license has generated/copied text

These files are publish output, not project configuration. The only source manifest is hql.json.

Existing JavaScript Or TypeScript Projects

An existing JS/TS project may keep its own package.json and package manager. Running its entry with hql is zero-config:

hql src/main.ts

If that project must keep Vite, esbuild, Rollup, Webpack, or Bun as its command, install hql-lang in that project and enable the matching adapter. This is the one unavoidable per-project integration because general-purpose bundlers do not discover a new source extension from a globally installed executable.

Next