Dev Toolsv0.1.7
@tekir/cli
tekir command-line tool: serve, build, test, and any provider-registered command.
Installation
$
bun add -g @tekir/cliFeatures
- `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:keyChangelog
v0.1.7LatestJuly 23, 2026
- Package metadata now follows the shared compatible
0.1.xdependency 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
# commentis trimmed without corrupting tokens likepa#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 testusesnpx --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 builddrives the new build-entry extractor in@tekir/core0.1.29. The cli reads the entry throughgenerateBuildEntry, writes the extracted source to a temp file, setsprocess.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 literaltekir()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 buildexportsTEKIR_RUNNER=build(via??=, so a CI script that already pins the value is left alone) before handing the entry to Bun, mirroring the'test'valuetekir testsets. 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 onTEKIR_RUNNER === 'build' || TEKIR_RUNNER === 'test'to short-circuit eager init. Convention documented at/advanced/runner-modes.oxc-parseris now a regular@tekir/clidependency instead of an optional peer.bun add @tekir/cliis enough to get the build-entry extractor and the autoload inliner working out of the box; the long-standing[build] \oxc-parser\is not installedwarning that confused users who never knew what to do with it is gone.@tekir/corekeepsoxc-parseras an optional peer for the rare consumer that uses the framework without the cli (e.g. drivingBun.buildprogrammatically with hand-rolled scripts).
v0.1.4May 8, 2026
- New
tekir test [args]command: a thin runner shim that exportsNODE_ENV=testplus theTEKIR_RUNNER=testsignalapp.start()listens for, then hands control to the runtime's native test runner (bun teston Bun,vitest runon Node). The signal is what lets a user entry's top-levelapp.start(callback)short-circuit when imported by a test file, so the canonical entry shape becomes the unconditionalapp.start(cb)and the per-appif (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/core0.1.28'sapp.start({ force: true })for integration tests that need a real socket.
v0.1.3May 5, 2026
tekir buildnow routes through the entry like every other command, so the user'stekir({...})instance gets to registeronBuildhooks before the bundle runs. Insidetekir()core,argv[2] === 'build'is detected and triggersserver.build()(which fires the hooks, e.g.@tekir/vitebuilds the frontend intodist/client/) followed byBun.buildfor the backend bundle. CallingrunBuilddirectly from the bin (the previous behavior) skipped the entry entirely and silently dropped any frontend build, so apps withfrontend: { type: 'vite' }shipped a backend bundle withoutdist/client/.runEntryno longer callsprocess.exit(0)after the import resolves. Forcing the exit was racing with three legitimate flows: the canonical fire-and-forgetserver.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-fileflag, 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. Thetekirshim created bybun add -g @tekir/cli(ornpm i -g) regenerates with this hint on upgrade, so existing scripts that chain--env-fileflags 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.jsonunder"tekir": { "envFiles": ["...", "..."] }are loaded automatically before the entry runs. Recommended for keeping per-package.envchains out of every script. Paths in JSON load first, then any CLI--env-file/--envfileflags layer on top with later-wins precedence; shell-provided env always wins both.
v0.1.0May 4, 2026
- Initial release