DeBasher Tools
Besides the Bash API used to define programs (see the DeBasher API
Section), DeBasher installs a set of standalone command-line tools
that execute, monitor, inspect and manage DeBasher programs. This
section describes each of these tools. Some of them are already
introduced, in context, in the Quickstart Example and
Executing DeBasher Programs Sections; they are described here again for completeness.
Every tool accepts a --help option that prints a summary of its
usage.
Program Execution
debasher_exec
debasher_exec is the main tool used to execute a DeBasher program.
It is described in detail in the Executing DeBasher Programs Section, which covers,
among other topics, its two mandatory options (--pfile <string>,
the module file defining the program to execute, and --outdir
<string>, the output directory), how to select and configure a
scheduler, how to inspect a program’s command line options before
running it, and the structure of the output directory that the tool
generates.
debasher_exec_process
$ debasher_exec_process [-q] <prgfile> <processname> [-- [<process_opts>]]
debasher_exec_process loads the module given by <prgfile> and
executes a single one of its processes, <processname>, directly in
the foreground, bypassing debasher_exec and any scheduler. It is
mainly useful to debug a process implementation in isolation.
If
-- <process_opts>is omitted, the tool does not execute the process. Instead, it prints the process’s option documentation (the same informationdebasher_doc_mod --show-optswould show for it) and exits. The task shaping options of the process are listed apart, since they are not given to the process.If
--is given, everything after it is passed as the process’s own command line options, and the process is executed. The tool then exits with the exit status of the process.-qdrops the progress messages of the tool (such as theLoading module ...lines), so that the standard error holds only what the process and the module write, and the errors.
debasher_test
$ debasher_test [--conda-support] [--docker-support] <prgdir>
debasher_test runs the business tests of a program: tests of what
each process does with the values of its options, run on its own
with debasher_exec_process, outside any run. It applies to a
program in a directory of its own, <prgdir>, of any name. For a
program saved by the web UI, the program file is the script named
after the program in its metadata (.debasher/program.json); for a
program written by hand, it is the only *.sh file at the top of
<prgdir>, and the tool refuses a directory with several. The tests are the
files <prgdir>/test/*.bats, which the tool runs with bats, and, for
the nodes of a resident program, the files <prgdir>/test/test_*.py,
which it runs with pytest.
A bats test loads the helper library whose path the tool exports as
DEBASHER_BATS_HELPERS, and runs a process with
debasher_process <processname> [<process_opts>]. Since no output
directory is involved, the test gives every option the process reads,
with the files it writes placed under the temporary directory of the
test. For example, for a process greet that writes a greeting
into the file given by -outf:
load "${DEBASHER_BATS_HELPERS}"
@test "greet writes the greeting into its file" {
run debasher_process greet -text Ann -secs 0 \
-outf "${BATS_TEST_TMPDIR}/greeting.txt"
[ "${status}" -eq 0 ]
[ "$(cat "${BATS_TEST_TMPDIR}/greeting.txt")" = "Hello, Ann!" ]
}
A node of a resident program is tested without running it: no FIFO is
opened and no Supervisor is involved. A pytest test builds the node
with load_node of the module debasher_runtime_testing, naming
the ports whose traffic it checks, gives it packets with feed and
reads what it sent on a port with sent. restart builds the node
again from its node state, as recovery after a crash does, and fails
when the restored node does not capture the same state. For example,
for a node Accumulate that sends the running sum of the numbers it
receives:
from debasher_runtime_testing import load_node
def test_running_sum():
node = load_node("Accumulate", inputs=["numbers"], outputs=["outsum"])
node.feed("numbers", 3)
node.feed("numbers", 4)
assert node.sent("outsum") == [3, 7]
def test_restart_keeps_the_sum():
node = load_node("Accumulate", inputs=["numbers"], outputs=["outsum"])
node.feed("numbers", 3)
node = node.restart()
node.feed("numbers", 4)
assert node.sent("outsum") == [7]
load_node also takes opts, the options of the node by name.
A node that observes the outside world, such as a
DirectoryWatcher, is tested with observe: it runs the
observe method of the node once and returns what it brought in,
which the node then processes as in a run. The test can change the
outside world between two calls, for example put a file in the
directory that a DirectoryWatcher watches (given with
opts={"watchdir": ...}) and observe twice, since a file counts
only once it has stayed the same for two observations in a row. A
ProgramLauncher and the Supervisor cannot be tested this way.
A process that activates a Conda environment runs in it in a test as
in a run. --conda-support and --docker-support create the Conda
environments and pull the Docker images that the processes declare
before the tests, as debasher_exec does before a run with the same
options; without them, they have to exist already, and a test of such
a process starts with debasher_skip_without_conda_env <name>, which
skips it, with its reason, where conda or the environment is missing.
Run tests in the web interface passes those options when the
program has conda or docker support.
The exit status of debasher_test is 0 when every test passed, 1
when a test failed, 2 when the tests could not be run (for instance,
<prgdir> has no program file, or bats or pytest is not installed)
and 77 when the program has no tests. DEBASHER_BATS and
DEBASHER_PYTEST give the bats and the pytest to run instead of
those found when DeBasher was configured. Running the tests writes
nothing into <prgdir>. The programs webui_batch_greet (bats
tests), webui_running_sum and webui_watch_tally (pytest
tests, the second of a DirectoryWatcher), installed under
<prefix>/share/debasher/webui_programs, carry examples.
debasher_proc_dataset
debasher_proc_dataset generates, for a set of dataset samples, one
debasher_exec command line per sample. It does not execute the
program itself: it prints the generated command lines to standard
output, so that they can be inspected, redirected to a script, or
piped into a job submission tool.
Its options are:
--pfile <string>: module file defining the program to be executed for each sample.--sched <string>: scheduler used to execute the program.--prg-sopts <string>: file containing, one line per sample, the program options specific to that sample (e.g. its input and output file names). This option is mandatory.--prg-opts <string>: file containing program options common to every sample (e.g. resource-related options), appended to each generated command line.--dflt-nodes <string>: default set of nodes used to execute the program.
For example, given a samples.txt file with one line of
sample-specific options per sample:
$ debasher_proc_dataset --pfile debasher_file_example.sh --sched SLURM \
--prg-sopts samples.txt --prg-opts common_opts.txt > run_samples.sh
Process Monitoring and Control
debasher_status
debasher_status shows the execution status of the processes of a
DeBasher program. It is described in the Executing DeBasher Programs Section, in its
Process Status Visualization part. In addition to the -d
<string> (output directory) and -p <string> (name of a specific
process) options covered there, debasher_status also accepts
-i, which additionally shows the scheduler id assigned to each
process. Like debasher_stats and debasher_stop, it takes the
processes of the program from program.procspec in the output
directory, not from the module, so it reports the processes that ran
even if the module changed since.
debasher_stats
debasher_stats reports, for the processes of a DeBasher program,
their status and the elapsed time in seconds until completion. For an
array process, it gives the total time of its finished tasks followed by
the time of each one (<total> : <idx>-><time> ; ...), and the total
is UNKNOWN when the time of any of its tasks is. It is
described in the Executing DeBasher Programs Section, in its Program Statistics
Generation part. As with debasher_status, the output directory is
given with -d <string> and, optionally, a single process can be
selected with -p <string>.
debasher_stop
debasher_stop stops the execution of a running DeBasher program,
or of a single one of its processes. It is described in the
Executing DeBasher Programs Section, in its Program Stop part. The output directory
is given with -d <string>; a specific process to stop can be given
with -p <string>, and is otherwise omitted to stop the whole
program.
debasher_reformat_status
debasher_reformat_status reformats the output of debasher_status
into a single, fixed-width status line, one column per process. This
is convenient for compact monitoring or logging, since it condenses
the multi-line output of debasher_status into one row of process
names and one row (or, optionally, just one row) of their statuses.
By default the tool reads debasher_status output from standard
input, so both tools are normally combined with a pipe:
$ debasher_status -d out | debasher_reformat_status -f 1 -l 12
Its options are:
-p <string>: file containingdebasher_statusoutput to reformat; if not given, the input is read from standard input.-f <int>: output format.1prints a header row (process names) followed by a row of statuses;2prints only the row of statuses.-l <int>: field length; every process name and status is padded or truncated to this length.-e <string>: comma-separated list of process names to exclude from the output.
Resident Program Control
The tools below act on a resident program, running or stopped, given
its output directory with -d <string>. The Resident DeBasher Programs Section
explains what they are for; debasher_status also works on a
resident program.
debasher_stop_resident
debasher_stop_resident stops a running resident program in order:
every node saves its state in one last snapshot and then stops, so
that the next debasher_exec on the same output directory resumes
it. debasher_stop would kill every process at once instead.
$ debasher_stop_resident -d <string> [-x <string>] [--timeout <int>]
-x <string>: comma-separated nodes to leave running: a process name (every task, if it is an array) or<process>:<idx>(one task of an array).--timeout <int>: seconds to wait for the stop to complete (60 by default), after which the tool falls back todebasher_stopand fails.
debasher_snapshot_resident
debasher_snapshot_resident takes a snapshot of a running resident
program: every node saves a checkpoint and prunes its input log.
$ debasher_snapshot_resident -d <string> [--timeout <int> | --every <int>]
--timeout <int>: seconds to wait for the snapshot to complete at every node (60 by default).--every <int>: take a snapshot every<int>seconds, until no node of the program is running.
debasher_reset_resident
debasher_reset_resident takes a stopped resident program back to
its first run: it moves the checkpoints, input logs, notices and
process outputs of every node under __reset__/<timestamp>/ in the
output directory, so that the next debasher_exec starts every node
afresh. It refuses while any process of the program is running.
$ debasher_reset_resident -d <string> [--delete]
--delete: delete the state of the nodes instead of setting it aside.
debasher_inspect_resident
debasher_inspect_resident shows, in JSON, what a node of a resident
program keeps, and changes nothing. It works on a running program as
well as on a stopped one.
$ debasher_inspect_resident -d <string> -p <string> [-t <int>] <command>
$ debasher_inspect_resident -d <string> notices
-p <string> gives the process and -t <int> the index of the
task, for an array process. The commands are:
summary: the state of the node (alive, down, finished or not launched), its checkpoints, the size of its input log against its limit, its health and its notice.checkpoint <int>: a checkpoint that the node keeps, given by its epoch, assummarylists them.log [--port <string>] [--last <int>]: the latest records of the input log (100 by default), or those of one port.runs: the batch runs of a launcher node, with their states.notices: the notices of every node of the program (with-dalone).
Retrieving Process Output
debasher_get_stdout
debasher_get_stdout shows the standard output generated by a
process. It is introduced in the Quickstart Example Section.
Its -d <string> and -p <string> options select, respectively,
the program’s output directory and the process whose standard output
should be shown. An additional -t <int> option can be used to
select an individual task when the process is part of a task array
(see the description of the generate_opts method in the
Implementing DeBasher Programs Section). Passing --watch follows the file as it
grows (like tail -f) instead of printing its current contents and
exiting, which is useful for monitoring a process that is still
running.
debasher_get_sched_out
debasher_get_sched_out shows the scheduler output for a process,
which includes its error output together with scheduling-related
information, and is therefore useful for debugging. Its standard output
is not included: debasher_get_stdout shows it.
It is introduced in the Quickstart Example Section. As with
debasher_get_stdout, it takes -d <string> and -p <string>,
plus an optional -t <int> to select an individual task of a task
array, and supports --watch to follow the file as it grows instead
of printing its current contents and exiting.
debasher_get_fifo_mirror
debasher_get_fifo_mirror shows the mirrored content of a process’s
FIFO, i.e. a copy of everything the owning process wrote into it,
provided the FIFO was declared with the mirroring option of
define_fifo_opt on an output option
(see the Implementing DeBasher Programs Section for more information about FIFOs) and
the owning process has already run.
Its options are:
-d <string>: output directory for program processes.-p <string>: name of the process owning the mirrored FIFO.-f <string>: name of the FIFO, as given todefine_fifo_opt.-t <int>: accepted for uniformity withdebasher_get_stdoutanddebasher_get_sched_out, and ignored: the name of a FIFO already tells apart the FIFOs of the tasks of an array.--watch: follow the file as it grows (liketail -f) instead of printing its current contents and exiting.
Module and Process Documentation
debasher_doc_mod
debasher_doc_mod generates Markdown documentation for a module and
its processes directly from their code, without having to read
through the module’s own source file. It is introduced in the
Implementing DeBasher Programs Section:
$ debasher_doc_mod -m debasher_file_example.sh -s file_writer \
--show-opts --show-opthnd --show-impl --show-specs --show-meths
The -m <string> option gives the module file, and the optional
-s <string> option restricts the output to a single process
(omitted, every process the module defines is documented). The report
always opens with the module’s name and description, followed by a
Program Type section giving the program type (general or
resident). The remaining options select which information is
included in the report:
--show-opts: process options, as documented byexplain_opts, and, in a section of their own, the task shaping options thatexplain_task_shaping_optsdocuments.--show-opthnd: the option-handler method actually used (define_opts, or thegenerate_opts_size/generate_optspair).--show-impl: the process implementation itself.--show-specs: the process’s computational and additional specifications.--show-meths: the names of the Process Methods the process defines.--show-meths-with-code: like--show-meths, but prints the full code of each method instead of just its name.--show-vars: process variables information.--show-vars-with-values: like--show-vars, but also shows the value of each variable (only meaningful for a non-Bash implementation).--show-shdirs: shared directories defined directly by the module.--show-all-shdirs: every shared directory reachable from the program (the module plus every module it loads, transitively).--show-all-envvars: every variable newly bound while loading the module (the module plus every module it loads, transitively), excluding names already set beforehand and the engine’s own internal bookkeeping.--resolve-var <string>: shows the value of a variable already set after loading the module; can be given multiple times.
Web Interface
debasher_webui
debasher_webui launches the DeBasher web interface (see the
DeBasher Web Interface Section): a server that exposes the workflow API and,
once the frontend has been built and installed, also serves it, so
that both are available from a single process at
http://<host>:<port>/. The server obeys only the requests that
carry its token: it prints the address of the web interface with the
token (http://<host>:<port>/#token=<token>), to open once in a
browser, and leaves the token for debasher_mcp in a file readable
only by the user (webui-<port>.token under
$XDG_RUNTIME_DIR/debasher, or ~/.debasher/run).
$ debasher_webui [--host <string>] [--port <int>] [--token <string>]
--host <string>: address to bind to (127.0.0.1by default).--port <int>: port to listen on (8000by default).--token <string>: the token, instead of a new random one at every start. TheDEBASHER_WEBUI_TOKENenvironment variable gives it as well, without showing it to the other users of the machine in the list of processes.
The tool requires the fastapi and uvicorn Python packages for
whichever python3 interpreter is first found on PATH. If they
are not installed, debasher_webui prints instructions for creating
a virtual environment, installing them there, and either activating
that environment before running the tool or pointing it directly at
the environment’s interpreter through the DEBASHER_WEBUI_PYTHON
environment variable.
debasher_mcp
debasher_mcp runs the MCP server of DeBasher, which offers to an AI
agent, such as Claude Code, what the web interface offers to a person:
reading a program, editing it, running it and following its run,
writing and running its business tests (see debasher_test), and
managing the files of its home directory, as tools
of the Model Context Protocol. The agent starts it and talks to it over its
standard input and output. It is a client of the server that
debasher_webui launches, which has to be running, and it edits programs
with the same rules as the editor of the web interface: each tool that
edits a program applies its edits whole or not at all, refuses a save over
changes saved elsewhere since it read the program, and, called with
dry_run, answers with what it would change and saves nothing.
$ debasher_mcp [--url <string>] [--claude-settings]
--url <string>: URL of the server of the web interface (http://127.0.0.1:8000by default).--claude-settings: prints the settings of Claude Code that debasher_claude passes, the permissions of the tools of the server, and exits.
It sends the token of the server with every request, which it reads by
itself from the file that debasher_webui leaves for its port (see
debasher_webui), so neither its command line nor its registration
with an agent holds the token. It does so only for a server on the local
machine that is still running.
The tool needs Node.js: it runs under the node named by the
DEBASHER_MCP_NODE environment variable, or else the one found when
DeBasher was configured, or else the first one on PATH. To make it
available to Claude Code, for example:
$ claude mcp add debasher -- debasher_mcp --url http://127.0.0.1:8000
To start Claude Code on one program, with this server already set up, see debasher_claude.
debasher_claude
debasher_claude starts Claude Code on a program saved with the web
interface, in its home directory, with everything DeBasher gives it: the
MCP server (see debasher_mcp) talking to the server of the web
interface, the permissions of its tools, and the plugin of DeBasher,
whose skills help with the web interface and DeBasher
(/debasher:help), with the design of a program, its processes and
their connections (/debasher:design), with the code of the
processes and their tests (/debasher:implement), and with feedback
on that code (/debasher:review). The editor of the
web interface, if the program is open there, loads what Claude Code
saves. It uses your own installation and account of Claude Code.
$ debasher_claude --home-dir <string> [--url <string>]
[--mode <string>] [--prompt <string>] [--dry-run]
[-- <claude options>]
--home-dir <string>: home directory of the program.--url <string>: URL of the server of the web interface (http://127.0.0.1:8000by default).--mode <string>: the skill the session starts with,help,design,implementorreview. Any of them can be called later in the same session.--prompt <string>: the first message of the session, given to the skill of the mode when there is one.--dry-run: prints the command that starts Claude Code instead of running it.
What follows -- is passed to Claude Code as it is, and the
DEBASHER_CLAUDE_CMD environment variable names its command
(claude by default). Tools that only read run without asking; those
that edit, validate, test or run the program ask until you allow them,
and those that delete files or program state, or stop or restart
something, always ask. Claude Code may not edit by hand what DeBasher
keeps in .debasher. For example:
$ debasher_claude --home-dir ~/programs/my_program --mode design
Claude Code keeps its conversations by the directory where it runs,
which debasher_claude makes the home directory of the program, so
the conversations of each program are its own. -- --continue takes
up the last one again, and -- --resume lists them for you to pick
one:
$ debasher_claude --home-dir ~/programs/my_program -- --continue