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

@atindo23/tamo

v0.3.0

Published

`tamo` remembers reusable project setup so you do not have to rebuild or re-explain the same setup every time.

Readme

tamo

tamo remembers reusable project setup so you do not have to rebuild or re-explain the same setup every time.

It helps set up ordinary projects without taking ownership of them. Native project files stay authoritative, and the project does not depend on tamo afterward.

Install

CLI

npm install -g @atindo23/tamo
tamo --help

Agent skill

The coding-agent skill teaches compatible agents how to discover, save, and reuse Recipes with tamo.

npx skills add athif23/tamo --skill tamo      # project-level
npx skills add athif23/tamo --skill tamo -g   # global

Installing the skill does not install the CLI itself.

Quick start

With an agent

Once the skill is installed, you can describe what you want without naming a Recipe first:

create a web app using TanStack Start, TypeScript, Tailwind, and shadcn

The agent can discover matching saved Recipes before rebuilding the same setup.

When you want to keep a setup for later:

i like this setup, save it with tamo

The agent can curate the reusable parts into a Recipe while leaving the source project untouched.

Create from a Recipe

tamo create my-app --recipe web --dry-run

Review the plan, then apply it:

tamo create my-app --recipe web --yes

Save reusable setup

tamo pack web --cwd ./my-project \
  --include tsconfig.json \
  --include src/styles.css \
  --dry-run

Then save it:

tamo pack web --cwd ./my-project \
  --include tsconfig.json \
  --include src/styles.css \
  --yes

Add setup to an existing project

tamo add lint --cwd ./my-project --dry-run

Inspect a project

tamo inspect --cwd ./my-project

inspect walks nested directories too, so a repository containing several apps or services reports the setup artifacts at their own paths — apps/web/vite.config.ts, apps/desktop/Cargo.toml, services/api/pyproject.toml — without classifying the repository as any particular kind of project.

Every mutating command supports --dry-run, so you can review what tamo plans to do before anything changes.

Why tamo

Project setup is repetitive. The same framework choices, TypeScript settings, lint rules, UI setup, test tooling, and directory conventions often get rebuilt or re-explained from project to project.

tamo lets those decisions live as reusable Recipes.

The key idea is:

Reusable setup without tool ownership.

A Recipe can be used to create a new project or reconciled into an existing one. The result stays an ordinary project with ordinary native files.

Templates

Templates and starter repos are useful when you want to copy a known starting point.

template
  ↓ copy / render
new project

A Recipe is different. It represents reusable setup that can be planned against the project that already exists.

Recipe
  ↓ plan + reconcile
new or existing project

Recipes can also compose. Where tamo understands the artifact type, compatible contributions combine and incompatible intent blocks instead of silently picking a winner.

A template is still the simpler choice when a fixed copied starting point is exactly what you want.

Projen

Projen-style generators keep a generator definition as the source of truth and generate project files from it.

generator definition
        ↓
generated project files

tamo deliberately keeps the native project files as the source of truth.

native project files
        ↕
   reusable Recipe
        ↓
native project files

tamo applies setup when asked, then gets out of the way. It does not continuously own or regenerate the project afterward.

Use a generator when you want centralized ownership of project configuration. Use tamo when you want reusable setup without handing ownership of the project to the setup tool.

Coding agents are one useful way to drive tamo, but they are not required. The CLI works on its own.

Recipes

A Recipe is reusable setup expressed through ordinary native project files plus a small amount of composition metadata.

Recipes live under the tamo home directory, which defaults to ~/.tamo and can be changed with TAMO_HOME.

~/.tamo/
  recipes/
    web/
      recipe.json
      behavior.mjs        # optional default behavior entrypoint
      artifacts/
        package.json
        tsconfig.json
        ...

Artifacts

artifacts/ contains ordinary native project files. These are the files the underlying tools already understand, such as package.json, tsconfig.json, components.json, Cargo.toml, or any tool-specific config.

The project itself does not get a project-level tamo.json.

recipe.json

recipe.json contains Recipe composition metadata, such as included Recipes, persistent customizations, and an optional Behavior entrypoint.

Example:

{
  "includes": [
    { "recipe": "typescript" },
    { "recipe": "lint" }
  ]
}

A Recipe may also choose a custom relative .mjs Behavior entrypoint:

{
  "behavior": "scripts/setup.mjs"
}

If no explicit path is configured, behavior.mjs is the zero-config default.

Behavior

Behavior is optional trusted local JavaScript for procedural setup that native files alone cannot express, such as running an upstream initializer.

Most Recipes do not need it.

Behavior can participate around artifact application through three hooks:

prepare
  ↓
apply artifacts
  ↓
finalize
  ↓
verify

Behavior is trusted executable code and is not currently sandboxed.

Commands

Run tamo <command> --help for exact flags.

pack

pack saves selected native artifacts from an existing directory as a Recipe.

tamo pack web --cwd ./my-project \
  --include tsconfig.json \
  --include src \
  --dry-run

A root package.json, when present, is captured with package-manifest semantics. Nested manifests selected via --include keep their own name and version.

pack is package-manager agnostic: any valid package.json is packable regardless of the packageManager field or lockfiles present.

A package.json is optional. A directory without one can be packed from --include artifacts alone — pack never synthesizes one — and at least one artifact is required.

The root source name and version are not treated as reusable setup. packageManager is preserved when present and is never invented.

Secrets, private keys, lockfiles, caches, dependency directories, generated output, and symlinked source state are not captured. Naming one directly with --include is blocked rather than quietly capturing nothing.

--include of a directory expands it recursively, and that expansion skips known dependency, generated, cache, and VCS state at any depth (node_modules, dist, build, target, __pycache__, virtualenvs, tool caches, .git, and the rest of the same list). A project that has already been installed and built therefore packs without deleting anything first:

tamo pack web --cwd ./my-project \
  --include apps \
  --include packages \
  --include services

The source project is never modified.

Repacking over an existing Recipe requires --force.

create

create applies a Recipe to a new project.

tamo create my-app --recipe web --dry-run

Review the plan, then apply it, or materialize the files without installing:

tamo create my-app --recipe web --no-install --yes

Native artifacts are written to their normal relative paths. A root package.json takes the new target directory's package name and plans a visible install by default; the manager comes from its packageManager field (pnpm, npm, yarn, or bun; pnpm when the field is absent). Nested manifests keep their own names and never trigger installs, and known workspace membership never triggers installs either. An unmatched nested manifest does not install either, and absence of membership never marks it independent. Tamo runs the root package manager once; that manager determines its own workspace behavior — tamo does not promise the root install covers any specific member. A Recipe with no root package.json creates without any install step. --no-install skips the automatic install while still creating and verifying the files.

Targets that already exist and are non-empty are blocked instead of overwritten.

The resulting project contains no tamo metadata.

add

add reconciles a Recipe with an existing project.

tamo add lint --cwd ./my-project --dry-run

Compatible state is preserved or combined, identical state becomes a no-op, missing state is added, and conflicting intent blocks instead of silently overwriting existing setup.

Rerunning a settled Recipe is idempotent.

inspect

inspect reports setup detected in an existing project and does not modify it.

tamo inspect --cwd ./my-project

It reports root package facts plus a recursive inventory of setup artifacts — each at its project-relative path, with the handler that understands it or whole-file for artifacts carried with conservative whole-file semantics. package.json artifacts use package-manifest composition semantics at any nested path:

tamo inspect --cwd ./my-monorepo
Node project ([email protected]) in C:\my-monorepo
Artifacts:
  apps/desktop/Cargo.toml (whole-file)
  apps/desktop/rustfmt.toml (whole-file)
  apps/web/components.json (whole-file)
  apps/web/package.json (package-manifest)
  apps/web/vite.config.ts (whole-file)
  package.json (package-manifest)
  pnpm-workspace.yaml (whole-file)
  services/api/pyproject.toml (whole-file)
Workspace memberships:
  apps/web/package.json <- pnpm-workspace.yaml

Nested setup is visible without the repository being classified: inspect never reports a project type, ecosystem, or language, and artifacts that cluster under apps/web or services/api stay plain paths. Known workspace membership links a nested manifest to the root declaration that proves it; absence of a fact means no known membership, never independence, and membership alone never triggers installation. Dependency, build, cache, and VCS trees are skipped, links are never followed, and ordinary source files are not listed.

For machine-readable output:

tamo inspect --cwd ./my-monorepo --json

Each artifact is one { path, handler } entry (abridged here):

{
  "inspection": {
    "artifacts": [
      { "path": "apps/web/vite.config.ts", "handler": null },
      { "path": "apps/web/package.json", "handler": "package-manifest" },
      { "path": "package.json", "handler": "package-manifest" }
    ],
    "workspaceMemberships": [
      { "member": "apps/web/package.json", "declaredBy": "pnpm-workspace.yaml" }
    ]
  }
}

A null handler is not missing data: it means Core's conservative whole-file fallback owns that artifact. Anything not listed can still be selected explicitly for pack with --include.

recipe

recipe reads and maintains the Recipes saved under the tamo home. list and inspect are read-only discovery; edit changes what one Recipe stores.

tamo recipe list
tamo recipe list --json

tamo recipe inspect web
tamo recipe inspect web --json

recipe list reports which Recipes exist, sorted by name, with a lightweight artifact count, their includes, and their Behavior entrypoint. A malformed Recipe is reported in place with its error instead of blocking the others.

recipe inspect <name> reports what one Recipe contains: includes, persistent customizations, its Behavior entrypoint, artifact paths, and the handler claiming each path. Paths are listed as stored, so nested artifacts appear as apps/web/components.json. Includes are named, not expanded.

Neither list nor inspect resolves a Recipe against a project, executes Behavior, ranks Recipes, or classifies them by ecosystem.

recipe edit

recipe edit changes the artifacts a saved Recipe stores.

tamo recipe edit web --remove apps/desktop --dry-run
tamo recipe edit web --cwd . --add biome.json --dry-run
tamo recipe edit web --cwd . --replace vite.config.ts --dry-run

--add captures a path from --cwd — a file, or a directory that expands into the files beneath it — and stores it at the same relative path. Adding over a differing artifact is a conflict, not an overwrite. --replace swaps the Recipe's own stored artifact at that path; replacing something the Recipe does not store is a conflict, not an implicit add. --remove deletes one stored artifact, or every stored artifact beneath a path prefix, so removing a whole area is one command. A --remove path that matches nothing is a conflict rather than a silent success.

Capture follows the same rules as pack: secrets, keys, lockfiles, caches, dependency directories, generated output, and symlinks are never captured; a root package.json keeps package-manifest semantics (source name and version stripped, packageManager preserved and never invented) while nested manifests keep their own name and version; and the source project is never modified.

Every change is planned and validated before anything is written, so conflicting or overlapping requests leave the Recipe untouched. The result is re-loaded through the same Recipe loader recipe inspect uses.

Editing a Recipe changes reusable future setup only. Projects previously created from that Recipe are never touched, and an included Recipe is never edited through it.

Artifacts contributed by an included Recipe cannot be edited from the parent: the conflict names the owning Recipe. Includes, persistent customizations, Behavior entrypoints, and an artifact's contents are not editable here.

Safety

behavior.mjs and custom Behavior entrypoints are trusted local executable JavaScript. They run during planning, before confirmation.

Review untrusted Recipes before using them.

Other safety properties:

  • reviewed inputs are fingerprinted and rechecked before execution
  • changed inputs invalidate the reviewed plan
  • conflicts produce zero operations instead of partial writes
  • secrets, keys, lockfiles, generated output, and symlinked source state are never captured
  • mutating commands support --dry-run
  • external commands can still partially change state
  • there is currently no automatic rollback

If execution fails after some operations have completed, tamo reports completed and remaining work so the project can be replanned before retrying.

Limitations

  • tamo can carry arbitrary native artifacts. Rich semantic handling exists for package.json at any nested path and for Oxlint config at the repository root. Other artifacts, including Cargo.toml and pyproject.toml, are carried with conservative whole-file semantics.
  • tamo pack can save selected artifacts from any directory. A root package.json is captured when present but is not required.
  • tamo create plans dependency installation only when the Recipe contributes a root package.json. The manager comes from that manifest's packageManager field (pnpm, npm, yarn, or bun; pnpm when absent), and --no-install skips it. Nested manifests and known workspace membership never trigger installs.
  • tamo inspect discovers setup artifacts recursively and reports known workspace membership as facts only; pack still captures a root package.json plus explicit --include paths. This is not full monorepo support: per-member or filtered installs, scoped whole-subtree packing, automatic whole-repository packing, and nested package rename policies are not implemented. The single root install's workspace behavior is delegated to the package manager, and no install-coverage model is planned. Nested names are preserved, never reconciled.
  • tamo recipe edit adds, replaces, and removes a Recipe's stored artifacts. Editing an artifact's contents, includes, persistent customizations, or Behavior is not implemented.
  • Native integration has primarily been exercised on Windows x64.
  • Behavior is trusted local code and is not sandboxed.
  • There is no automatic rollback after partial execution failures.

Development

Requires Node.js 24.15+ and pnpm.

pnpm install
pnpm check
pnpm format
pnpm test:integration

To run the CLI directly from source:

pnpm install
node src/cli.ts --help

See SPEC.md for the full contract and PARKING_LOT.md for deferred work.

License

MIT. See LICENSE.