Modules#

An overview of the packages that make up nur. The API reference below is generated automatically from the source docstrings.

CLI (nur.cli)#

Typer command-line interface: discovers project tasks and either runs one directly or launches the TUI.

nur.cli.format_list(registry)[source]#

Render the discovered tasks grouped by provider prefix.

Parameters:

registry (Registry)

Return type:

str

nur.cli.main(argv=None)[source]#

Entry point: parse args with Typer, returning an int instead of exiting.

Typer/Click raise SystemExit for help, version, and every command exit; catching it here keeps main’s int contract so it stays usable from tests and embedders. Passthrough args are handed to the command via ctx.obj.

Parameters:

argv (list[str] | None)

Return type:

int

nur.cli.split_passthrough(argv)[source]#

Split argv on the first -- into task args and passthrough args.

Parameters:

argv (list[str])

Return type:

tuple[list[str], list[str]]

Discovery (nur.core.discovery)#

Walks the working directory and builds the task registry from every supported source file.

Registry (nur.core.registry)#

Holds discovered tasks and resolves a query to a single task, with ambiguity and close-match handling.

exception nur.core.registry.AmbiguousTaskError(name, candidates)[source]#

Bases: ResolutionError

Parameters:
Return type:

None

exception nur.core.registry.ResolutionError[source]#

Bases: Exception

Base class for name-resolution failures.

exception nur.core.registry.UnknownTaskError(query, suggestions)[source]#

Bases: ResolutionError

Parameters:
Return type:

None

Execution (nur.core.execution)#

Runs a resolved task’s command, propagating its exit code.

class nur.core.execution.ProcessRunner[source]#

Bases: object

Runs a command with combined output captured and streamed line-by-line.

Blocking; intended to be driven from a background thread by the TUI.

nur.core.execution.run_direct(task, extra_args, cwd)[source]#

Run a task with inherited stdio; return the child’s exit code.

A natively-parsed provider (npm/PDM/poe) can surface a task whose runner binary is not installed. Rather than letting FileNotFoundError escape as a traceback, report a controlled error and return 127.

Parameters:
Return type:

int

Models (nur.core.models)#

Core data types shared across discovery, the registry, and execution.

class nur.core.models.Provider(*args, **kwargs)[source]#

Bases: Protocol

class nur.core.models.Task(name: 'str', prefix: 'str', argv_base: 'tuple[str, ...]', description: 'str | None' = None, definition: 'str' = '', source_file: 'str' = '', passthrough_prefix: 'tuple[str, ...]' = ())[source]#

Bases: object

Parameters:

Providers (nur.core.providers)#

One module per supported task source (make, npm, deno, composer, just, taskfile, pdm, poe, mise, cargo-make, moon, xc).

nur.core.providers.make.parse_targets(text)[source]#

Extract target names from Makefile text without executing anything.

Deliberately does NOT shell out to make: the database dump (make -pRrq) still evaluates $(shell ...) / != assignments while reading the file, so a repository’s Makefile could run arbitrary commands merely by discovering/listing tasks. Text parsing is safe, at the cost of not resolving include directives or computed targets.

Parameters:

text (str)

Return type:

list[str]

nur.core.providers.just.parse_justfile(text, source_file='justfile')[source]#

Extract recipes from justfile text without executing anything.

Deliberately does NOT shell out to just --dump: a pure text parse needs no just binary on PATH and cannot run recipe bodies. Descriptions come from the comment immediately preceding a recipe (skipping any attribute lines) or from an explicit [doc('...')] attribute. Grammar fidelity is intentionally partial: imports, string interpolation, and computed names are not resolved (see docs/adr/0001).

Parameters:
  • text (str)

  • source_file (str)

Return type:

list[Task]

nur.core.providers.task.parse_taskfile(text, source_file='Taskfile.yml')[source]#

Parse a Taskfile’s YAML text without executing anything.

Deliberately does NOT run task --list: go-task evaluates dynamic sh: variables while loading/compiling the file, so listing could run repository-controlled commands during discovery. Reading the YAML directly is safe, at the cost of not resolving includes: or generated tasks.

Parameters:
  • text (str)

  • source_file (str)

Return type:

list[Task]

nur.core.providers.moon.parse_moon(text, source_file='moon.yml')[source]#

Parse a moon project’s moon.yml text without executing anything.

Deliberately does NOT run moon query tasks: enumerating tasks that way boots moon’s toolchain and resolves inherited config, which can run repository-controlled commands during discovery. Reading the YAML directly is safe, at the cost of not resolving inherited tasks from .moon/ or project-qualified <project>:<task> addressing across the monorepo.

Parameters:
  • text (str)

  • source_file (str)

Return type:

list[Task]

nur.core.providers.xc.parse_xc(text, source_file='README.md')[source]#

Parse xc tasks out of a markdown text without executing anything.

Deliberately does NOT run xc -s: xc executes task scripts, and listing should never be able to run repository-controlled commands. The grammar is documented at https://xcfile.dev/task-syntax/task-list/.

Parameters:
  • text (str)

  • source_file (str)

Return type:

list[Task]

TUI (nur.tui)#

Textual terminal user interface for browsing and running tasks.

class nur.tui.app.HeaderItem(prefix)[source]#

Bases: ListItem

Initialize a Widget.

Parameters:
  • *children – Child widgets.

  • name – The name of the widget.

  • id – The ID of the widget in the DOM.

  • classes – The CSS classes for the widget.

  • disabled – Whether the widget is disabled or not.

  • markup – Enable content markup?

  • prefix (str)

can_focus = False#

Widget may receive focus.

can_focus_children = True#

Widget’s children may receive focus.

class nur.tui.app.NurApp(cwd, scan)[source]#

Bases: App[None]

Create an instance of an app.

Parameters:
  • driver_class – Driver class or None to auto-detect. This will be used by some Textual tools.

  • css_path – Path to CSS or None to use the CSS_PATH class variable. To load multiple CSS files, pass a list of strings or paths which will be loaded in order.

  • watch_css – Reload CSS if the files changed. This is set automatically if you are using textual run with the dev switch.

  • ansi_color – Allow ANSI colors if True, or convert ANSI colors to RGB if False, None to use “ansi” parameter from themes.

  • cwd (Path)

  • scan (Callable[[], Registry])

Raises:

CssPathError – When the supplied CSS path(s) are an unexpected type.

CSS_PATH = 'app.tcss'#

File paths to load CSS from.

BINDINGS = [('q', 'quit', 'quit'), ('escape', 'quit', 'quit'), ('slash', 'focus_filter', 'filter'), ('j', 'next', 'down'), ('k', 'prev', 'up'), ('r', 'run', 'run'), Binding(key='ctrl+c', action='interrupt', description='interrupt', show=True, key_display=None, priority=True, tooltip='', id=None, system=False, group=None), ('question_mark', 'toggle_help', 'help')]#

The default key bindings.

compose()[source]#

Yield child widgets for a container.

This method should be implemented in a subclass.

Return type:

Iterable[Widget]

async action_quit()[source]#

An [action](/guide/actions) to quit the app as soon as possible.

Return type:

None

class nur.tui.app.TaskItem(task)[source]#

Bases: ListItem

Initialize a Widget.

Parameters:
  • *children – Child widgets.

  • name – The name of the widget.

  • id – The ID of the widget in the DOM.

  • classes – The CSS classes for the widget.

  • disabled – Whether the widget is disabled or not.

  • markup – Enable content markup?

  • task (Task)

can_focus = False#

Widget may receive focus.

can_focus_children = True#

Widget’s children may receive focus.