Custom Dialects
Custom Dialect Support
Section titled “Custom Dialect Support”Starlark is a configuration language used by many build systems and tools. Each tool extends Starlark with its own builtin functions, types, and globals. This creates a challenge for tooling: how do you provide accurate completions, hover documentation, and diagnostics when different files use different builtins?
skyls solves this with custom dialect support. You can configure which files use which dialect, and provide builtin definitions for each dialect.
Understanding Starlark Dialects
Section titled “Understanding Starlark Dialects”What is a Dialect?
Section titled “What is a Dialect?”The term “dialect” describes how different tools extend vanilla Starlark with custom builtins, rules, and behaviors. This is not an official Starlark term - it is how sky and other tools describe Starlark variations.
A Python Analogy
Section titled “A Python Analogy”If you come from the Python world, dialects are similar to how different frameworks and implementations extend or modify core Python:
| Python Concept | Starlark Parallel | Description |
|---|---|---|
| CPython vs PyPy vs MicroPython | starlark-go vs starlark-rust vs starlark-java | Same language, different interpreters with varying features |
| Django’s template language | Bazel’s BUILD files | Python-like but with restrictions and custom builtins |
| Jinja2 templates | Tilt’s Tiltfiles | ”Python-like but not Python” - familiar syntax, different capabilities |
| NumPy’s array syntax extensions | Buck2’s record and enum types | Implementation-specific extensions beyond the core spec |
| Flask vs Django vs FastAPI | Bazel vs Buck2 vs Tilt | Same language, different frameworks with different builtins |
The Layered Architecture
Section titled “The Layered Architecture”Every Starlark dialect builds on layers:
┌─────────────────────────────────────────────────────────────────┐│ Tool-Specific Builtins ││ (docker_build, cc_library, cxx_library, core.workflow, etc.) │├─────────────────────────────────────────────────────────────────┤│ Implementation Extensions ││ (record, enum, union types - starlark-rust) │├─────────────────────────────────────────────────────────────────┤│ Core Starlark Builtins ││ (len, range, str, dict, list, print, getattr, hasattr) │├─────────────────────────────────────────────────────────────────┤│ Starlark Language Spec ││ (syntax, semantics, data types, control flow) │└─────────────────────────────────────────────────────────────────┘Vanilla Starlark vs Dialects
Section titled “Vanilla Starlark vs Dialects”Vanilla Starlark (the official specification) provides:
# Core data typesnumbers = [1, 2, 3]mapping = {"key": "value"}text = "hello"
# Core builtinslength = len(numbers) # 3items = range(10) # [0, 1, 2, ..., 9]joined = ", ".join(["a", "b"]) # "a, b"
# Functions and control flowdef greet(name): if name: return "Hello, " + name return "Hello, World"
# Module loadingload("//lib:utils.star", "helper")Bazel extends this with build-system concepts:
# Bazel-specific: rule definitionscc_library( name = "mylib", srcs = ["lib.cc"], hdrs = ["lib.h"], deps = ["//other:lib"],)
# Bazel-specific: native module in .bzl filesdef _my_rule_impl(ctx): # ctx is a Bazel-specific object output = ctx.actions.declare_file(ctx.label.name + ".out") ctx.actions.run( outputs = [output], inputs = ctx.files.srcs, executable = ctx.executable._tool, ) return [DefaultInfo(files = depset([output]))]
# Bazel-specific: rule() and provider()MyInfo = provider(fields = ["value"])my_rule = rule(implementation = _my_rule_impl, attrs = {...})Buck2 has similar concepts but different names and additional type features:
# Buck2-specific: different rule namescxx_library( name = "mylib", srcs = ["lib.cpp"], headers = ["lib.h"], # Note: 'headers' not 'hdrs')
# Buck2-specific: record and enum types (starlark-rust extensions)BuildConfig = record( name = str, srcs = list[str], debug = field(bool, False),)
Status = enum("pending", "running", "complete")
# Buck2-specific: BXL scripts for build graph queriesdef _query_impl(ctx): deps = ctx.cquery().deps(ctx.cli_args.target) ctx.output.print("Dependencies: {}".format(len(deps)))Tilt extends for Kubernetes development:
# Tilt-specific: container and K8s functionsdocker_build( 'myapp-image', context='.', dockerfile='Dockerfile', live_update=[ sync('./src', '/app/src'), run('pip install -r requirements.txt', trigger=['requirements.txt']), ],)
k8s_yaml('k8s/deployment.yaml')k8s_resource('myapp', port_forwards='8080:8080')
# Tilt-specific: local development utilitieslocal_resource( 'compile', cmd='make build', deps=['./src'],)Why Dialects Exist
Section titled “Why Dialects Exist”Each tool has domain-specific needs that core Starlark cannot address:
| Tool | Domain | Why Custom Builtins? |
|---|---|---|
| Bazel | Build systems | Needs rules, actions, providers, dependency graphs |
| Buck2 | Build systems | Similar to Bazel, plus BXL for scripting the build graph |
| Tilt | K8s development | Needs container builds, K8s resources, live updates |
| Copybara | Code migration | Needs git operations, transformations, workflows |
| Kurtosis | Test environments | Needs service orchestration, networking, plans |
| ytt | YAML templating | Needs YAML-specific operations, overlays |
Dialect Detection
Section titled “Dialect Detection”The challenge for tooling is identifying which dialect a file uses. skyls uses several signals:
- Filename patterns:
BUILDfiles are Bazel,Tiltfileis Tilt - Workspace markers: Presence of
WORKSPACE,.buckconfig, etc. - Explicit configuration: The
.starlark/config.jsonfile - File extensions:
.bzlvs.starvs.bara.sky
Common Dialects Reference
Section titled “Common Dialects Reference”The following table shows which builtins are available in each dialect:
| Dialect | Tool | Files | Example Builtins |
|---|---|---|---|
| Bazel | Bazel build system | BUILD, *.bzl, WORKSPACE, MODULE.bazel | cc_library, java_binary, rule, provider |
| Buck2 | Buck2 build system | BUCK, *.bzl | cxx_library, genrule, bxl functions |
| Tilt | Tilt local dev | Tiltfile, *.star | docker_build, k8s_yaml, local_resource |
| Copybara | Copybara migration | *.bara.sky | core.workflow, git.origin, transformations |
| Kurtosis | Test environments | *.star | plan.add_service, ServiceConfig, plan.wait |
| Custom | Your own tools | Any pattern | Your DSL functions |
Without dialect awareness, skyls would report errors like undefined: docker_build when editing a Tiltfile, because it does not know about Tilt’s builtins.
Detailed Dialect Comparison
Section titled “Detailed Dialect Comparison”Available everywhere - these builtins are part of the Starlark specification:
# Type constructorsbool(x) # Convert to booleandict(**kwargs) # Create dictionaryint(x) # Convert to integerlist(iterable) # Create liststr(x) # Convert to stringtuple(iterable) # Create tuple
# Sequence operationslen(x) # Length of sequencerange(stop) # Integer sequencerange(start, stop) # Integer sequence with startsorted(x) # Sorted copyreversed(x) # Reversed iterator
# Dictionary operations{}.get(key, default) # Get with default{}.items() # Key-value pairs{}.keys() # Keys iterator{}.values() # Values iterator{}.update(other) # Merge dictionaries
# String operations"".format(*args) # String formatting"".join(iterable) # Join strings"".split(sep) # Split string
# Attribute accessgetattr(obj, name) # Get attributehasattr(obj, name) # Check attribute existsdir(obj) # List attributes
# Otherprint(*args) # Output (implementation-defined)type(x) # Type name as stringzip(a, b) # Pair up iterablesenumerate(x) # Index-value pairsany(iterable) # True if any truthyall(iterable) # True if all truthyBUILD files have these globals:
# Native rules (subset - many more exist)cc_library(name, srcs, hdrs, deps, ...)cc_binary(name, srcs, deps, ...)java_library(name, srcs, deps, ...)java_binary(name, srcs, main_class, deps, ...)py_library(name, srcs, deps, ...)py_binary(name, srcs, main, deps, ...)genrule(name, srcs, outs, cmd, ...)filegroup(name, srcs, ...)sh_binary(name, srcs, ...)alias(name, actual)
# BUILD file utilitiespackage(default_visibility, features, ...)licenses(license_types)exports_files(srcs, visibility, ...)glob(include, exclude, ...)select(conditions, no_match_error).bzl files also have:
# Rule definitionrule(implementation, attrs, outputs, ...)provider(doc, fields)aspect(implementation, attr_aspects, ...)
# Actions (in rule implementation)ctx.actions.run(outputs, inputs, executable, ...)ctx.actions.run_shell(outputs, inputs, command, ...)ctx.actions.write(output, content, ...)ctx.actions.declare_file(name)ctx.actions.declare_directory(name)
# Native module (in .bzl files)native.cc_library(...)native.glob(...)native.package_name()native.repository_name()BUCK files have:
# Native rules (Buck2 naming)cxx_library(name, srcs, headers, deps, ...)cxx_binary(name, srcs, deps, ...)python_library(name, srcs, deps, ...)python_binary(name, main, deps, ...)genrule(name, srcs, out, cmd, ...)filegroup(name, srcs, ...)export_file(name, src, ...)
# Configurationselect(conditions)read_config(section, key, default)BXL scripts (.bxl files) have:
# BXL entry pointbxl_main(impl, cli_args)
# CLI argument typescli_args.target_label()cli_args.string()cli_args.bool()cli_args.list()
# Context operationsctx.cquery() # Configured queryctx.uquery() # Unconfigured queryctx.analysis(target) # Run analysisctx.build(targets) # Build targetsctx.output.print(msg) # Print outputctx.output.write_json(path, data) # Write JSON
# Query operationsctx.cquery().deps(target)ctx.cquery().kind(pattern, targets)ctx.cquery().owner(files)Type extensions (starlark-rust):
# Record typesMyConfig = record( name = str, debug = field(bool, False),)
# Enum typesStatus = enum("pending", "running", "done")
# Type annotationsdef process(cfg: MyConfig) -> str: return cfg.nameTiltfile builtins:
# Container buildsdocker_build(ref, context, dockerfile, ...)docker_build_with_restart(ref, context, entrypoint, ...)custom_build(ref, command, deps, ...)
# Kubernetes resourcesk8s_yaml(yaml, allow_duplicates)k8s_resource(workload, port_forwards, resource_deps, ...)k8s_custom_deploy(name, apply_cmd, delete_cmd, ...)
# Local operationslocal(cmd, quiet, echo_off)local_resource(name, cmd, serve_cmd, deps, ...)read_file(path, default)read_json(path, default)read_yaml(path, default)
# Live updatesync(local_path, remote_path)run(cmd, trigger)restart_container()fall_back_on(files)
# Utilitieshelm(chart, name, namespace, values, ...)kustomize(path)blob(content)encode_json(obj)decode_json(str)
# Extensionsload('ext://restart_process', 'docker_build_with_restart')load('ext://namespace', 'namespace_create').bara.sky file builtins:
# Workflow definitioncore.workflow( name, origin, destination, authoring, transformations, mode, ...)
# Git operationsgit.origin(url, ref)git.destination(url, push, fetch)git.github_origin(url, ref)git.github_destination(url, push)git.github_pr_origin(url, branch, ...)git.github_pr_destination(url, destination_ref, ...)
# Authoringauthoring.pass_thru(default)authoring.overwrite(default)authoring.allowed(default, allowlist)
# Transformationscore.replace(before, after, paths, ...)core.move(before, after, paths, ...)core.remove(paths)core.rename(before, after)core.verify_match(regex, paths, ...)core.transform(transformations, ...)
# Globsglob(include, exclude)
# Metadatametadata.squash_notes(prefix, ...)metadata.expose_label(name, ...)Configuration File
Section titled “Configuration File”Dialect support is configured via .starlark/config.json in your workspace root.
File Discovery
Section titled “File Discovery”skyls searches for configuration in this order:
- CLI flag:
--config path/to/config.json(planned) - Environment:
STARLARK_CONFIG=/path/to/config.json(planned) .starlark/config.json(walking up from the file being edited)starlark.config.jsonin workspace root- Auto-detection based on workspace markers (
WORKSPACE,.buckconfig,Tiltfile)
Minimal Configuration
Section titled “Minimal Configuration”For simple cases, specify just the dialect:
{ "$schema": "https://sky.dev/schemas/starlark-config.json", "version": 1, "dialect": "bazel"}This tells skyls to use Bazel builtins for all Starlark files in the workspace.
Full Configuration
Section titled “Full Configuration”For complex workspaces with multiple dialects:
{ "$schema": "https://sky.dev/schemas/starlark-config.json", "version": 1,
"rules": [ { "files": ["Tiltfile", "tilt_modules/**/*.star"], "dialect": "tilt" }, { "files": ["*.bara.sky", "copy.bara.sky"], "dialect": "copybara" }, { "files": ["**/*.bzl"], "dialect": "bazel-bzl" }, { "files": ["BUILD", "BUILD.bazel", "**/BUILD", "**/BUILD.bazel"], "dialect": "bazel-build" }, { "files": ["**/*.star"], "dialect": "starlark" } ],
"dialects": { "tilt": { "builtins": [ ".starlark/builtins/tilt.builtins.json" ], "extends": "starlark" }, "copybara": { "builtins": [ ".starlark/builtins/copybara.builtins.json" ], "extends": "starlark" }, "bazel-build": { "builtins": [], "extends": "starlark" }, "bazel-bzl": { "builtins": [], "extends": "bazel-build" } },
"settings": { "reportUndefinedNames": true, "reportUnusedBindings": true, "checkLoadStatements": true }}Configuration Schema
Section titled “Configuration Schema”Top-Level Fields
Section titled “Top-Level Fields”| Field | Type | Required | Description |
|---|---|---|---|
$schema | string | No | JSON Schema URL for validation |
version | number | Yes | Schema version (currently 1) |
dialect | string | No | Default dialect for all files |
rules | array | No | File pattern to dialect mapping |
dialects | object | No | Custom dialect definitions |
settings | object | No | Analysis settings |
Rules Array
Section titled “Rules Array”Rules map file patterns to dialects. The first matching rule wins.
{ "rules": [ { "files": ["Tiltfile", "tilt_modules/**/*.star"], "dialect": "tilt" } ]}| Field | Type | Description |
|---|---|---|
files | string[] | Glob patterns to match (relative to config file) |
dialect | string | Dialect ID to apply |
Glob Pattern Syntax
Section titled “Glob Pattern Syntax”| Pattern | Matches |
|---|---|
* | Any characters except / |
** | Any characters including / (recursive) |
? | Any single character |
[abc] | Character class |
{a,b} | Alternatives |
Examples:
{ "rules": [ {"files": ["BUILD"], "dialect": "bazel"}, {"files": ["BUILD.bazel"], "dialect": "bazel"}, {"files": ["**/BUILD"], "dialect": "bazel"}, {"files": ["**/*.bzl"], "dialect": "bazel"}, {"files": ["src/**/*.star"], "dialect": "custom"}, {"files": ["tests/**/*_test.star"], "dialect": "custom"} ]}Dialects Object
Section titled “Dialects Object”Define custom dialects with builtin sources and inheritance:
{ "dialects": { "my-dialect": { "builtins": [ ".starlark/builtins/core.builtins.json", ".starlark/builtins/extensions.builtins.json", "https://example.com/builtins/v1.json" ], "extends": "starlark" } }}| Field | Type | Description |
|---|---|---|
builtins | string[] | Paths or URLs to builtin definition files |
extends | string | Parent dialect to inherit builtins from |
Builtin Sources
Section titled “Builtin Sources”Builtins can be loaded from:
- Local files: Relative to config file or absolute paths
- Remote URLs: HTTPS URLs (planned, not yet implemented)
- Embedded data: Built-in definitions for Bazel, Buck2 (automatic)
Settings Object
Section titled “Settings Object”Control analysis behavior:
{ "settings": { "reportUndefinedNames": true, "reportUnusedBindings": true, "checkLoadStatements": true }}| Setting | Type | Default | Description |
|---|---|---|---|
reportUndefinedNames | boolean | true | Report undefined variable/function references |
reportUnusedBindings | boolean | true | Report unused local variables |
checkLoadStatements | boolean | false | Validate load statement targets exist |
Dialect Inheritance
Section titled “Dialect Inheritance”Dialects can extend other dialects using the extends field. This creates a chain of builtin providers:
starlark (core builtins) | +-- bazel-build (BUILD file builtins) | | | +-- bazel-bzl (.bzl file builtins) | +-- tilt (Tilt builtins) | +-- copybara (Copybara builtins)When resolving builtins:
- Start with the specified dialect’s builtins
- Walk up the inheritance chain
- Merge all builtins (child overrides parent on collision)
Example:
{ "dialects": { "internal-build": { "builtins": [".starlark/builtins/internal.builtins.json"], "extends": "bazel-build" } }}The internal-build dialect gets:
- Core Starlark builtins (
len,range,str, …) - Bazel BUILD builtins (
cc_library,glob, …) - Internal builtins (your custom rules)
Builtin Definition Formats
Section titled “Builtin Definition Formats”skyls supports three formats for defining builtins:
| Format | Extension | Best For |
|---|---|---|
| JSON | .builtins.json | Easy authoring, human-readable |
| Textproto | .builtins.textproto | starpls compatibility, proto validation |
| Python Stub | .builtins.pyi | Tilt LSP compatibility, familiar syntax |
See Builtin Formats Reference for complete format specifications.
Quick JSON Example
Section titled “Quick JSON Example”{ "$schema": "https://sky.dev/schemas/starlark-builtins.json", "version": 1, "name": "my-dialect", "description": "Custom Starlark dialect for my tool",
"functions": [ { "name": "my_function", "doc": "Does something useful.\n\nThis is a longer description.", "params": [ {"name": "name", "type": "string", "doc": "Resource name", "required": true}, {"name": "config", "type": "dict", "doc": "Configuration options", "default": "{}"} ], "return_type": "MyResult" } ],
"types": [ { "name": "MyResult", "doc": "Result of my_function", "fields": [ {"name": "status", "type": "string", "doc": "Success or failure"} ] } ],
"globals": [ {"name": "VERSION", "type": "string", "doc": "Tool version"} ]}Project Structure
Section titled “Project Structure”Recommended directory layout for dialect configuration:
Directoryproject/
Directory.starlark/
- config.json
Directorybuiltins/
- tilt.builtins.json
- copybara.builtins.json
- internal.builtins.json
- BUILD
- Tiltfile
- copy.bara.sky
Directorysrc/
- lib.bzl
For monorepos with nested configurations:
Directorymonorepo/
Directory.starlark/
- config.json (root config)
Directoryprojects/
Directoryfrontend/
Directory.starlark/
- config.json (overrides for frontend)
- BUILD
Directorybackend/
- BUILD
Step-by-Step Tutorial
Section titled “Step-by-Step Tutorial”-
Create the configuration directory
Terminal window mkdir -p .starlark/builtins -
Create the config file
Create
.starlark/config.json:{"$schema": "https://sky.dev/schemas/starlark-config.json","version": 1,"rules": [{"files": ["Tiltfile", "**/*.tilt.star"],"dialect": "tilt"}],"dialects": {"tilt": {"builtins": [".starlark/builtins/tilt.builtins.json"],"extends": "starlark"}}} -
Create the builtins file
Create
.starlark/builtins/tilt.builtins.json:{"$schema": "https://sky.dev/schemas/starlark-builtins.json","version": 1,"name": "tilt","functions": [{"name": "docker_build","doc": "Build a Docker image from a Dockerfile.","params": [{"name": "ref", "type": "string", "required": true, "doc": "Image reference"},{"name": "context", "type": "string", "default": "'.'", "doc": "Build context path"},{"name": "dockerfile", "type": "string", "default": "'Dockerfile'", "doc": "Dockerfile path"}],"return_type": "None"},{"name": "k8s_yaml","doc": "Deploy Kubernetes YAML manifests.","params": [{"name": "yaml", "type": "string | list[string]", "required": true, "doc": "YAML content or paths"}],"return_type": "None"}]} -
Verify the configuration
Open your Tiltfile in an editor with skyls. You should see:
- No “undefined” errors for
docker_buildandk8s_yaml - Completions for these functions
- Hover documentation
- No “undefined” errors for
-
Add more builtins as needed
When you use a new Tilt function, add it to the builtins file.
Real-World Examples
Section titled “Real-World Examples”Tilt Configuration
Section titled “Tilt Configuration”Complete configuration for Tilt development:
{ "$schema": "https://sky.dev/schemas/starlark-config.json", "version": 1, "rules": [ { "files": ["Tiltfile", "tilt_modules/**/*.star"], "dialect": "tilt" } ], "dialects": { "tilt": { "builtins": [".starlark/builtins/tilt.builtins.json"], "extends": "starlark" } }}{ "$schema": "https://sky.dev/schemas/starlark-builtins.json", "version": 1, "name": "tilt", "description": "Tilt Starlark builtins for local Kubernetes development",
"functions": [ { "name": "docker_build", "doc": "Build a Docker image from a Dockerfile.\n\nThis is the most common way to build images in Tilt.", "params": [ {"name": "ref", "type": "string", "doc": "Image reference (e.g., 'myimage:latest')", "required": true}, {"name": "context", "type": "string", "doc": "Build context path", "default": "'.'"}, {"name": "dockerfile", "type": "string", "doc": "Path to Dockerfile", "default": "'Dockerfile'"}, {"name": "build_args", "type": "dict[string, string]", "doc": "Build arguments"}, {"name": "live_update", "type": "list[LiveUpdateStep]", "doc": "Live update rules"}, {"name": "ignore", "type": "list[string]", "doc": "Patterns to ignore"} ], "return_type": "None" }, { "name": "k8s_yaml", "doc": "Deploy Kubernetes YAML manifests.", "params": [ {"name": "yaml", "type": "string | list[string] | Blob", "doc": "YAML content or file paths", "required": true}, {"name": "allow_duplicates", "type": "bool", "doc": "Allow duplicate resource names", "default": "False"} ], "return_type": "None" }, { "name": "k8s_resource", "doc": "Configure a Kubernetes resource.", "params": [ {"name": "workload", "type": "string", "doc": "Workload name", "required": true}, {"name": "port_forwards", "type": "list[string | int | PortForward]", "doc": "Port forward specifications"}, {"name": "resource_deps", "type": "list[string]", "doc": "Resource dependencies"}, {"name": "labels", "type": "list[string]", "doc": "Labels for grouping"} ], "return_type": "None" }, { "name": "local_resource", "doc": "Run a command on the host machine.", "params": [ {"name": "name", "type": "string", "doc": "Resource name", "required": true}, {"name": "cmd", "type": "string | list[string]", "doc": "Command to run", "required": true}, {"name": "serve_cmd", "type": "string | list[string]", "doc": "Long-running serve command"}, {"name": "deps", "type": "list[string]", "doc": "File dependencies"}, {"name": "resource_deps", "type": "list[string]", "doc": "Resource dependencies"} ], "return_type": "None" }, { "name": "local", "doc": "Run a local command and return output.", "params": [ {"name": "cmd", "type": "string | list[string]", "doc": "Command to run", "required": true}, {"name": "quiet", "type": "bool", "doc": "Suppress output", "default": "False"}, {"name": "echo_off", "type": "bool", "doc": "Don't echo command", "default": "False"} ], "return_type": "Blob" }, { "name": "read_file", "doc": "Read file contents as a Blob.", "params": [ {"name": "path", "type": "string", "doc": "File path", "required": true}, {"name": "default", "type": "string", "doc": "Default if file not found"} ], "return_type": "Blob" }, { "name": "helm", "doc": "Deploy a Helm chart.", "params": [ {"name": "chart", "type": "string", "doc": "Chart path or name", "required": true}, {"name": "name", "type": "string", "doc": "Release name"}, {"name": "namespace", "type": "string", "doc": "Kubernetes namespace"}, {"name": "values", "type": "list[string]", "doc": "Values files"}, {"name": "set", "type": "list[string]", "doc": "Set values on command line"} ], "return_type": "Blob" } ],
"types": [ { "name": "Blob", "doc": "Binary large object - file contents or command output." }, { "name": "LiveUpdateStep", "doc": "A step in the live update process." }, { "name": "PortForward", "doc": "Port forward specification.", "fields": [ {"name": "local_port", "type": "int", "doc": "Local port number"}, {"name": "container_port", "type": "int", "doc": "Container port number"} ] } ],
"globals": [ {"name": "os", "type": "OsModule", "doc": "Operating system utilities"}, {"name": "config", "type": "ConfigModule", "doc": "Tilt configuration settings"} ]}Copybara Configuration
Section titled “Copybara Configuration”{ "$schema": "https://sky.dev/schemas/starlark-config.json", "version": 1, "rules": [ { "files": ["*.bara.sky", "copy.bara.sky"], "dialect": "copybara" } ], "dialects": { "copybara": { "builtins": [".starlark/builtins/copybara.builtins.json"], "extends": "starlark" } }}{ "$schema": "https://sky.dev/schemas/starlark-builtins.json", "version": 1, "name": "copybara", "description": "Copybara Starlark builtins for code migration",
"functions": [ { "name": "core.workflow", "doc": "Defines a migration workflow from origin to destination.", "params": [ {"name": "name", "type": "string", "required": true, "doc": "Workflow identifier"}, {"name": "origin", "type": "origin", "required": true, "doc": "Source repository"}, {"name": "destination", "type": "destination", "required": true, "doc": "Target repository"}, {"name": "authoring", "type": "authoring", "required": true, "doc": "Author mapping"}, {"name": "transformations", "type": "list[transformation]", "default": "[]", "doc": "List of transformations"} ], "return_type": "None" }, { "name": "git.origin", "doc": "Defines a Git repository as the source of truth.", "params": [ {"name": "url", "type": "string", "required": true, "doc": "Git repository URL"}, {"name": "ref", "type": "string", "default": "'master'", "doc": "Branch, tag, or commit"} ], "return_type": "origin" }, { "name": "git.destination", "doc": "Defines a Git repository as the migration destination.", "params": [ {"name": "url", "type": "string", "required": true, "doc": "Git repository URL"}, {"name": "push", "type": "string", "default": "'master'", "doc": "Branch to push to"} ], "return_type": "destination" }, { "name": "authoring.pass_thru", "doc": "Use original commit authors.", "params": [ {"name": "default", "type": "string", "required": true, "doc": "Default author for commits without author info"} ], "return_type": "authoring" }, { "name": "core.replace", "doc": "Replace text in files.", "params": [ {"name": "before", "type": "string", "required": true, "doc": "Text to find"}, {"name": "after", "type": "string", "required": true, "doc": "Replacement text"}, {"name": "paths", "type": "glob", "default": "glob(['**'])", "doc": "Files to process"} ], "return_type": "transformation" }, { "name": "core.move", "doc": "Move or rename files.", "params": [ {"name": "before", "type": "string", "required": true, "doc": "Source path"}, {"name": "after", "type": "string", "required": true, "doc": "Destination path"} ], "return_type": "transformation" } ],
"types": [ {"name": "origin", "doc": "Source repository for a workflow"}, {"name": "destination", "doc": "Target repository for a workflow"}, {"name": "authoring", "doc": "Author mapping configuration"}, {"name": "transformation", "doc": "A code transformation step"}, {"name": "glob", "doc": "File glob pattern"} ]}Multi-Dialect Monorepo
Section titled “Multi-Dialect Monorepo”For a monorepo with Bazel, Tilt, and custom tools:
{ "$schema": "https://sky.dev/schemas/starlark-config.json", "version": 1,
"rules": [ {"files": ["Tiltfile"], "dialect": "tilt"}, {"files": ["tools/codegen/**/*.star"], "dialect": "codegen"}, {"files": ["BUILD", "BUILD.bazel", "**/BUILD", "**/BUILD.bazel"], "dialect": "bazel-build"}, {"files": ["**/*.bzl"], "dialect": "bazel-bzl"}, {"files": ["**/*.star"], "dialect": "starlark"} ],
"dialects": { "tilt": { "builtins": [".starlark/builtins/tilt.builtins.json"], "extends": "starlark" }, "codegen": { "builtins": [".starlark/builtins/codegen.builtins.json"], "extends": "starlark" }, "bazel-build": { "builtins": [".starlark/builtins/bazel-custom-rules.builtins.json"], "extends": "starlark" }, "bazel-bzl": { "builtins": [], "extends": "bazel-build" } }}Collision Handling
Section titled “Collision Handling”When multiple builtin sources define the same symbol, the resolution order is:
- Local builtins (from
dialects[name].builtins) - highest priority - Inherited builtins (from
extendschain) - Core builtins (built into skyls) - lowest priority
Within the builtins array, later files override earlier ones:
{ "builtins": [ "base.builtins.json", // Loaded first "overrides.builtins.json" // Overrides 'base' on conflict ]}Auto-Detection
Section titled “Auto-Detection”When no config file is found, skyls auto-detects the dialect based on workspace markers:
| Marker File | Detected Dialect |
|---|---|
WORKSPACE or WORKSPACE.bazel | bazel |
MODULE.bazel | bazel |
.buckconfig | buck2 |
Tiltfile | tilt |
| (none) | starlark |
Auto-detection uses built-in builtins for standard dialects. For custom dialects, create a config file.
Troubleshooting
Section titled “Troubleshooting”Config file not found
Section titled “Config file not found”Check the file location and name:
.starlark/config.json(preferred)starlark.config.json(root-level alternative)
Verify with:
ls -la .starlark/cat .starlark/config.jsonBuiltins not loading
Section titled “Builtins not loading”- Check paths are relative to the config file
- Verify JSON syntax:
Terminal window python3 -m json.tool .starlark/builtins/my.builtins.json - Check file extension is
.builtins.json,.builtins.textproto, or.builtins.pyi
Wrong dialect applied
Section titled “Wrong dialect applied”Check rule order - first match wins:
{ "rules": [ {"files": ["**/*.star"], "dialect": "starlark"}, // Matches everything! {"files": ["Tiltfile"], "dialect": "tilt"} // Never reached ]}Fix by putting specific patterns first:
{ "rules": [ {"files": ["Tiltfile"], "dialect": "tilt"}, // Specific first {"files": ["**/*.star"], "dialect": "starlark"} // General last ]}Completions not appearing
Section titled “Completions not appearing”- Ensure the function is defined in builtins
- Check the file matches a rule for the correct dialect
- Verify the config file is valid JSON
- Restart the language server
Related Documentation
Section titled “Related Documentation”- Builtin Formats Reference - Complete format specifications
- Configuration Schema - Full config file reference
- Language Server Overview - LSP features and setup