skills/starlark-dev/SKILL.md
Develop and debug Kurtosis Starlark packages. Create packages from scratch, understand the plan-based execution model, use print() debugging, handle future references, and test packages locally. Use when writing or troubleshooting .star files.
npx skillsauth add kurtosis-tech/kurtosis starlark-devInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Create, debug, and test Kurtosis Starlark packages.
A minimal Kurtosis package needs two files:
my-package/
kurtosis.yml # Package metadata
main.star # Entry point
name: github.com/your-org/my-package
def run(plan, args):
plan.add_service(
name="my-service",
config=ServiceConfig(
image="nginx:latest",
ports={
"http": PortSpec(number=80, transport_protocol="TCP"),
},
),
)
# Run a local package
kurtosis run ./my-package
# Run with parameters
kurtosis run ./my-package '{"param1": "value1"}'
# Run a remote package from GitHub
kurtosis run github.com/ethpandaops/ethereum-package
# Run with a custom config file
kurtosis run github.com/ethpandaops/ethereum-package --args-file config.yaml
# Dry run (plan only, no execution)
kurtosis run ./my-package --dry-run
Kurtosis Starlark executes in two phases:
add_service(), exec(), etc. don't execute immediately — they return future references.This means you cannot use the return value of plan.exec() in Python-level logic like if/else during the planning phase. Use plan.verify() or plan.assert() instead.
# WRONG: result is a future reference, not a real value during planning
result = plan.exec(service_name="my-service", recipe=ExecRecipe(command=["echo", "hello"]))
if result["output"] == "hello": # This won't work as expected
plan.print("matched")
# RIGHT: use plan.verify for conditional checks
result = plan.exec(service_name="my-service", recipe=ExecRecipe(command=["echo", "hello"]))
plan.verify(result["exit_code"], "==", 0)
def run(plan, args):
plan.print("Args received: {}".format(args))
service = plan.add_service(
name="my-service",
config=ServiceConfig(image="nginx:latest"),
)
plan.print("Service IP: {}".format(service.ip_address))
plan.print("Service hostname: {}".format(service.hostname))
plan.wait(
service_name="my-service",
recipe=GetHttpRequestRecipe(port_id="http", endpoint="/health"),
field="code",
assertion="==",
target_value=200,
timeout="60s",
)
result = plan.exec(
service_name="my-service",
recipe=ExecRecipe(command=["cat", "/etc/hostname"]),
)
plan.verify(result["exit_code"], "==", 0)
plan.print("Hostname: {}".format(result["output"]))
config_template = read_file("./templates/config.toml")
artifact = plan.render_templates(
name="my-config",
config={
"config.toml": struct(
template=config_template,
data={"key": "value"},
),
},
)
plan.add_service(
name="my-service",
config=ServiceConfig(
image="my-image:latest",
files={"/etc/myapp": artifact},
),
)
dependency = import_module("github.com/org/other-package/lib.star")
def run(plan, args):
dependency.some_function(plan)
Use a dry-run → execute → verify workflow:
# 1. Validate the plan without executing
kurtosis run --dry-run ./my-package
# 2. Run and check output
kurtosis run ./my-package
# 3. Inspect the created enclave
kurtosis enclave inspect <enclave-name>
# 4. Check service logs
kurtosis service logs <enclave-name> <service-name>
# 5. Shell into a service to verify state
kurtosis service shell <enclave-name> <service-name>
# 6. Clean up after testing
kurtosis clean -a
| Error | Cause | Fix |
|-------|-------|-----|
| cannot use future reference in if | Using plan result in Python logic | Use plan.verify() or plan.assert() |
| service not found | Service name typo or not yet created | Check plan.add_service() name matches |
| port not found | Port ID mismatch | Ensure port_id in recipes matches ports dict key |
| image pull failed | Image doesn't exist or no auth | Verify image tag, check docker pull manually |
| kurtosis.yml not found | Running from wrong directory | Run from package root containing kurtosis.yml |
data-ai
Manage services in Kurtosis enclaves. Add, inspect, stop, start, remove, update services. View logs, shell into containers, and execute commands. Use when you need to interact with running services.
content-media
Run Starlark scripts and packages with kurtosis run. Covers all flags including dry-run, args-file, parallel execution, image download modes, verbosity levels, and production mode. Use when executing Kurtosis packages locally or from GitHub.
testing
Manage Kurtosis Portal for remote context access. Start, stop, and check status of the Portal daemon that enables communication with remote Kurtosis servers. Use when working with remote Kurtosis contexts.
testing
View and manage port mappings for Kurtosis services. Check which local ports map to service ports and troubleshoot connectivity. Use when services aren't reachable or you need to find the right port.