Reference

Everything noodge.yaml understands, and everything the CLI does. If you are here to get it running, the install section is shorter.

Getting started

Install noodge, then run noodge init in a project. That writes a starter noodge.yaml with two working commands so you can check everything before you write anything of your own.

$ noodge init
created ~/dev/my-project/noodge.yaml
run 'noodge' to see what it declares

The two fields that matter most are description and output. They are the point of the whole thing — what the browser shows you when you are trying to remember which command to run. Write them for whoever joins next month.

Discovery

noodge walks up from your working directory to the nearest noodge.yaml, the same way git finds .git, and stops at a repository boundary. Commands run in the directory holding the config, not wherever you happened to be standing, so noodge build means the same thing from any subdirectory.

Configuration is discovered, not configured. There is no global config file and nothing to register. Two flags override the search when you need them to:

  • -C, --directory <dir> — start looking in this directory instead of the current one.
  • --file <path> — load this exact config file and skip discovery entirely.

The NOODGE_CONFIG environment variable does the same job as --file.

The noodge.yaml

One file at the root of your project. The modeline on the first line points your editor at the JSON Schema, which gives you completion and inline errors as you type.

# yaml-language-server: $schema=https://wimhaanstra.github.io/noodge/schema/v1/noodge.schema.json
version: 1
name: my-api

commands:
  start:
    description: |
      Starts the API server against the shared development database.

      Day-to-day command. Hot-reloads on save. Nothing is written to disk,
      so it is safe to kill at any time.
    steps:
      - node myscript.ts
    output: |
      Streams the server log to stdout. Listens on http://localhost:3000.

Top-level fields

FieldWhat it does
versionSchema version. Always 1 today.
nameThe project name, shown at the top of the browser and of noodge list.
shellThe shell used to run steps, when you need one other than the default.
envEnvironment variables added to every command in the file.
groupsTitles and descriptions for the command families. See Groups.
commandsThe commands themselves, keyed by name.

Command fields

FieldWhat it does
descriptionWhat this command is for. Shown in the browser, in --help, in noodge list and in tab completion.
stepsWhat it runs. See Steps.
outputWhat it produces — so someone can decide whether to run it without running it.
paramsDeclared parameters. See Parameters.
envEnvironment variables for this command only.
cwdRun in this directory instead of the one holding the config.
aliasesOther names this command answers to.
hiddenKeep it out of the browser and the lists. It still runs when named.
confirmAsk before running. See Confirm.
shellOverride the shell for this command.

Parameters

Declare a parameter and noodge builds the flag, documents it in --help, validates what you pass, and expands it into the step. Every refusal happens before any process starts.

stringintnumber boolpathenum
commands:
  serve:
    description: Runs the server.
    params:
      - name: host
        flag: --host
        type: string
        default: localhost
        pattern: '^[a-z0-9.-]+$'
        description: Hostname to bind to.
      - name: port
        flag: --port
        type: int
        default: 8080
        description: Port to listen on.
      - name: timeout
        flag: --timeout
        type: number
        default: 2.5
        description: Request timeout in seconds.
      - name: verbose
        flag: --verbose
        short: -v
        type: bool
        description: Log every request.
      - name: config
        flag: --config
        type: path
        required: true
        description: Path to the config file.
      - name: env
        flag: --env
        type: enum
        values: [dev, staging, prod]
        default: dev
        description: Which environment to run against.
    steps:
      - node server.js {{flag host}} {{flag port}} {{flag config}} {{flag env}}
FieldWhat it does
nameHow you refer to it in a step, as {{name}} or {{flag name}}.
flagHow you type it. Must start with two dashes.
shortA single-dash alias, such as -c.
typeOne of the six above.
descriptionThe line that appears in --help and in the browser's form.
requiredRefuse to run without it.
defaultThe value used when you do not pass one.
valuesThe allowed values, for enum.
patternA regular expression the value must match.

Parameter values are always quoted. Every value is shell-quoted on the way out, so noodge deploy --host 'a && shutdown /s' reaches the wrapped tool as one literal argument. It is data, and it stays data.

Placeholders

A step refers to its parameters with placeholders. {{flag name}} writes the flag and its value together, and disappears entirely when the parameter is unset — so no empty flag is ever left behind. {{name}} writes the bare value.

PlaceholderWhen the parameter isExpands to
{{flag host}}set, or defaulted--host localhost
{{flag host}}optional and unsetnothing at all
{{flag verbose}}a bool, and true--verbose
{{flag verbose}}a bool, and falsenothing at all
{{host}}setlocalhost
{{args}}whatever you typed after --

Anything after -- is appended to the last step, so noodge test -- -run TestDiscover -v works without editing the file. Use {{args}} when you need them somewhere other than the end.

A parameter that no step uses, and a placeholder with no matching parameter, are both errors. noodge validate catches them with a line number.

Steps

Steps run in order, and each one is its own process — which matters on Windows, where PowerShell 5.1 has no && at all. A step is a string, an array of arguments when you want no shell parsing at all, or a parallel: group.

steps:
  - npm run build
  - ["npm", "pack", "--pack-destination", "./dist"]
  - parallel:
      api: noodge api
      worker: noodge worker
      web: npm run dev

Everything in a parallel group starts at the same time, and every line of output is labelled with the key that produced it.

api    | listening on :3000
worker | polling for jobs
web    | vite ready in 412 ms

Everything a group starts goes into one process tree, so stopping it also stops what those processes started. On Windows, which has no process groups, killing npm normally leaves node holding the port — noodge uses a Job Object with kill-on-close, so the whole tree goes.

If any member of a group fails, the group fails.

Confirm

Set confirm: true for the default prompt, or give it a string to write your own.

  db:reset:
    description: Drops and recreates the local database.
    confirm: true
    steps:
      - ./scripts/reset-db.sh

  deploy:prod:
    description: Deploys to production.
    confirm: This deploys to PRODUCTION. Continue?
    steps:
      - ./scripts/deploy.sh --env prod
$ noodge db:reset
Really run "db:reset"? [y/N] n
$ echo $?
2

Declining exits 2, so a script that says no fails rather than carrying on quietly. Pass --yes to answer every prompt with yes, for CI and scripts.

Groups

A command belongs to the family named by the part of its name before the first colon, so dev:api and dev:worker are both in the dev family. Families appear in the browser either way, headed by the bare prefix. Declaring one here adds a readable title and a line of explanation.

groups:
  - prefix: dev
    title: Running it
    description: The stack you work against day to day.
  - prefix: db
    title: Database
    description: The local Postgres the API develops against.
my-api  ~/dev/my-api/noodge.yaml

  Running it            Database
    dev                
    dev:api             The local Postgres the API develops against.
> Database            
    db:reset            2 commands in this group.
    db:stop            

Environment

Set variables for the whole file with a top-level env:, or for one command with its own. noodge also injects two of its own into every run, so a script can tell how it was invoked.

InjectedValue
NOODGE_COMMANDThe name of the command being run.
NOODGE_PARAM_<NAME>One per declared parameter, uppercased.
start:local would run in ~/dev/my-api:
  1. node serve.ts --host "localhost" --certificate "dev.pfx" --verbose

with environment:
  NODE_ENV=local
  NOODGE_COMMAND=start:local
  NOODGE_PARAM_CERTIFICATE=dev.pfx
  NOODGE_PARAM_HOST=localhost
  NOODGE_PARAM_VERBOSE=true

Variables noodge reads

VariableWhat it does
NOODGE_CONFIGLoad this config file instead of discovering one.
NOODGE_THEMElight or dark, when the terminal's own is detected wrongly.
NOODGE_NO_UPDATE_CHECKSet to 1 to make noodge do no network requests at all.
NOODGE_UPDATE_FEEDPoint the update check somewhere else.
NOODGE_VERSIONInstallers only: the version to install. Defaults to the latest release.
NOODGE_INSTALL_DIRInstallers only: where to put the binary.
NOODGE_NO_PATHInstallers only, Windows: do not touch PATH.

CLI commands

CommandWhat it does
noodgeOpen the browser, or list when there is no terminal.
noodge <command>Run a command from noodge.yaml.
noodge run <command>The same, for when the name collides with one below.
noodge list [--json]List commands, optionally machine-readable.
noodge validateCheck the config and report problems with line numbers.
noodge initWrite a starter noodge.yaml.
noodge completion <shell>Print the completion script.
noodge completion install <shell>Set completion up for you.
noodge schemaPrint the JSON Schema.
noodge upgradeInstall the latest version.
noodge versionPrint the version.

Global flags

  -C, --directory string   start looking for noodge.yaml in this directory
                           instead of the current one
      --dry-run            print the exact command lines that would run,
                           and run nothing
      --file string         load this exact config file instead of
                           discovering a noodge.yaml
  -h, --help               help for noodge
      --yes                answer any confirmation prompt with yes,
                           for CI and scripts

noodge upgrade also takes --check, which reports whether an upgrade is available and changes nothing, and --force, which upgrades even when a package manager installed this copy. noodge completion install takes --print-only and -y, --yes.

Exit codes

A step's exit code passes through untouched. noodge never invents one on a command's behalf, so anything wrapping noodge sees what it would have seen wrapping the tool directly.

CodeMeans
0Everything succeeded.
anything a step returnsPassed straight through.
2noodge itself refused: a bad config, a missing required flag, a value that does not validate, or a declined confirmation. Every one of these happens before any process starts.
10noodge upgrade --check found an upgrade available.
noodge: required flag "--certificate" is not set
noodge: --certificate: dev.pfx does not exist
noodge: unknown command "nosuchcommand" for "noodge"

Tab completion

Completion is per-directory: it offers the commands this project declares, with their descriptions, and never another project's. noodge will set it up for you.

$ noodge completion install zsh

Supported targets are bash, zsh, fish, pwsh and windows-powershell. Pass --print-only to see what it would change and write nothing.

Editor support

The JSON Schema is generated from the doc comments in the source, published with every release, and shipped inside the binary. noodge init writes the modeline for you; add it to an existing file and your editor will do the rest.

# yaml-language-server: $schema=https://wimhaanstra.github.io/noodge/schema/v1/noodge.schema.json

Offline, or behind a proxy, noodge schema prints the same document to stdout.

Updating

$ noodge upgrade

noodge checks for a new version in the background and mentions it on stderr when there is one. NOODGE_NO_UPDATE_CHECK=1 switches that off, and then noodge makes no network requests at all.

noodge 0.3.0 is available (you have 0.2.3). Run 'noodge upgrade'.

If a package manager installed this copy, upgrading in place would leave that package manager believing the old version is still installed, and its next update would put it back. noodge refuses, and tells you the right command instead.

noodge: this noodge was installed by Scoop, which keeps its own record of the
installed version. Upgrading in place would leave Scoop believing the old
version is still installed, and its next update would put it back.

  scoop update noodge