Attributes and interpreters
Attributes live in comments (# @key value) and adjust how a function is exposed or executed. Interpreter selection can be declared via attributes or shebangs.
Descriptions and args
@desc— one-line summary shown in listings and MCP tool schemas.@arg <name> [type] <description>— add human-readable parameter docs. Names should match the signature. Optional type keyword (string,integer,float/number,boolean,object/dict) sets the JSON schema type for MCP when the function has no typed signature.@instructions <text>— top-level MCP guidance line appended to serverinitialize.instructions. This is single-line and repeatable; lines are aggregated in merged/source order.
# @desc Deploy to an environment
# @arg env Target environment (staging|prod)
# @arg version Version to deploy (defaults to "latest")
deploy(env: str, version = "latest") { ... }
@argtype vs. signature type hint: The type keyword in@argand the type annotation in the function signature serve related but distinct purposes:
- Signature type hint (e.g.,
env: str) is the primary driver. When a typed signature is present, it controls the MCP JSON schema type and, in polyglot functions (Python, Node.js, Ruby), drives automatic runtime value conversion.@argtype keyword (e.g.,# @arg env string …) is a fallback used when the function has no typed signature — for example, shell functions that rely on positional variables ($1,$2). In that case, the@argtype sets the MCP schema type.@argdescription is always used regardless of whether a signature type hint is present.- The two do not need to agree, but keeping them consistent is recommended. If they conflict, the signature type hint wins for MCP schema generation.
Top-level MCP instruction example:
# @instructions Confirm target environment before deploy calls
# @instructions Prefer exact keywords when using memory recall queries
Platform guards
Limit a function to specific operating systems.
Attribute form (separate functions by OS):
# @os windows
clean() del /Q dist
# @os unix
clean() rm -rf dist
Working directory (@cd)
The @cd <path> attribute sets the working directory for a function's execution:
- Relative paths are resolved relative to the file defining the function (e.g. the sourced file's directory or the root Runfile directory).
- Absolute paths and home directory (
~/or~) paths are supported. - When composed with other functions, directory changes are executed in an isolated subshell to prevent directory changes from leaking to callers.
- Works across all interpreters (shell, Python, Node.js, Ruby, etc.).
# @cd ./frontend
build() npm run build
# @cd crates/cli
test() cargo test
Task dependencies and parallelism
Functions can declare prerequisite tasks using # @depends:
@depends <task1>, <task2>, ...— declare one or more dependencies to run before this task.- Dependencies are resolved as a Directed Acyclic Graph (DAG) with automatic cycle detection.
- Deduplication / Memoization: If multiple dependencies share a common prerequisite (e.g. diamond dependency pattern), the shared prerequisite executes only once.
- Failure of any dependency immediately halts downstream execution.
To execute independent dependencies concurrently:
@parallel— marks the function so that independent tasks at the same depth in the dependency DAG execute in parallel stages.- Concurrency can also be controlled on the command line using
-p, --parallelor-j, --jobs <N>. - Passing
-j 1overrides@paralleland forces sequential execution.
clean() {
cargo clean
}
# @depends clean
build() {
cargo build --release
}
# @depends build
lint() {
cargo clippy
}
# @depends build
test() {
cargo test
}
# @depends lint, test
# @parallel
ci() {
echo "CI checks passed!"
}
In the example above, running run ci:
- Runs
clean. - Runs
build. - Runs
lintandtestconcurrently in parallel. - Runs
ci.
Interpreter selection
There are two ways to pick an interpreter for a function body:
- Shebang detection — first line inside the body
script() {
#!/usr/bin/env python3
import sys
print(sys.argv[1])
}
@shellattribute — explicit, and takes precedence over a shebang
# @shell node
serve() {
console.log(process.argv[1] || 3000);
}
Supported interpreters include python, python3, node, ruby, pwsh, bash, and sh.
Precedence and resolution
@shelloverrides a shebang if both exist.- If no interpreter is set, the function uses the default shell (
RUN_SHELLor platform default).
For language-specific behaviors and argument forwarding, see Polyglot commands.