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

@orxataguy/tyr

v1.0.17

Published

Tyr is a TypeScript-based environment that resolves this fragmentation through the creation, execution, and automation of CLI tools. Its architecture is built on dependency injection: the "Kernel" provides an execution context where "Managers" expose thei

Readme


What is Tyr?

Tyr solves the fragmentation problem in DevOps scripting. Instead of maintaining scattered shell scripts, ad-hoc Node utilities, and undocumented automation glue, Tyr gives you a single, typed, dependency-injected context from which every command operates.

You write a function. Tyr takes care of everything else — argument routing, dependency resolution, error formatting, and live documentation.


Installation

npm install -g @orxataguy/tyr

Or as a project dependency:

npm install @orxataguy/tyr

After installing, run the setup command to initialize Tyr in your project:

tyr install

This creates the expected folder structure and registers the tyr alias in your shell config.


Quick Start

1. Create a command

tyr gen greet greet

This generates src/commands/greet.tyr.ts and registers it in config/map.yml.

2. Edit the command

import { TyrContext } from '../core/Kernel';

export default ({ task, fail, logger }: TyrContext) => {
    return async (args: string[]) => {
        if (args.length === 0) {
            fail('A name is required', 'Usage: tyr greet <name>');
        }

        await task('Greeting', async () => {
            logger.success(`Hello, ${args[0]}!`);
        });
    };
};

3. Run it

tyr greet World

Core Concepts

Kernel

The Kernel is the main engine. It boots on every invocation, loads config/map.yml, resolves the command name to a module, and executes it with a fully-wired TyrContext.

You never instantiate the Kernel directly — it runs automatically via bin/tyr.js.

Container & Dependency Injection

All services (Managers) are instantiated once by the Container and injected into every command via TyrContext. You never import a Manager directly — you destructure it from the context:

export default ({ shell, fs, git, logger }: TyrContext) => {
    return async (args: string[]) => {
        const branch = await git.currentBranch();
        logger.info(`On branch: ${branch}`);
    };
};

TyrContext

The object injected into every command. It exposes all available Managers plus framework utilities:

| Property | Type | Description | |---|---|---| | logger | Logger | Colored terminal output | | task | Function | Wraps async ops with error context | | fail | Function | Throws a controlled TyrError | | run | Function | Invokes another Tyr command programmatically | | shell | ShellManager | Execute shell commands | | fs | FileSystemManager | File and directory operations | | pkg | PackageManager | npm package management | | docker | DockerManager | Docker container operations | | git | GitManager | Git operations | | system | SystemManager | OS-level utilities | | sql | SQLManager | MSSQL database queries | | web | WebManager | HTTP requests and web scraping |

Commands

A command is an exported default function that takes a TyrContext and returns an async handler:

export default (context: TyrContext) => {
    return async (args: string[]) => {
        // your logic here
    };
};

Commands are registered in config/map.yml:

commands:
  greet: ./src/commands/greet.tyr.ts
  deploy: ./src/commands/deploy.tyr.ts

Built-in Commands

tyr gen <command-name> [output-file]

Scaffolds a new command file and registers it in config/map.yml.

tyr gen deploy deploy
# creates src/commands/deploy.tyr.ts

tyr rem <command-name>

Removes the command file and its entry from config/map.yml.

tyr rem deploy

tyr doc

Parses JSDoc from all Managers and serves an interactive HTML reference at http://localhost:3000. Useful for discovering available methods without leaving your terminal.

tyr doc
# → Open http://localhost:3000

Context API Reference

task(label, fn)

Wraps an async operation. If it throws, Tyr captures the error, adds the label as context, and formats a clean error message — no manual try/catch needed.

const result = await task('Building project', async () => {
    return await shell.exec('npm run build');
});

fail(message, suggestion?)

Immediately stops command execution with a formatted error. Optionally include a suggestion to guide the user.

if (!args[0]) {
    fail('Missing required argument: name', 'Run: tyr greet <name>');
}

run(commandName, args)

Invokes another registered Tyr command from within a command. Enables command composition.

await run('install', ['--force']);

logger

Standardized colored output. Warnings and errors are suppressed unless --debug is passed.

logger.info('Starting...');
logger.success('Done.');
logger.warn('Skipping optional step.');
logger.error('Something went wrong.');

Error Handling

Tyr distinguishes between controlled and uncontrolled errors.

Controlled — use fail() for expected validation failures:

fail('Config file not found', 'Create a config.yml in the project root.');

Uncontrolled — wrap risky operations in task():

await task('Connecting to database', async () => {
    await sql.connect(connectionString);
});

Run any command with --debug to see the full stack trace:

tyr deploy --debug

Project Structure

├── bin/
│   └── tyr.js                 # CLI entry point
├── src/
│   ├── core/
│   │   ├── Kernel.ts          # Command router and execution engine
│   │   ├── Container.ts       # Dependency injection container
│   │   ├── TyrError.ts        # Structured error type
│   │   └── sys/
│   │       ├── gen.ts         # Built-in: scaffold a command
│   │       ├── rem.ts         # Built-in: remove a command
│   │       └── doc.ts         # Built-in: serve live documentation
│   ├── commands/
│   │   └── *.tyr.ts           # Your custom commands go here
│   └── lib/
│       ├── ShellManager.ts
│       ├── FileSystemManager.ts
│       ├── PackageManager.ts
│       ├── DockerManager.ts
│       ├── GitManager.ts
│       ├── SystemManager.ts
│       ├── SQLManager.ts
│       └── WebManager.ts
├── config/
│   └── map.yml                # Command registry
└── tests/
    ├── setup.ts               # Mock context factory
    └── test-runner.ts         # Smoke test runner

Testing

Unit tests

npm test              # Run all tests
npm run test:watch    # Watch mode
npm run test:coverage # Coverage report
npm run test:ui       # Interactive Vitest UI

Smoke tests

Validates that every registered command loads correctly, exports a default function, and can be instantiated without errors:

npm run test:smoke

Writing tests

Use createMockContext() from tests/setup.ts to get a fully mocked TyrContext:

import { createMockContext } from '../tests/setup';
import myCommand from '../src/commands/my-command.tyr';

test('my command runs', async () => {
    const ctx = createMockContext();
    const handler = myCommand(ctx);
    await handler(['arg1']);
    expect(ctx.logger.success).toHaveBeenCalled();
});

Dependencies

| Package | Purpose | |---|---| | chalk | Terminal colors | | execa | Shell command execution | | axios | HTTP requests | | inquirer | Interactive prompts | | js-yaml | YAML config parsing | | mssql | MSSQL database driver | | mongodb | MongoDB driver | | cheerio | HTML parsing / web scraping | | dotenv | Environment variable loading | | tsx | TypeScript execution |


NPM & Community

Tyr is published on npm as @orxataguy/tyr.

The project follows a hybrid open community model — the main repository is open, and contributors are encouraged to publish their own forks under their own npm scope. You do not need permission from the maintainer to fork, improve, or publish your own version.

Publishing your own distribution

  1. Fork this repository
  2. Make your changes
  3. Update the name field in package.json to your own npm scope:
    "name": "@yourname/tyr"
  4. Add your NPM_TOKEN as a secret in your forked repo settings, then push a tag like v1.0.0 — the release workflow will handle the rest automatically
  5. Users can then install your version with:
    npm i @yourname/tyr

If you want your fork listed as a community distribution, open a PR adding it to COMMUNITY.md.


License

MIT — Manel Andreu Pérez