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

@infinityloop.labs/ai-cli

v0.4.20

Published

Template TypeScript CLI library compiled for Node.js

Downloads

3,976

Readme

ILL CLI (@infinityloop.labs/ai-cli)

Config-driven CLI runner for template/bootstrap and sync workflows.

What Was Done

  • Moved CLI implementation from legacy code/ layout to root src/ layout.
  • Switched build setup to rollup.config.mjs + TypeScript declarations output in dist/.
  • Added executable CLI entrypoint (dist/cli.js) with aliases: ill, aic, infinity-cli.
  • Kept plugin-based runtime and covered key paths with tests.

Install

As a package dependency:

npm install @infinityloop.labs/ai-cli

Alternative package managers:

yarn add @infinityloop.labs/ai-cli
pnpm add @infinityloop.labs/ai-cli

Global install (optional):

npm install -g @infinityloop.labs/ai-cli

CLI Commands

Show help:

ill --help

Initialize config in current folder:

ill init --repo owner/template-repo --target-repo owner/product-repo --ref main

Sync with template repository using configured command:

ill sync

Run any configured command key:

ill <commandKey> --name MyFeature

Run command keys declared in infinityloop.config.*:

ill addWidget Header
ill addService Auth
ill addOpenApiConfig Billing
ill removeWidget Header
ill removeService Auth
ill removeOpenApiConfig Billing

Extended form:

ill <commandKey> --name MyFeature --config ./infinityloop.config.js --cwd .

Supported command aliases:

  • ill
  • aic
  • infinity-cli

NPM Scripts

  • npm run build - clean, bundle, generate declaration files, set execute bit on CLI output.
  • npm run clean - remove dist/.
  • npm run test - run Node test suite (src/**/*.test.ts).
  • npm run typecheck - TypeScript check without emit.
  • npm run watch - TypeScript watch mode.
  • npm run start - build and run CLI from dist/cli.js.

Config

CLI auto-detects one of:

  • infinityloop.config.js
  • infinityloop.config.mjs
  • infinityloop.config.cjs

commands is a map where each key is a command and value is an array of steps.

module.exports = {
  commands: {
    createWidget: [
      {
        type: "add",
        from: "_templates/react_template/_template/widget",
        to: "generated/widgets/$name",
        replace: [{ Sample: "$name" }, { sample: "$name" }],
      },
    ],
    removeWidget: [
      {
        type: "remove",
        target: "generated/widgets/$name",
      },
    ],
  },
};

Step Types

  • add: copy file/folder from from to to with optional replace.
  • copy: copy file/folder from from to to without substitutions.
  • download: clone template repository and copy into cwd without .git and .github. .gitignore is preserved. Works in non-empty folders by default; set allowNonEmpty: false to require empty target.
  • merge-template: подтягивает снапшот шаблона, строит 3-way patch и накладывает его поверх текущей рабочей копии. По умолчанию CLI предложит выбрать удаляемые файлы в интерактивном режиме. Если удалений быть не должно вовсе, установите allowDeletes: false. Массив protectedPaths (пути относительно корня проекта) позволяет заблокировать удаление конкретных директорий/файлов даже при включённых удалениях.
  • insert: insert line after placeholder in file.
  • replace: replace the first occurrence of search with replace in file.
  • rename: replace tokens in file contents and file/directory names inside target with case preservation (Sample / sample / SAMPLE).
  • remove-line: remove a line from file by text match.
  • remove: delete file/folder at target.
  • read: load variables from a key=value file (for example .cli) and inject them into the command context so subsequent steps can use ${PROJECT_NAME} placeholders.

Template values & variables

  • Fields such as file, placeholder, line, search, and replace accept either a string with $variable / ${variable} placeholders or a function (variables) => string.
  • Available variables:
    • name, namePascal, nameCamel, nameLower, nameSnake, nameKebab, nameScreamingSnake
  • Any extra CLI flag becomes a variable: --store-name=SideMenu exposes ${storeName}, --dry-run sets ${dryRun} to "true", and disabling flags like --no-store / --nostore set ${store} to "false" while ${noStore} becomes "true". Flag names are normalized to camelCase by stripping dashes/underscores, but you can still reference hyphenated names in when expressions (e.g. when: "!no-store").
  • The read step is typically used to load a .cli file with entries like PROJECT_NAME=my-app. Each KEY=VALUE pair becomes available via ${KEY} or ${key} in later steps.
  • For ${variable} syntax, the placeholder casing controls the transform: ${name} lowers the first letter, ${Name} capitalizes it, ${NAME} uppercases the whole string. Plain $variable keeps the stored value.
  • Example:
{
  type: "insert",
  file: "app/features/services/$name/hooks.ts",
  placeholder: "// Services: Start",
  line: "  $nameLower: createAction(${name}Actions),",
}

Conditional execution

  • Every step may declare when, either as a string ("store", "!store") or an array of such strings. All conditions must be truthy for the step to run.
  • Truthiness is based on the variable value: missing/"false"/"0"/empty strings are treated as false, everything else is true. Prefix ! to invert the result.
  • Example: skip store-related insertions when --no-store is provided.
{
  type: "insert",
  when: "!no-store", // executes only when --no-store/--nostore is not provided
  file: "app/store/index.ts",
  placeholder: "// Services: Start",
  line: "  ${name}: ${Name}Reducer,",
}

// merge-template example that blocks deletions but still fetches updates
{
  type: "merge-template",
  repo: TEMPLATE_REPO,
  ref: TEMPLATE_REF,
  allowDeletes: false,
  protectedPaths: [".cli", "app/business"],
}