npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

trik-run

v0.1.1

Published

A universal task runner with smart caching and file-based task discovery

Readme

trik

A universal task runner with smart caching and file-based task discovery. Built for Bun.

Tasks live in a .trik/ directory as plain TypeScript files — no config files, no plugins, just code.

Quick Start

bun install -g trik
trik init              # creates .trik/ with an example task
trik hello             # runs the example

Defining Tasks

Tasks are TypeScript files inside .trik/. Each file exports a default class whose @Task()-decorated methods are procedures. Calling trik <name> runs the default() procedure.

// .trik/build.ts
export class Build {
  @Task()
  async compile() {
    await $`tsc`;
  }

  @Task()
  async lint() {
    await $`eslint src/`;
  }

  @Task()
  async test() {
    await Promise.all([this.compile(), this.lint()]);
    await $`vitest run`;
  }

  @Task()
  async default() {
    await this.test();
  }
}

export default Build;

Run specific procedures with task:proc syntax:

trik build             # runs default()
trik build:compile     # runs compile()
trik build:lint        # runs lint()

Function-based Tasks

For simple single-step tasks, export a plain async function:

// .trik/clean.ts
export default async function clean() {
  await $`rm -rf dist`;
}

Caching

@SuccessCache

Skip a procedure if it succeeded last time:

@SuccessCache()
async install() {
  await $`npm ci`;
}

@FunctionCache + FileCache

Re-run only when input files change:

@FunctionCache(() => FileCache("compile", {
  inputs: ["src/**/*.ts"],
  outputs: ["dist/"],
}))
async compile() {
  await $`tsc`;
}

CacheGate Combinators

Combine multiple cache conditions:

@FunctionCache(() => CacheGate.all([
  FileCache("build", { inputs: ["src/**/*.ts"] }),
  PreviousSuccessCache("install"),
]))
async build() {
  // ...
})
  • CacheGate.all([...]) — skip if ALL assertors pass
  • CacheGate.any([...]) — skip if ANY assertor passes
  • CacheGate.not(assertor) — negate an assertor

Custom Assertor

@FunctionCache(() => async (ctx) => {
  return ctx.cache["my-task"]?.["my-proc"]?.status === "success";
})
async deploy() {
  // ...
}

Shell Commands

The $ tagged template literal runs shell commands:

await $`echo hello`;
await $`npm run build`;

// Capture output
const { stdout } = await $`git rev-parse HEAD`.capture();

// Quiet mode — suppress all output
await $`some-command`.quiet();

// Per-command shell override
await $.withShell("pwsh")`Write-Host "hello"`;

// Project-wide default shell
$.setShell("pwsh");

Supported shells: "sh", "cmd", "pwsh", "nu", custom string[], or false for direct execution.

Task DAG

@Task() methods deduplicate automatically — calling the same method twice returns the same Promise. Express dependencies naturally:

export class Ci {
  @Task() async lint()   { await $`eslint .`; }
  @Task() async typecheck() { await $`tsc --noEmit`; }
  @Task() async test()   { await $`vitest run`; }

  @Task()
  async default() {
    // lint + typecheck in parallel, then test
    await Promise.all([this.lint(), this.typecheck()]);
    await this.test();
  }
}

Cross-file Task References

Reference tasks across .trik/ directories (useful in monorepos):

const build = await trik.task("build");
await build.default();

// Discover all matching instances across packages
const allBuilds = await trik.tasks("build");
await Promise.all(allBuilds.map(b => b.default()));

Context

Ctx provides runtime info inside any task:

Ctx.env         // process.env
Ctx.os          // process.platform
Ctx.args        // positional args after --
Ctx.flags       // parsed --key=value flags
Ctx.git         // Promise<{ branch, sha, isDirty }>

CLI Reference

trik <task>              Run a task (calls default())
trik <task>:<proc>       Run a specific procedure
trik <task> -- --flag    Pass flags/args (Ctx.flags, Ctx.args)
trik list                List all tasks
trik list <task>         List procedures in a task
trik init                Initialize .trik/ in current directory
trik clean               Delete the task cache file
trik help                Show help

Options:
  -v, --verbose          Show all logs
  -f, --force            Ignore cache, re-run everything
  -n, --dry-run          Show what would run without executing
  -w, --watch            Re-run on file changes
  -j <n>                 Max concurrent procedures
  --silent               Suppress all output
  --log <level>          Set log level (default: 3)

Task Config

Export a config object for metadata:

export const config: TaskConfig = {
  name: "deploy",
  description: "Deploy to production",
  scope: "root",              // only runnable from workspace root
  cwd: "workspace-root",      // chdir before execution
  cache: "previous-success",  // or FileCache config, or custom function
};

export default async function deploy() {
  await $`npm run deploy`;
}

Monorepo Support

trik searches for .trik/ directories both upward and downward from the current directory. Place .trik/ in each package and run tasks from anywhere:

monorepo/
├── packages/
│   ├── app/
│   │   └── .trik/
│   │       └── build.ts
│   └── lib/
│       └── .trik/
│           └── build.ts
└── .trik/
    └── ci.ts

trik ci from the root runs the top-level task. Tasks can reference sub-package tasks via trik.task("build").

License

MIT