Starlark — 18 Operations for AI Agents

Starlark is the language of build logic at scale — Bazel macros, Buck rules, the Python-shaped layer that decides what compiles. act101 reads rules and macros as structure, so agents navigate build definitions instead of reverse-engineering them.

This page is the canonical reference an AI coding agent uses to refactor, query, and analyze Starlark code through the act MCP server. 18 operations available: 0 refactor, 18 query, 0 analysis. Each operation is callable from Claude Code, Cursor, Codex, OpenCode, or any MCP-compatible agent host. Click any operation for a stable anchor link suitable for citation.

18Query

Worked Starlark examples

act101 reads a Starlark file's load(...) statement as an import declaration, named for the entire statement text rather than just the loaded path; a top-level assignment like BOARD_DEFINES = {...} as a variable; and each def as a function. symbols covers the same functions and the same top-level assignment, but tags the assignment kind: unknown instead of variable, and has no rule for load(...) at all, so the import disappears from that query entirely. The unit of structure in this grammar is the top-level statement: neither query descends into a function's own body, so the if/for control flow inside firmware_variant and firmware_variants produces no declaration of its own. Each example below is the verbatim output of the command shown, run against the file shown. Query outputs are pretty-printed with the timing block omitted.

Read the load statement, board table, and macros as a skeleton

firmware_variants.bzl generates per-board firmware targets: it loads cc_binary from cc_rules.bzl, keeps a BOARD_DEFINES table of per-board preprocessor defines, and two macros — firmware_variant for one board, firmware_variants for a whole list.

$ act query skeleton firmware_variants.bzl

Before

load("//tools:cc_rules.bzl", "cc_binary")

BOARD_DEFINES = {
    "esp32-devkit": ["BOARD_ESP32", "HAS_WIFI"],
    "esp32-lite": ["BOARD_ESP32", "LOW_POWER"],
    "stm32-bringup": ["BOARD_STM32", "NO_WIFI"],
}

def firmware_variant(name, board, extra_defines = []):
    defines = BOARD_DEFINES.get(board)
    if not defines:
        fail("unknown board: " + board)
    cc_binary(
        name = name + "-" + board,
        srcs = ["main.c"],
        defines = defines + extra_defines,
    )

def firmware_variants(name, boards):
    for board in boards:
        firmware_variant(name = name, board = board)

Output

{
    "type": "Skeleton",
    "declarations": [
        {
            "kind": "import",
            "name": "load(\"//tools:cc_rules.bzl\", \"cc_binary\")",
            "range": {
                "start": {
                    "file": "firmware_variants.bzl",
                    "line": 1,
                    "column": 1,
                    "byte_offset": 0
                },
                "end": {
                    "file": "firmware_variants.bzl",
                    "line": 1,
                    "column": 42,
                    "byte_offset": 41
                }
            }
        },
        {
            "kind": "variable",
            "name": "BOARD_DEFINES",
            "range": {
                "start": {
                    "file": "firmware_variants.bzl",
                    "line": 3,
                    "column": 1,
                    "byte_offset": 43
                },
                "end": {
                    "file": "firmware_variants.bzl",
                    "line": 7,
                    "column": 2,
                    "byte_offset": 208
                }
            },
            "name_range": {
                "start": {
                    "file": "firmware_variants.bzl",
                    "line": 3,
                    "column": 1,
                    "byte_offset": 43
                },
                "end": {
                    "file": "firmware_variants.bzl",
                    "line": 3,
                    "column": 14,
                    "byte_offset": 56
                }
            }
        },
        {
            "kind": "function",
            "name": "firmware_variant",
            "range": {
                "start": {
                    "file": "firmware_variants.bzl",
                    "line": 9,
                    "column": 1,
                    "byte_offset": 210
                },
                "end": {
                    "file": "firmware_variants.bzl",
                    "line": 17,
                    "column": 6,
                    "byte_offset": 489
                }
            },
            "name_range": {
                "start": {
                    "file": "firmware_variants.bzl",
                    "line": 9,
                    "column": 5,
                    "byte_offset": 214
                },
                "end": {
                    "file": "firmware_variants.bzl",
                    "line": 9,
                    "column": 21,
                    "byte_offset": 230
                }
            }
        },
        {
            "kind": "function",
            "name": "firmware_variants",
            "range": {
                "start": {
                    "file": "firmware_variants.bzl",
                    "line": 19,
                    "column": 1,
                    "byte_offset": 491
                },
                "end": {
                    "file": "firmware_variants.bzl",
                    "line": 21,
                    "column": 53,
                    "byte_offset": 605
                }
            },
            "name_range": {
                "start": {
                    "file": "firmware_variants.bzl",
                    "line": 19,
                    "column": 5,
                    "byte_offset": 495
                },
                "end": {
                    "file": "firmware_variants.bzl",
                    "line": 19,
                    "column": 22,
                    "byte_offset": 512
                }
            }
        }
    ]
}

The skeleton reports four declarations: the load(...) line as import, named for the entire statement rather than the loaded path; BOARD_DEFINES as variable; and firmware_variant and firmware_variants as function.

List the table and macros as symbols, without the load statement

firmware_variant looks up board in BOARD_DEFINES and fails if the board is unknown; firmware_variants loops over a list of boards and calls it once per board.

$ act query symbols firmware_variants.bzl

Before

load("//tools:cc_rules.bzl", "cc_binary")

BOARD_DEFINES = {
    "esp32-devkit": ["BOARD_ESP32", "HAS_WIFI"],
    "esp32-lite": ["BOARD_ESP32", "LOW_POWER"],
    "stm32-bringup": ["BOARD_STM32", "NO_WIFI"],
}

def firmware_variant(name, board, extra_defines = []):
    defines = BOARD_DEFINES.get(board)
    if not defines:
        fail("unknown board: " + board)
    cc_binary(
        name = name + "-" + board,
        srcs = ["main.c"],
        defines = defines + extra_defines,
    )

def firmware_variants(name, boards):
    for board in boards:
        firmware_variant(name = name, board = board)

Output

{
    "type": "Symbols",
    "symbols": [
        {
            "name": "BOARD_DEFINES",
            "kind": "unknown",
            "range": {
                "start": {
                    "file": "firmware_variants.bzl",
                    "line": 3,
                    "column": 1,
                    "byte_offset": 43
                },
                "end": {
                    "file": "firmware_variants.bzl",
                    "line": 3,
                    "column": 14,
                    "byte_offset": 56
                }
            },
            "visibility": "unknown"
        },
        {
            "name": "firmware_variant",
            "kind": "function",
            "range": {
                "start": {
                    "file": "firmware_variants.bzl",
                    "line": 9,
                    "column": 5,
                    "byte_offset": 214
                },
                "end": {
                    "file": "firmware_variants.bzl",
                    "line": 9,
                    "column": 21,
                    "byte_offset": 230
                }
            },
            "visibility": "unknown"
        },
        {
            "name": "firmware_variants",
            "kind": "function",
            "range": {
                "start": {
                    "file": "firmware_variants.bzl",
                    "line": 19,
                    "column": 5,
                    "byte_offset": 495
                },
                "end": {
                    "file": "firmware_variants.bzl",
                    "line": 19,
                    "column": 22,
                    "byte_offset": 512
                }
            },
            "visibility": "unknown"
        }
    ]
}

symbols reports the same BOARD_DEFINES, firmware_variant, and firmware_variants, but tags BOARD_DEFINES kind: unknown rather than variable; the load(...) import that appeared in the skeleton has no rule in symbols.scm and is absent here.

Query

18 query tools, the same on every supported language. Descriptions live in the shared reference: /docs/query-tools.

callers control_flow data_flow definition diagnostics effect_closure effect_summary fix_auto get_type graph import_organize interface mutations references repo_outline skeleton symbols symbols_batch

← SQLiteSvelte →