Skip to main content

Getting Started with Sindr

Sindr is a modern replacement for make that allows you to create CLI tools using Starlark scripts. It provides a batteries-included set of functions for common development tasks.

Before getting started, make sure you have installed Sindr on your system.

Quick Start​

  1. Create a sindr.star file in your project root:
# Define CLI metadata
cli(
name = "my-project",
usage = "My awesome project CLI"
)

# Define a build command
def build_action(ctx):
print("Building project...")
result = shell('go build .')
if result.success:
print("Build completed successfully!")
else:
print("Build failed:", result.stderr)

command(
name = "build",
help = "Build the project",
action = build_action
)
  1. Run your command:
sindr build

Core Concepts​

Commands​

Define commands using the command() function:

def my_action(ctx):
print("Hello from", ctx.args.name)

command(
name = "greet",
help = "Greet someone",
action = my_action,
args = ["name"]
)

Shell Execution​

Execute shell commands with the shell() function:

def deploy(ctx):
result = shell('docker build -t myapp .')
if result.success:
shell('docker push myapp')
print("Deployment successful!")
else:
print("Build failed:", result.stderr)

Environment Variables​

Load environment variables from .env files:

def setup(ctx):
dotenv(['.env', '.env.local'])
shell('echo "Using database: $DATABASE_URL"')

Caching​

Cache expensive operations:

def expensive_build(ctx):
c = cache()

def build_task():
shell('npm run build')
print('Build completed')

# Only rebuild if version changed
if c.with_version(build_task, name='build', version='1.2.3'):
print('Build executed')
else:
print('Build skipped - version unchanged')

Available Functions​

FunctionDescription
cli()Configure CLI metadata
command()Define commands
sub_command()Define nested subcommands
shell()Execute shell commands
exec()Execute with specific interpreter
dotenv()Load environment variables
cache()Create cache instance
string()Render templates
start()Run functions concurrently
wait()Wait for async operations

Examples​

Building and Testing​

def test_action(ctx):
result = shell('go test ./...')
if not result.success:
print("Tests failed!")
return

shell('go build -o myapp .')
print("Build and test completed successfully!")

command(name="test", action=test_action, help="Run tests and build")

Multi-stage Deployment​

sub_command(
path = ["deploy", "staging"],
help = "Deploy to staging environment",
action = lambda ctx: deploy_to_env("staging")
)

sub_command(
path = ["deploy", "production"],
help = "Deploy to production environment",
action = lambda ctx: deploy_to_env("production")
)

def deploy_to_env(env):
dotenv([f'.env.{env}'])
shell(f'docker build -t myapp:{env} .')
shell(f'docker push myapp:{env}')

Next Steps​

  • Check the project repository for more examples and documentation
  • Explore the available functions and their parameters
  • Create your own custom commands for your workflow