Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

CLI Reference

This reference covers all Turnkey CLI commands.

tk - Buck2 Wrapper

tk is the primary Turnkey CLI. It wraps Buck2 with automatic dependency synchronization.

Overview

When using Buck2 with Nix-managed dependencies, certain files must be regenerated when source files change. tk solves this by automatically running sync operations before buck2 commands that read the build graph.

Quick Start

# Use tk just like buck2 - it syncs automatically
tk build //some:target     # syncs first, then builds
tk test //some:target      # syncs first, then tests
tk run //some:target       # syncs first, then runs

# Explicit sync operations
tk sync                    # manually sync all stale files
tk check                   # check if files are stale (for CI)

# Skip sync when needed
tk --no-sync build //...   # skip sync, run buck2 directly

Command Reference

tk build/run/test/... (Buck2 passthrough)

Most tk commands are passed through to Buck2. Commands that read the build graph automatically sync first:

Sync-first commands (sync before running):

  • build - Build targets
  • run - Run a target
  • test - Run tests
  • query - Query the build graph
  • cquery - Configured query
  • uquery - Unconfigured query
  • targets - List targets
  • audit - Audit the build
  • bxl - Run BXL scripts

Pass-through commands (no sync):

  • clean - Clean build artifacts
  • kill - Kill Buck2 daemon
  • killall - Kill all Buck2 processes
  • status - Show daemon status
  • log - View build logs
  • rage - Generate debug report
  • help - Show help
  • docs - Open documentation
  • init - Initialize a project

Unknown commands default to syncing first (safe default).

tk sync

Explicitly synchronize all stale files.

tk sync              # sync stale files
tk sync --verbose    # show what's being synced
tk sync --dry-run    # show what would be synced without doing it

Exit codes:

  • 0 - Success (files synced or nothing to sync)
  • 1 - Sync failed

tk check

Check if any files are stale without regenerating them. Useful for CI validation.

tk check             # check staleness
tk check --verbose   # show detailed status

Exit codes:

  • 0 - All files up-to-date
  • 1 - Files are stale (run tk sync to fix)

Example CI usage:

- name: Check files in sync
  run: tk check

tk completion

Generate shell completion scripts.

tk completion bash    # output bash completion script
tk completion zsh     # output zsh completion script
tk completion fish    # output fish completion script

Enable completions:

# Bash (add to ~/.bashrc)
eval "$(tk completion bash)"

# Zsh (add to ~/.zshrc)
eval "$(tk completion zsh)"

# Fish (run once)
tk completion fish > ~/.config/fish/completions/tk.fish

tk rules

Manage rules.star files that define Buck2 build targets from source files. This command automatically detects imports from source files and updates the deps list in rules.star.

tk rules check              # Check if rules.star files need updates
tk rules sync               # Update rules.star files with detected dependencies
tk rules help               # Show help

Options:

FlagDescription
--all, -aProcess all files (skip staleness detection)
--force, -fSame as --all
--verbose, -vShow detailed output including skipped files
--quiet, -qSuppress output
--dry-run, -nShow what would be changed without writing

Staleness Detection:

By default, only files where source files are newer than rules.star are processed. Use --all or --force to check/sync all files.

Examples:

tk rules check                    # Check stale rules.star files
tk rules check --all              # Check all rules.star files
tk rules sync                     # Update stale rules.star files
tk rules sync --all               # Force update all files
tk rules sync src/cmd/tk          # Sync specific directory
tk rules sync --dry-run           # Preview changes without writing

Preserving Manual Dependencies:

If you have manual dependencies that shouldn't be auto-detected, use preservation markers in your rules.star:

# turnkey:preserve-start
    "//some/manual:dep",
# turnkey:preserve-end

Dependencies within these markers are preserved during sync.

tk Flags

Flags must come before the subcommand:

FlagDescription
--no-syncSkip sync, run Buck2 directly
--no-localSkip local target overrides from .turnkey/local.toml
--verbose, -vShow what tk is doing
--dry-run, -nShow what would be synced without doing it
--quiet, -qSuppress non-error output
--help, -hShow help

Examples:

tk --no-sync build //...     # skip sync
tk --no-local run //target   # skip local overrides
tk --verbose sync            # verbose sync
tk -v -n sync                # dry-run with verbose output

Configuration

Sync Configuration File

tk reads staleness rules from .turnkey/sync.toml. This file is automatically generated from your Nix configuration.

When you configure dependency files in your flake.nix:

  • goDepsFile generates a Go deps rule
  • rustDepsFile generates a Rust deps rule
  • pythonDepsFile generates a Python deps rule

Example generated sync.toml:

[[deps]]
name = "go"
sources = ["go.mod", "go.sum"]
target = "go-deps.toml"
generator = ["godeps-gen", "--go-mod", "go.mod", "--go-sum", "go.sum", "--prefetch"]

[[deps]]
name = "rust"
sources = ["Cargo.toml", "Cargo.lock"]
target = "rust-deps.toml"
generator = ["rustdeps-gen", "--cargo-lock", "Cargo.lock"]

Each [[deps]] entry defines:

  • name - Human-readable name for this rule
  • sources - Files that trigger regeneration when modified
  • target - The generated file
  • generator - Command to regenerate the target

Local Target Overrides

tk supports per-developer local overrides via .turnkey/local.toml. This file is not committed to git, allowing each developer to customize target arguments for their local environment.

Use cases:

  • Different network addresses for local development
  • Debug flags for specific targets
  • Custom ports or configuration

Example .turnkey/local.toml:

# Override args for tk run
[run."//docs/user-manual"]
args = ["-n", "192.168.1.100"]

# Override args for tk build
[build."//src/cmd/server:server"]
args = ["--config=debug"]

# Pattern matching with "..."
[test."//src/..."]
args = ["--verbose", "--timeout=60s"]

How it works:

When you run a command that matches a configured target:

tk run //docs/user-manual
# Becomes: buck2 run //docs/user-manual -- -n 192.168.1.100

The args are injected after --, which passes them to the target binary.

Pattern matching:

Patterns ending with ... match any target with that prefix:

  • //src/... matches //src:foo, //src/pkg:bar, //src/cmd/tool:main
  • //... matches any target

Disable for a single command:

tk --no-local run //docs/user-manual   # skips local.toml

Verbose output:

tk --verbose run //docs/user-manual
# Output: tk: applying local override for run //docs/user-manual: [-n 192.168.1.100]

Shell Integration

buck2 alias to tk:

# In devenv shell, buck2 is aliased to tk
buck2 build //...   # actually runs: tk build //...

Disable with:

TURNKEY_NO_ALIAS=1 buck2 build //...   # uses raw buck2

tw - Native Tool Wrapper

tw wraps native language tools (go, cargo, uv) to keep dependency files in sync when using standard workflows.

The Problem

When you run go get github.com/foo/bar, Go updates go.mod and go.sum. But Buck2 needs go-deps.toml to know about the new dependency. Without auto-sync, you'd need to manually regenerate it.

The Solution

Turnkey transparently wraps go, cargo, and uv so that dependency sync happens automatically:

go get github.com/foo/bar  # Just works - go-deps.toml is auto-updated

How It Works

User runs: go get github.com/foo/bar
                    │
                    ▼
Shell wrapper (provides 'go' binary)
• Sets TURNKEY_REAL_GO to actual go binary path
• Calls: tw go get github.com/foo/bar
                    │
                    ▼
tw (turnkey wrapper)
1. Loads .turnkey/sync.toml configuration
2. Finds wrapper rule for 'go'
3. Checks if 'get' is a mutating subcommand → yes
4. Captures SHA256 hashes of go.mod, go.sum
5. Runs the real 'go get' command
6. Compares hashes - detects changes
7. Runs godeps-gen to regenerate go-deps.toml

Supported Tools

ToolMutating CommandsWatch FilesDeps Target
goget, modgo.mod, go.sumgo-deps.toml
cargoadd, remove, updateCargo.toml, Cargo.lockrust-deps.toml
uvadd, remove, lock, syncpyproject.toml, uv.lockpython-deps.toml

Escape Hatches

Bypass for a Single Command

TURNKEY_NO_WRAP=1 go get github.com/foo/bar

This runs the real go directly, skipping tw entirely.

Disable Sync for a Command

tw --no-sync go get github.com/foo/bar

This runs through tw but skips the sync step even if files change.

Verbose Output

tw -v go get github.com/foo/bar

Shows what tw is doing:

tw: capturing state of [go.mod go.sum]
tw: detected changes in [go.mod go.sum], running sync
Syncing go-deps.toml...
  Running: godeps-gen --go-mod go.mod --go-sum go.sum --prefetch
  Regenerated go-deps.toml

Non-Mutating Commands

Commands not in mutating_subcommands pass through without any overhead:

go build ./...    # No snapshot, no sync check - just runs go build
go version        # Direct passthrough

godeps-gen

Generate go-deps.toml from go.mod and go.sum.

Usage

godeps-gen [OPTIONS]

Options

OptionDescription
--go-mod PATHPath to go.mod file (default: go.mod)
--go-sum PATHPath to go.sum file (default: go.sum)
--prefetchFetch Nix hashes using nix-prefetch-github
--indirectInclude indirect dependencies (default: true)
-o, --output PATHOutput file (default: stdout)

Examples

# Generate with prefetched hashes
godeps-gen --prefetch -o go-deps.toml

# Use custom paths
godeps-gen --go-mod src/go.mod --go-sum src/go.sum -o go-deps.toml

# Quick check without fetching (placeholder hashes)
godeps-gen --no-prefetch

rustdeps-gen

Generate rust-deps.toml from Cargo.lock.

Usage

rustdeps-gen [OPTIONS]

Options

OptionDescription
--cargo-lock PATHPath to Cargo.lock file (default: Cargo.lock)
--no-prefetchSkip prefetching (produces incorrect hashes)
-o, --output PATHOutput file (default: stdout)

Examples

# Generate from default Cargo.lock
rustdeps-gen -o rust-deps.toml

# Use custom path
rustdeps-gen --cargo-lock rust/Cargo.lock -o rust-deps.toml

pydeps-gen

Generate python-deps.toml from Python dependency files.

Usage

pydeps-gen [OPTIONS]

Options

OptionDescription
--lock PATHPath to pylock.toml (PEP 751 lock file) - RECOMMENDED
--pyproject PATHPath to pyproject.toml
--requirements PATHPath to requirements.txt
-o, --output PATHOutput file (default: stdout)
--no-prefetchSkip prefetching (produces placeholder hashes)
--include-devInclude dev dependencies

Input Formats

FormatFlagReproducibilityNotes
pylock.toml (PEP 751)--lockBestExact versions and URLs
pyproject.toml--pyprojectVariesUses latest matching versions
requirements.txt--requirementsVariesPin versions with ==
# 1. Generate lock file from pyproject.toml
uv lock

# 2. Export to PEP 751 format
uv export --format pylock.toml -o pylock.toml

# 3. Generate python-deps.toml with Nix hashes
pydeps-gen --lock pylock.toml -o python-deps.toml

Examples

# From PEP 751 lock file (best for reproducibility)
pydeps-gen --lock pylock.toml -o python-deps.toml

# From pyproject.toml (resolves to latest matching versions)
pydeps-gen --pyproject pyproject.toml -o python-deps.toml

# From requirements.txt
pydeps-gen --requirements requirements.txt -o python-deps.toml

# Include dev dependencies
pydeps-gen --lock pylock.toml --include-dev -o python-deps.toml

Troubleshooting

"tk: .buckconfig not found"

tk looks for .buckconfig to find the project root. Make sure you're in a Buck2 project directory.

"tk: failed to load sync config"

The .turnkey/sync.toml file is missing or invalid. Ensure you're in a Turnkey project with proper configuration.

"tk: sync failed: generator command failed"

The generator command failed. Check that:

  • The generator command is correct
  • Required tools are in PATH
  • Source files exist

Sync is slow

If sync takes a long time:

  • Use --prefetch with godeps-gen to cache downloads
  • Check if generators are doing unnecessary work

Bypass tk

If you need to use raw Buck2:

# Option 1: --no-sync flag
tk --no-sync build //...

# Option 2: TURNKEY_NO_ALIAS environment variable
TURNKEY_NO_ALIAS=1 buck2 build //...