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 🙏

© 2025 – Pkg Stats / Ryan Hefner

tag-cli

v0.3.0

Published

Tag build generator

Downloads

10

Readme

STATUS: Tag is in initial development. Don't use it yet - you won't have a fun time when things change.

Tag is a task runner/build script generator that employs a very basic DSL in order to specify job dependencies with potentially complex build configurations (variants).

Tag is most similar to GNU Make, and consists of just a few primitives:

  • Rules - map inputs to targets (outputs)
  • Tasks - pseudo-commands to build a pre-determined set of targets (similar to .PHONY rules in GNU Make)
  • Commands - run via the shell on the host system (e.g. /bin/bash on unix, cmd.exe on windows, and so on)
  • Tags - boolean flags that enable or disable rules/commands/tasks (hence the project name)

... just a few philosophies ...

  • Build contexts - similar to Docker contexts, Tag forces out-of-source builds by using a root directory as a "context" for which files can be referenced. This allows Tag to run builds in a variety of ways.
  • Strict variables - unlike other build tools, Tag enforces the presence of variables when they're used. This is similar to set -u in shell script.
  • Unopinionated - Tag doesn't make any assumptions about what you're trying to run. It simply runs it in various ways. Use tag as a build system, tag runner, scripting language, etc.

Installation

Install Tag by running one of the following commands:

$ yarn global add tag-cli
$ npm i -g tag-cli

Usage

$ tag --help

 tag - yet another task runner

 $ tag -v [task ...] [@tag ...] [NAME=[value] ...]
 $ tag --help

 OPTIONS
   --help                    shows this help message
   --version, -V             shows the version string
   --verbose, -v             verbose output

   --tagfile, -F filename    the filename to read as the Tagfile
                             (defaults to './Tagfile')

   @tag_name                 enables a tag by name
                             (can be specified multiple times)

   NAME=[value]              sets a variable
                             (can be specified multiple times)

For example, to run Tag using the working directory's Tagfile with the all task (the default), simply run

$ tag

To enable the foo tag:

$ tag @foo

To set the variable FOO to Bar:

$ tag FOO=Bar

To run clean and then all (a full rebuild):

$ tag clean all

And finally, you may combine all of these together:

$ tag clean all @foo @bar SOME_VAR='Some value'

Why?

Because writing cross-platform scripts with various configurations is annoying. Further, I needed a jumping off point for a tool that can run various scripts on multiple platforms/environments, with the ability to create specific edge-case variants of commands in very specific situations.

Non-goals

There are some things Tag doesn't care too much about:

  • Configuration speed - reconfiguration doesn't happen often (at least, not as often as builds), so Tag takes the liberty to perform some potentially hefty filesystem operations in order to add a few more features while keeping this a bit more deterministic and 'correct'.
  • Build system primitives - Tag won't come bundled with any add_shared_c++_library()-type functions. It aims to be more like GNU Make and less like CMake.

Basics

# This is a comment. They can appear anywhere (even alongside Tag code),
# starting with a `#' and continuing until a newline (`\n').

# Set variable values by using the `SET' builtin.
# Values are consumed until the end of the line.
# Quotes have no special meaning and are considered literals.
#
# Although not strictly enforced by Tag, it is convention
# to name variables with ALL_CAPS to differentiate between variables
# and tags.
#
# Note that once an identifier has been used in a tag or a variable,
# it cannot be re-used as another type (Tag will error). This is another
# reason for the above convention.
SET FOO=bar

# You can reference variables anywhere in Tag code by
# wrapping the variable in curly braces (`{}')
SET FOO={FOO} bar2  # FOO now equates to "bar bar2"

# Use tag's built-in preset called "os", which
# provides the @win32, @macos, @linux, etc. tags.
USE os

# `TAGPATH' is used to resolve the argument to `USE'.
#
# Note that its path separator is always a colon (`:'),
# regardless of `PATHSEP'.
#
# Here is the default `TAGPATH' value.
#
# By default, all environment variables are included as variables.
SET TAGPATH=./%.tag:./node_modules/tag-preset-%/index.tag:./node_modules/%/index.tag

# `PATHSEP` is used to delimit multi-element strings in variables.
# If you `USE os', `PATHSEP' is set for you.
#
# (If you're curious about the `@' and `!', keep reading.)
@win32 SET PATHSEP=;
!win32 SET PATHSEP=:

# Tags are boolean (1 or 0) values that can be turned on or off.
# Turning on/off a tag that is already respectively enabled/disabled
# has no effect.
#
# As a convention (though not enforced), tags should be lower case
# in order to differentiate between tags and variables.
ON foo
OFF foo

# Tags can then be used to enable/disable statements. Yes, any statement.
@foo ECHO Foo is enabled!
!foo ECHO Foo is disabled!

# The `ECHO' builtin prints out information about whatever is running.
ECHO Hello from Tag!
@win32 ECHO You're running on Windows.
!win32 ECHO You're not running on Windows.

# Remember the variable substitution syntax above (`{VAR}')? It's more than
# just substitution.
#
# By prefixing substitutions, you can conditionally ignore/include the
# whole substitution.
ECHO You are {!win32 NOT }running on windows.

# Note that an empty substitution emits nothing.
ECHO {} # echoes nothing.

# If a variable is used in place of a tag prefix, the "boolean" is whether or
# not the variable exists.
@SOMETHING echo Something is {SOMETHING}  # not echoed.
SET SOMETHING=Hello
@SOMETHING echo Something is {SOMETHING}  # echoes

# This can, of course, be used in a substitution as well.
ECHO C flags that are set: {@CFLAGS {CFLAGS}}

# Substitutions have a little syntactic sugar to help in the cases
# where a variable doesn't _have_ to exist via the use of the question
# mark (`?') operator.
#
# It's worth mentioning that the question mark operator is available ONLY
# inside of substitutions - nowhere else.
#
# The following two lines are semantically identical.
ECHO Foobar is: {@FOOBAR {FOOBAR}}
ECHO Foobar is: {?FOOBAR}

# This means Tag is strict about unknown variables and will error if
# it encounters a variable that has not been seen before if used
# in a substitution.
#
# Assuming the variable `FIZZBUZZ' does not exist, the following line
# will cause Tag to fatally exit with an error.
ECHO {FIZZBUZZ}   # causes fatal error (FIZZBUZZ is not a tag or a variable)
ECHO {?FIZZBUZZ}  # echoes an empty line

# TODO `RUN'
# TODO `CALL'
# TODO `IN'
# TODO `DEF`
# TODO `TASK`
# TODO `MAIN`

As a bonus, here's some ~~absurd~~ advanced stuff you can do with the Tag language.

# Double substitution works like you'd expect.
SET FOO=BAR
SET BAR=baz
ECHO {{FOO}} # echos "baz"

# If, for whatever reason, you want to localize something, this is one
# way you could do it.
SET LANG=en_US
ON foo

ON {LANG}
@en_US SET ON_TXT=is enabled
@en_US SET OFF_TXT=is disabled
@de_DE SET ON_TXT=ist aktiviert
@de_DE SET OFF_TXT=ist nicht aktiviert

ECHO foo {{@foo ON_TXT}{!foo OFF_TXT}}

# Some alternative ways to write the above line:
ECHO foo {@foo {ON_TXT}}{!foo {OFF_TXT}}
ECHO foo {{@foo ON}{!foo OFF}_TXT}
@foo ECHO foo {ON_TXT}
!foo ECHO foo {OFF_TXT}

# Force Tag to exit with a fatal error if a tag is enabled
# (though this is a strange and not-so-recommended way of doing this)
@throw_if_on SET _={DOESNOTEXIST}  # assumes `DOESNOTEXIST' really doesn't exist ;)

Built-in Tasks

Tag currently provides one built-in task: all. Note that built-in tasks can be overridden.

The all task evaluates all rules and builds up a graph of all applicable files, building each one. While this is probably suitable for small projects, larger projects will want to override the entry point using the MAIN keyword.

Examples

C/C++ compilation

# specify @fast for fast code
# specify @small for small code
# specify @debug for debug symbols to be generated

USE os # @win32, @linux, @macos, etc.

@win32 !mingw SET OBJ=obj
!OBJ SET OBJ=o

OFF lang_c
OFF lang_c++
OFF linker
IN PATH gcc on lang_c linker gcc
IN PATH g++ on lang_c++ linker g++
IN PATH clang on lang_c linker clang
IN PATH clang++ on lang_c++ linker clang++
IN PATH ld on linker ld
@win32 IN PATH cl.exe on lang_c lang_c++ msvc
@win32 IN PATH link.exe on msvc linker

!lang_c ERROR no C toolchain was detected
!lang_c++ ERROR no C++ toolchain was detected
!linker ERROR no linker was detected

@lang_c++ DEF bin/$1.{OBJ} : src/(.+)\.c(c|pp)
	@msvc RUN cl.exe /c /OUT:{OUT} {IN} {@fast /O2 /Ox} {@small /O1 /Ox} {@debug /Od}
	# TODO @clang
	# TODO @gcc

@lang_c DEF bin/$1.{OBJ} : src/(.+)\.c
	@msvc RUN cl.exe /c /OUT:{OUT} {IN} {@fast /O2 /Ox} {@small /O1 /Ox} {@debug /Od}
	# TODO @clang
	# TODO @gcc

@linker DEF bin/$1 {@msvc @debug OUT_PDB=bin/$1.pdb} : bin/(.+)\.{OBJ}
	@msvc RUN link.exe {@debug /DEBUG /PDB:{OUT_PDB} /OUT:{OUT}} {IN}
	# TODO @clang
	# TODO @gcc