# run installation
go install github.com/pt-main/run/cmd/run@latest
# tal installation
go install github.com/pt-main/run/cmd/tal@latestrun is a tool for managing scripts, scripting any scenarios in an embedded Lua-like language with incrementality, storing scripts in global/local storage, complete independence from system and platform (works anywhere Go compiles), and with built-in ways to distribute scripts, for example via GitHub.
The project contains Task Lua (tal) inside itself - a task runner seamlessly integrated into run. More details can be read in the project README.
| Problem | run solves |
|---|---|
| Scripts scattered across projects | Global storage ~/run/ |
| Need to remember paths | One command: run -r myscript |
| Different languages | Support for Python, Bash, Batch, Lua - and easily extensible |
| Grouping | Tags for selective running (--tagged) |
| Project scripts | Local mode with .run/ in the current folder |
| Security | TYCL config with a strict contract |
| Compactness | Small binary while fully platform-independent |
run gives globality, simplicity and control without unnecessary complexity.
And why Tal?
| Problem | tal solves |
|---|---|
| Makefile is hard to read and write | Simple DSL with comments and Lua instead of Shell |
| Incrementality works poorly | SHA256 hashes instead of modification time |
| No calling tasks from each other | Tasks can be called via a built-in function |
| File dependencies are cumbersome | works out of the box |
tal gives incrementality, modernity and Lua - all in one tool.
Download the release for your OS/architecture and put it in PATH:
# Linux/macOS
chmod +x run-linux-amd64
sudo mv run-linux-amd64 /usr/local/bin/run
# Windows
# Just put run-windows-amd64.exe in a folder that is in PATHgo install github.com/pt-main/run@latestOn first launch run will create a structure in ~/run/:
config.tycl- config with the list of scripts.scripts/- Lua wrappers for launching.base/- original script files.
| Command | Description | Example |
|---|---|---|
-add <path> <name> [docs] [--force] |
Add a script (supports .py, .sh, .bat, .lua) |
run -add script.py mypy |
-remove <name> |
Remove a script | run -remove mypy |
-list |
Show the list of scripts | run -list |
-install <url> [name] [description] [--force] [--args="..."] |
Install a script from an external source, or run a tal script for installation | |
<name> [args...] |
Run a script (if the name does not match a command) | run mypy arg1 |
-tag <name> <tags...> |
Add tags | run -tag mypy deploy prod |
-rm-tag <name> <tags...> |
Remove tags | run -rm-tag mypy prod |
-localmode [true/false] |
Enable/disable local mode, show the current script launch state | run -localmode true |
-r <name> [args...] [--tagged='...'] |
Run a script | run -r mypy arg1 arg2 |
-r --tagged="tag1;tag2;..." |
Run scripts with any of the tags | run -r --tagged="deploy;test" |
-r --tagged="..." --parallel |
Run scripts with the required tag in parallel | run -r --tagged="deploy;build" --parallel |
-r --tagged="..." --args="" |
Pass arguments to the script (if you need to avoid a conflict, for example with run flags, or not pass arguments) | run -r --tagged="deploy;build" --args="--tagged dev",run -r --tagged="deploy;build" --parallel --args - does not pass arguments instead of passing --parallel |
-version |
Show the version of run and tal | run -version |
--no_color – flag disables colored output throughout the session.
By default run works globally (config in ~/run/).
Enable local mode - and run will use .run/ in the current folder:
run -localmode true # enable
run -localmode false # disable
run -localmode # show stateThis is convenient for projects: scripts are stored in the repository and do not interfere with the global config.
--ll / --localmode / --gm / --globalmode immediately after run - launch in local/global mode; after completion, restores the mode set with run -localmode.
run automatically generates Lua wrappers that call the original scripts with the passed arguments.
| Extension | Language | Note |
|---|---|---|
.py |
Python | Looks for python3, then python |
.sh |
Bash | Executes via bash |
.bat |
Batch | Executes via cmd /c |
.lua |
Lua | Executes directly (without a wrapper) |
.task.lua |
Task Lua (Tal) | Executes via run tal run |
~/run/
├── config.tycl # Config in TYCL (strict contract)
├── scripts/ # Lua wrappers for launching
│ └── myscript.lua
└── base/ # Original scripts
└── myscript.py
Script configuration is built on Tycl - a typed language with the concept of contracts (fixed config formats).
Config contract -
strict {
scripts: objects = strict {
name: string, // Script name (command)
script: string, // Name of the wrapper file (matches the Lua script name inside run/scripts, without extension)
description: string, // Description
tags: strings, // Tags
ext: string, // Extension (.py, .sh, .bat, .lua)
},
}
The config is filled in automatically by the run CLI; after the first launch it looks like this -
{
scripts: objects = [
{
name: string = "test",
script: string = "test",
description: string = "[?BBK]Simple script for functions test[?RT]",
ext: string = "",
tags: strings = ["__test"],
}
],
}
Each wrapper is a Lua script that provides:
script_path(name)- path to the original script.get_arg(idx)- get an argument by index.get_args()- table of all arguments.run_script(name, ...)- run another script from the wrapper.run_script_parallel(name, ...)– runs the specified script asynchronously in a background thread. Does not block execution of the current script. All arguments after the name are passed to the called script.wait()– waits for all background scripts started viarun_script_parallelto finish. It is recommended to call it after starting parallel tasks to wait for their completion before the main script exits.run_cli(args)- run run cli with the passed arguments (as a string) in the current session.
Example:
run_script_parallel("build", "--release")
run_script_parallel("test")
wait() -- wait for the build and tests to finishrun -add ~/projects/tools/deploy.py deploy "Deploy to production"
run -list
# ╭─────── Scripts
# ⎬─ deploy (.py):
# │ Deploy to production
# ╰───────run -r deploy --env=prod
# or
run deploy --env=prod # when the script name does not conflict with run commandsrun -tag deploy prod utils
run -r --tagged="prod" # will run all scripts with the prod tagcd ~/myproject
run -localmode true
run -add script.py build
# now the script will be saved in .run/or
run --localmode add script.py buildImportant: for correct operation, the --localmode flag must be immediately after run.
By Pt, 2026 – written using lc, tap, pack, tycl.