Scripting runtime for systems and agentic automation

Create systems and infrastructure automation scripts that are easy for humans to understand and safe for AI agents to execute.

local-check.star
#!/usr/bin/env kite
# local-check.star — read config, process logs, and write SQL

def main():
    db_path = var_str("db_path", "data/app.db")
    db = sql.open("sqlite3", db_path)
    
    # Process backup logs concurrently
    backups = fs.glob("backups/*.json")
    for f in backups:
        data = json.decode(fs.read(f))
        db.exec("INSERT INTO logs (host, status) VALUES (?, ?)", 
                data["host"], data["status"])
    
    printf("Processed %d logs.\n", len(backups))
k8s-controller.star
#!/usr/bin/env kite
# k8s-controller.star — reconcile replica counts

def reconcile(event, obj):
    if obj.spec.replicas > 10:
        k8s.apply({
            "apiVersion": "apps/v1",
            "kind": "Deployment",
            "metadata": {"name": obj.metadata.name,
                         "namespace": obj.metadata.namespace},
            "spec": {"replicas": 10},
        })

k8s.control("deployments",
    reconcile = reconcile,
    labels    = "enforce-max=true",
)
fleet-check.star
#!/usr/bin/env kite
# fleet-check.star — inspect remote host fleets

def main():
    fleet = ssh.config(
        hosts       = ["web-1", "web-2", "web-3"],
        user        = "deploy",
        key         = "~/.ssh/id_ed25519",
        exec_policy = "concurrent",
    )
    for r in fleet.exec("systemctl is-active nginx"):
        status = "Active" if r.ok else "Inactive/Failed"
        printf("Host %s Nginx: %s\n", r.host, status)
weather-mcp.star
#!/usr/bin/env kite
# weather-mcp.star — expose tools to AI agents

def get_weather(city):
    """Return the current weather for a city."""
    forecasts = {
        "san francisco": {"temp": 64, "conditions": "foggy"},
        "tokyo":         {"temp": 78, "conditions": "sunny"},
    }
    return forecasts.get(city.lower(), {"error": "no data"})

mcp.serve(
    name  = "weather-provider",
    tools = [get_weather],
)

Quick Install

Install the kite binary on your local machine using your preferred setup:

go install github.com/project-starkite/starkite/kite@latest
# Linux (x86_64)
wget https://github.com/project-starkite/starkite/releases/latest/download/kite-linux-amd64 -O kite

# macOS (Apple Silicon)
wget https://github.com/project-starkite/starkite/releases/latest/download/kite-darwin-arm64 -O kite

# Windows (PowerShell)
Invoke-WebRequest -Uri "https://github.com/project-starkite/starkite/releases/latest/download/kite-windows-amd64.exe" -OutFile kite.exe
git clone https://github.com/project-starkite/starkite.git
cd starkite
make kite          # builds ./bin/kite (all-in-one)
sudo install -m 0755 ./bin/kite /usr/local/bin/kite

Running Starkite Scripts

1. Run via the kite CLI

Starkite scripts run through the kite CLI. The kite run command (or its implicit shorthand) accepts any .star file and forwards --var arguments to the script — suitable for ad-hoc invocation, CI pipelines, and pipeline composition with other tools.

$ kite run ./deploy.star

# shorthand — `run` is implicit
$ kite ./deploy.star --var image_tag=v1.0.0

# pipe results to other tools
$ kite ./manifest.star | kubectl apply -f -

2. Execute via shebang

A starkite script with a #!/usr/bin/env kite shebang and the executable bit set runs like any other shell program. The kite prefix is not required at the call site.

$ cat deploy.star
#!/usr/bin/env kite
print("rolling out v1.0.0")

$ chmod +x deploy.star
$ ./deploy.star
rolling out v1.0.0

One Binary. Complete Automation.

Standard Library

Twenty-seven built-in modules cover everyday automation: files, processes, HTTP client and server, SSH, JSON, YAML, CSV, gzip/zip, hashing, regex, templating, time, UUIDs, structured logging, retries, and concurrency. Every module is built directly into the runtime, eliminating the need for a Python venv, Node install, or external package manager.

Browse modules
#!/usr/bin/env kite

# Spin up an HTTP API server in a few lines
def health(req):
    return {"status": 200, "body": {"ok": True}}

def echo(req):
    return {"status": 200, "body": req.body}

http.serve({
    "GET /health": health,
    "POST /echo":  echo,
}, port=8080)

Infrastructure

Starkite's infrastructure capabilities center on native Kubernetes operations, integrating the API directly into the runtime across three tiers: k8s.list/apply/watch for direct resource control, k8s.deploy/expose/rollout for kubectl-equivalent verbs, and typed constructors for programmatic manifest composition. Scripts run as long-lived controllers via k8s.control or as admission webhooks via k8s.webhook. The kite kube subcommand generates the corresponding deployment manifests for either.

Explore Infrastructure
#!/usr/bin/env kite

# Reject Deployments asking for too many replicas
def validate(obj):
    if obj.spec.replicas > 10:
        return {"allowed": False,
                "message": "max 10 replicas"}
    return {"allowed": True}

k8s.webhook("/validate",
    validate = validate,
    port     = 9443,
    tls_cert = "/certs/tls.crt",
    tls_key  = "/certs/tls.key",
)

Agentic Support

To build or extend AI-native automation, Starkite supports agentic workflows through two main patterns: exposing Starlark functions as MCP tools that external agents — Claude, Cursor, IDE assistants — invoke without glue code. Alternatively, an agent can be composed entirely in Starlark using multi-provider LLM clients (Gemini, GPT, Claude), built-in tool calling, and structured output.

Build agents
#!/usr/bin/env kite

# Expose cluster operations as MCP tools
def list_pods(namespace):
    """List pods in a namespace."""
    pods = k8s.list("pods", namespace=namespace)
    return [{"name":  p["metadata"]["name"],
             "phase": p["status"]["phase"]} for p in pods]

def restart_deployment(name, namespace):
    """Restart a deployment."""
    k8s.rollout("deployment", name,
        action="restart", namespace=namespace)
    return "restarted %s/%s" % (namespace, name)

mcp.serve(
    name  = "k8s-ops",
    tools = [list_pods, restart_deployment],
)

Security

Two layers of defense apply to every script. Permission profiles gate module calls at the API layer under a deny-by-default policy (os.exec denied, fs.read allowed). gVisor sandboxing isolates the script at the syscall layer with no host filesystem access and no outbound network. Named profiles are defined in ~/.starkite/config.yaml and apply to any invocation via a single command-line flag.

Read the security model
# Named profile from ~/.starkite/config.yaml
$ kite run ./job.star --permissions=ci --sandbox=ci

# Built-in ladder profile — no config file needed
$ kite run ./job.star --allow-fs

# Deny-all permissions + strict sandbox for untrusted code
$ kite run ./untrusted.star --permissions=deny-all --sandbox=opaque
Error: permission denied: os.exec is not allowed

Built-in Script Testing

Write tests

Test files end in _test.star and define test_* functions. Each test verifies conditions through the built-in assert(cond, msg), with optional setup() and teardown() hooks running before and after every test. The skip() built-in marks the current test as skipped.

def test_addition():
    assert(2 + 2 == 4, "basic math should work")

def test_string_contains():
    assert("kite" in "starkite", "starkite should contain kite")

def test_list_length():
    items = ["a", "b", "c"]
    assert(len(items) == 3, "list should have 3 items")

Run tests

The kite test command discovers every _test.star file under the given path, runs each test_* function, and reports pass/fail counts. The --verbose flag prints each test name as it runs. The exit code is non-zero on any failure.

$ kite test ./tests/
Found 1 test file(s)
============================================================
Tests: 3 passed, 0 failed, 3 total
Time:  9ms
============================================================

Ready to Start? Learn more.