tekir
All Packages
Dev Toolsv0.1.7

@tekir/cli

tekir command-line tool: serve, build, test, and any provider-registered command.

Installation

$bun add -g @tekir/cli

Features

  • `tekir serve` runs the entry in-process
  • `tekir serve --dev` re-execs with `--watch` for hot reloads
  • `tekir build --outdir <dir>` bundles without ever importing the entry, so Redis/message-bus side-effect modules stay quiet during build
  • `tekir build --compile` builds a single self-contained executable; the resulting binary dispatches commands directly (`./server routes`) without the bin
  • `tekir <command>` forwards any other command (`generate:key`, provider-registered, custom) to the in-app dispatcher in-process
  • Entry resolution (every command): `--entry <path>` flag → `tekir.entry` in `package.json` → first match among `index.ts`, `api/index.ts`, `app/index.ts`, `src/index.ts`, `index.js`. Positional arguments are never treated as the entry, so `tekir make:controller User` is unambiguous
  • `--env-file <path>` (multi) loads dotenv-style files before the entry runs. Shell env wins; later files override earlier ones; under Bun the flags also forward to `bun --watch` so a saved `.env` re-applies on each restart
  • Full `bun build` flag surface for production output: `--format esm|cjs|iife`, granular `--minify-syntax / --minify-whitespace / --minify-identifiers`, `--keep-names`, `--drop <name>`, `--env inline|disable|<PREFIX>*`, `--public-path <url>`, `--banner / --footer`, `--entry-naming / --chunk-naming / --asset-naming`, `--metafile <path>` and `--metafile-md <path>` for bundle analysis

Quick Example

TypeScript
# Install once, globally or as a dev dep
bun add -g @tekir/cli

# Default project layout: nothing extra to specify
tekir serve
tekir serve --dev                  # watch mode, NODE_ENV=development
tekir build --outdir ./dist        # plain bundle
tekir build --compile --outfile server
tekir routes                       # any built-in / provider / custom command
tekir make:controller UserController

# Renamed entry: set it once in package.json
# {
#   "tekir": { "entry": "server.ts" }
# }

# Or override per-invocation:
tekir serve --entry server.ts
tekir build --entry server.ts --compile

# Compiled binary runs commands directly. No bin needed:
./server
./server routes
./server generate:key

Changelog

v0.1.7LatestJuly 23, 2026
  • Package metadata now follows the shared compatible 0.1.x dependency range used by this coordinated Tekir release.
v0.1.6June 13, 2026
  • The entry path is now validated to stay under the current working directory before it is imported, so a crafted --entry ../../evil.ts (or an absolute path outside the repo) is refused rather than executed. Both the run and build paths share this guard.
  • Env-file loading no longer double-applies. After the parent loads env files it marks them so the re-exec'd watch child inherits the flag and skips reloading, removing duplicate loads and warnings. Quoted env values are taken verbatim and an unquoted trailing # comment is trimmed without corrupting tokens like pa#ss.
  • Writing the temporary build entry is now wrapped so a read-only directory produces a clear warning and falls back to a full-entry import instead of crashing.
  • On Node, tekir test uses npx --no-install vitest run, so a missing local vitest fails fast instead of silently downloading from the registry.
  • Found and fixed with Fable.
v0.1.5May 10, 2026
  • tekir build drives the new build-entry extractor in @tekir/core 0.1.29. The cli reads the entry through generateBuildEntry, writes the extracted source to a temp file, sets process.argv[1] to the original entry path so the in-app build dispatcher bundles the real file, then imports the temp source. User entries that the extractor cannot statically resolve (no literal tekir() call, multiple calls, parse error) fall through to a plain full-entry import as a last resort, so the worst case is identical to the historical behaviour.
  • tekir build exports TEKIR_RUNNER=build (via ??=, so a CI script that already pins the value is left alone) before handing the entry to Bun, mirroring the 'test' value tekir test sets. Most library code is no longer imported during build at all (the entry extractor sees to that), so the flag is a belt-and-suspenders safety net for the rare entry shape that falls back to a full-entry import; libraries can still gate on TEKIR_RUNNER === 'build' || TEKIR_RUNNER === 'test' to short-circuit eager init. Convention documented at /advanced/runner-modes.
  • oxc-parser is now a regular @tekir/cli dependency instead of an optional peer. bun add @tekir/cli is enough to get the build-entry extractor and the autoload inliner working out of the box; the long-standing [build] \oxc-parser\ is not installed warning that confused users who never knew what to do with it is gone. @tekir/core keeps oxc-parser as an optional peer for the rare consumer that uses the framework without the cli (e.g. driving Bun.build programmatically with hand-rolled scripts).
v0.1.4May 8, 2026
  • New tekir test [args] command: a thin runner shim that exports NODE_ENV=test plus the TEKIR_RUNNER=test signal app.start() listens for, then hands control to the runtime's native test runner (bun test on Bun, vitest run on Node). The signal is what lets a user entry's top-level app.start(callback) short-circuit when imported by a test file, so the canonical entry shape becomes the unconditional app.start(cb) and the per-app if (env !== 'test') guard goes away. Forwarded args go to the runner verbatim: tekir test --watch, tekir test path/to/file.test.ts, etc. Pairs with @tekir/core 0.1.28's app.start({ force: true }) for integration tests that need a real socket.
v0.1.3May 5, 2026
  • tekir build now routes through the entry like every other command, so the user's tekir({...}) instance gets to register onBuild hooks before the bundle runs. Inside tekir() core, argv[2] === 'build' is detected and triggers server.build() (which fires the hooks, e.g. @tekir/vite builds the frontend into dist/client/) followed by Bun.build for the backend bundle. Calling runBuild directly from the bin (the previous behavior) skipped the entry entirely and silently dropped any frontend build, so apps with frontend: { type: 'vite' } shipped a backend bundle without dist/client/.
  • runEntry no longer calls process.exit(0) after the import resolves. Forcing the exit was racing with three legitimate flows: the canonical fire-and-forget server.start().catch(...) pattern (Bun.serve was getting killed mid-bind the moment import completed), in-app dispatchers that exit on their own, and any top-level async work the user awaited. The runtime exits naturally when the event loop drains in all three cases.
v0.1.2May 4, 2026
  • Bin shebang now routes through Bun (#!/usr/bin/env bun). Bun is position-strict on its own --env-file flag, so --env-file=... tokens after the script path pass through to the bin's argv where the in-bin loader filters missing files with a warning and keeps the rest. The tekir shim created by bun add -g @tekir/cli (or npm i -g) regenerates with this hint on upgrade, so existing scripts that chain --env-file flags work unchanged.
  • --envfile (no hyphen) added as a Node-host-safe alias of --env-file. The hyphenated form is intercepted by Node's runtime before the bin runs and hard-errors on a missing file; the un-hyphenated form is unrecognized by Node's CLI parser and is forwarded to the script's argv unchanged. Useful when invoking the bin directly under Node (node node_modules/@tekir/cli/bin/tekir.mjs --envfile=path serve).
  • Env files declared in package.json under "tekir": { "envFiles": ["...", "..."] } are loaded automatically before the entry runs. Recommended for keeping per-package .env chains out of every script. Paths in JSON load first, then any CLI --env-file / --envfile flags layer on top with later-wins precedence; shell-provided env always wins both.
v0.1.0May 4, 2026
  • Initial release

Other Dev Tools packages