Complete guide to the Ananke command-line interfaces.
Ananke has two CLIs: the Zig CLI (primary, for constraint extraction, compilation, and generation) and the Python CLI (Maze, for direct Modal interaction). This guide covers both.
- Zig CLI (Primary)
- Python CLI (Maze)
- Common Workflows
- Constraint Format
- Tips and Best Practices
- Troubleshooting
The Zig CLI is the main interface for constraint extraction, compilation, and generation. It supports 14 languages, CLaSH domain compilation, FIM mode, and both sglang and Modal backends.
# Build from source
git clone --recurse-submodules https://github.com/rand/ananke.git
cd ananke && zig build
# Binary at ./zig-out/bin/ananke
./zig-out/bin/ananke --versionExtract constraints from source code via tree-sitter AST analysis.
ananke extract <FILE> [OPTIONS]
# Options: --output/-o, --language, --verbose/-vCompile constraints into ConstraintIR (JSON Schema, grammar, regex, token masks).
ananke compile <FILE> [OPTIONS]
# Options: --output/-o, --verbose/-vGenerate code with constraints. Supports sglang and Modal backends, FIM mode.
ananke generate <PROMPT> [OPTIONS]
# Options:
# --backend sglang|modal Backend selection (auto-detect from config)
# --constraints/-c FILE Constraint file
# --context FILE Source file for auto-extraction + rich context
# --language LANG Target language
# --output/-o FILE Output file
# --max-tokens N Max tokens (default: 4096)
# --temperature F Sampling temperature (default: 0.7)
# --model NAME Model override
# --endpoint URL Endpoint override
# --verbose/-v Verbose output
#
# FIM mode:
# --fim Enable fill-in-the-middle mode
# --prefix TEXT Code before the cursor
# --suffix TEXT Code after the cursor
# --hole-scale SCALE expression|statement|block|function|module
# --cursor-line N Cursor line number
# --cursor-column N Cursor column numberFIM example:
ananke generate --fim \
--prefix "def process(data: List[str]) -> " \
--suffix ":\n for item in data:" \
--language python \
--hole-scale expression \
--backend sglangValidate code against constraints.
ananke validate <FILE> [OPTIONS]One-shot pipeline: extract + compile + rich context → ConstraintSpec JSON.
ananke export-spec <FILE> [OPTIONS]
# Outputs the full ConstraintSpec JSON for sglang consumptionInitialize .ananke.toml configuration file.
ananke initananke version
ananke help [COMMAND]The Zig CLI reads from .ananke.toml and environment variables:
# .ananke.toml
[sglang]
endpoint = "https://rand--v1-chat-completions.modal.run"
[modal]
endpoint = "https://rand--ananke-inference-generate-api.modal.run"
[model]
name = "Qwen/Qwen2.5-Coder-32B-Instruct"Backend auto-detection: sglang if sglang.endpoint is configured, otherwise Modal.
The Python CLI wraps the Maze Rust library for direct Modal inference interaction.
cd maze && maturin developThe Ananke CLI provides command-line access to constraint-driven code generation powered by vLLM and llguidance. It allows you to:
- Generate code based on natural language prompts
- Apply constraints (JSON schemas, grammars, regex patterns) to guide generation
- Compile constraints for reuse and validation
- Check inference service health
- Manage constraint compilation cache for performance
The CLI communicates with a Modal inference endpoint to perform actual code generation and constraint compilation.
# From the Ananke project root
cd maze
maturin develop
# Verify installation
ananke --version- Python 3.8+
- Click (for CLI framework)
- Ananke Python bindings (installed via
maturin develop) - Modal account and deployment (for inference)
# Show version
ananke --version
# Show general help
ananke --help
# Show help for a specific command
ananke <command> --helpThe Ananke CLI uses environment variables for configuration. No configuration file is needed.
Set these variables to configure the CLI:
# Modal inference endpoint (required)
export ANANKE_MODAL_ENDPOINT="https://your-app.modal.run"
# Modal API key (optional, some endpoints may not require it)
export ANANKE_MODAL_API_KEY="your-api-key"
# Model name (optional, defaults to Qwen/Qwen2.5-Coder-32B-Instruct)
export ANANKE_MODEL="Qwen/Qwen2.5-Coder-32B-Instruct"The URL of your Modal inference endpoint. This must be set before using generate or compile commands.
export ANANKE_MODAL_ENDPOINT="https://your-org-ananke.modal.run"Optional API key for authentication with your Modal endpoint. Not always required, depending on endpoint configuration.
export ANANKE_MODAL_API_KEY="modal_token_abc123"The LLM model to use for generation. Defaults to Qwen/Qwen2.5-Coder-32B-Instruct.
export ANANKE_MODEL="Qwen/Qwen2.5-Coder-32B-Instruct"Create a .env.local file in your project:
#!/bin/bash
# .env.local - Source this to set up CLI environment
export ANANKE_MODAL_ENDPOINT="https://your-org-ananke.modal.run"
export ANANKE_MODAL_API_KEY="your-api-key"
export ANANKE_MODEL="Qwen/Qwen2.5-Coder-32B-Instruct"Then source it before running commands:
source .env.local
ananke configDisplay current Ananke configuration settings.
Usage:
ananke config [OPTIONS]Options:
--endpoint- Modal inference endpoint URL (from ANANKE_MODAL_ENDPOINT env var)--api-key- Modal API key (from ANANKE_MODAL_API_KEY env var)--model- Model name (from ANANKE_MODEL env var)
Description:
Shows the current configuration including the Modal endpoint, selected model, and whether an API key is configured. Useful for verifying your setup is correct.
Examples:
# Show configuration from environment variables
ananke config
# Override endpoint for this command
ananke config --endpoint https://different-endpoint.modal.runOutput:
Ananke Configuration:
Endpoint: https://your-app.modal.run
Model: Qwen/Qwen2.5-Coder-32B-Instruct
API Key: (configured)
Generate code based on a prompt, with optional constraints.
Usage:
ananke generate <PROMPT> [OPTIONS]Arguments:
<PROMPT>- Natural language description of code to generate (required, quoted string)
Options:
--max-tokens N- Maximum tokens to generate (default: 2048, range: 1-8192)--temperature F- Sampling temperature 0.0-2.0 (default: 0.7, higher = more creative)--constraints FILE- JSON file containing constraints to apply--output, -o FILE- Save output to file (default: stdout)--endpoint URL- Modal inference endpoint (overrides ANANKE_MODAL_ENDPOINT)--api-key KEY- Modal API key (overrides ANANKE_MODAL_API_KEY)--model NAME- Model name (overrides ANANKE_MODEL)
Description:
Generates code using the specified prompt and optional constraints. The generation is performed by the Modal inference service. Output includes the generated code, token count, constraint satisfaction status, and metadata.
Examples:
Simple code generation:
ananke generate "Write a Python function to calculate factorial"With output file:
ananke generate "Create a TypeScript REST API handler" -o handler.tsWith constraints:
ananke generate "Write a function to parse JSON" \
--constraints schema.json \
--max-tokens 1024Custom sampling:
# Deterministic (low temperature)
ananke generate "Implement binary search in Rust" \
--temperature 0.2 \
--max-tokens 2048 \
-o search.rs
# Creative (high temperature)
ananke generate "Generate creative variable names for a data structure" \
--temperature 1.5Saving to JSON:
ananke generate "Write a hello world program" -o output.jsonIf output file ends with .json, the full response is saved as JSON:
{
"generated_text": "...",
"finish_reason": "length|stop_sequence",
"tokens_generated": 256,
"constraint_satisfied": true,
"model": "Qwen/Qwen2.5-Coder-32B-Instruct",
"timestamp": "2024-11-26T10:30:45Z"
}If output file has a different extension, only the generated code is saved.
Output Format:
By default, output is sent to stdout with a formatted display:
================================================================================
Generated Code:
================================================================================
<generated code here>
================================================================================
Tokens: 342 | Finish: length | Constraints: satisfied
Compile constraints to llguidance format for reuse and validation.
Usage:
ananke compile <CONSTRAINTS_FILE> [OPTIONS]Arguments:
<CONSTRAINTS_FILE>- JSON file containing constraints (required)
Options:
--output, -o FILE- Write compiled constraints to file (default: stdout)--endpoint URL- Modal inference endpoint (overrides ANANKE_MODAL_ENDPOINT)--api-key KEY- Modal API key (overrides ANANKE_MODAL_API_KEY)--model NAME- Model name (overrides ANANKE_MODEL)
Description:
Compiles constraints from a JSON file to the llguidance format used by the inference engine. Useful for:
- Validating constraint syntax before use
- Caching compiled constraints for faster generation
- Inspecting the compiled output
The compilation hash can be used to identify identical constraint sets.
Examples:
Basic compilation:
ananke compile constraints.jsonSave compiled constraints:
ananke compile constraints.json -o compiled.jsonVerify constraints before use:
ananke compile my-rules.json
# If successful, no errors are shown
# If there are syntax errors, error message is displayedOutput Format:
Default (stdout):
{
"hash": "sha256_hash_of_constraints",
"compiled_at": "2024-11-26T10:30:45Z",
"schema_preview": "..."
}Check the health status of the Modal inference service.
Usage:
ananke health [OPTIONS]Options:
--endpoint URL- Modal inference endpoint (overrides ANANKE_MODAL_ENDPOINT)--api-key KEY- Modal API key (overrides ANANKE_MODAL_API_KEY)--model NAME- Model name (overrides ANANKE_MODEL)
Description:
Performs a health check against the Modal inference service to verify it is running and accessible. Returns exit code 0 if healthy, 1 if unhealthy.
Examples:
Check service health:
ananke healthOutput on success:
Status: HEALTHY
Endpoint: https://your-app.modal.run
Model: Qwen/Qwen2.5-Coder-32B-Instruct
Output on failure:
Status: UNHEALTHY
Using in scripts:
if ananke health; then
echo "Service is ready, starting generation..."
ananke generate "Create a user model"
else
echo "Service is down, aborting"
exit 1
fiView or clear the constraint compilation cache.
Usage:
ananke cache [OPTIONS]Options:
--clear- Clear the cache (boolean flag)--endpoint URL- Modal inference endpoint (overrides ANANKE_MODAL_ENDPOINT)--api-key KEY- Modal API key (overrides ANANKE_MODAL_API_KEY)--model NAME- Model name (overrides ANANKE_MODEL)
Description:
Shows statistics about the constraint compilation cache, or clears it if --clear is specified. The cache stores compiled constraints for faster subsequent compilations.
Examples:
View cache statistics:
ananke cacheOutput:
Cache Statistics:
Size: 42 entries
Limit: 1000 entries
Usage: 4.2%
Clear the cache:
ananke cache --clearOutput:
Cache cleared successfully
When to clear cache:
- After updating constraint definitions
- When cache hits the limit
- When troubleshooting constraint-related issues
Generate code with just a prompt:
# Set up environment
export ANANKE_MODAL_ENDPOINT="https://your-app.modal.run"
# Generate simple function
ananke generate "Create a function that reverses a string in Python"
# Save to file
ananke generate "Write a REST API handler" -o handler.pyDefine constraints in a JSON file and use them to guide generation:
constraints.json:
{
"name": "api_constraints",
"json_schema": {
"type": "object",
"properties": {
"method": {"enum": ["GET", "POST", "PUT", "DELETE"]},
"status_code": {"type": "integer"}
},
"required": ["method", "status_code"]
}
}Generate with constraints:
ananke generate "Create an API handler" --constraints constraints.json -o api.pyMultiple constraints:
[
{
"name": "type_safety",
"json_schema": {"type": "object", "additionalProperties": false}
},
{
"name": "naming_conventions",
"regex_patterns": ["^[a-z_][a-z0-9_]*$"]
}
]For repeated generation with the same constraints:
# Compile once and cache
ananke compile my-constraints.json -o compiled.json
# Use cached constraints multiple times
ananke generate "Create user handler" --constraints compiled.json
ananke generate "Create product handler" --constraints compiled.json
ananke generate "Create order handler" --constraints compiled.json
# Check cache statistics
ananke cache
# Clear cache if needed
ananke cache --clearGenerate multiple pieces of code in sequence:
#!/bin/bash
set -e
export ANANKE_MODAL_ENDPOINT="https://your-app.modal.run"
# Create output directory
mkdir -p generated
# Generate multiple related files
ananke generate "Create user model class" -o generated/user.py
ananke generate "Create user repository interface" -o generated/user_repo.py
ananke generate "Create user service" -o generated/user_service.py
echo "Generated files:"
ls -la generated/Integrate code generation into your CI/CD pipeline:
.github/workflows/generate.yml:
name: Generate Code
on: [push]
jobs:
generate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install Ananke
run: |
cd maze
pip install maturin
maturin develop
- name: Check service health
env:
ANANKE_MODAL_ENDPOINT: ${{ secrets.ANANKE_MODAL_ENDPOINT }}
ANANKE_MODAL_API_KEY: ${{ secrets.ANANKE_MODAL_API_KEY }}
run: ananke health
- name: Generate code
env:
ANANKE_MODAL_ENDPOINT: ${{ secrets.ANANKE_MODAL_ENDPOINT }}
ANANKE_MODAL_API_KEY: ${{ secrets.ANANKE_MODAL_API_KEY }}
run: |
ananke generate "Create user handler" -o src/handlers/user.py
ananke generate "Create product handler" -o src/handlers/product.py
- name: Commit generated files
run: |
git config user.name "Ananke Bot"
git config user.email "bot@ananke.dev"
git add src/handlers/
git commit -m "chore: regenerated code with Ananke" || true
git pushConstraints guide code generation to ensure output follows specific patterns, schemas, or rules.
Define what the generated output should match:
{
"name": "json_output",
"json_schema": {
"type": "object",
"properties": {
"id": {"type": "integer"},
"name": {"type": "string"},
"email": {"type": "string", "format": "email"},
"status": {"enum": ["active", "inactive"]}
},
"required": ["id", "name", "email"]
}
}Specify BNF-style grammar:
{
"name": "function_signature",
"grammar": "def <name>(<params>) -> <return_type>: ..."
}Match output against regular expressions:
{
"name": "naming_convention",
"regex_patterns": [
"^def [a-z_][a-z0-9_]*.*:",
"^class [A-Z][a-zA-Z0-9_]*.*:"
]
}Combine different constraint types:
[
{
"name": "schema_validation",
"json_schema": {
"type": "object",
"properties": {"method": {"type": "string"}},
"required": ["method"]
}
},
{
"name": "naming_patterns",
"regex_patterns": ["^[a-z_][a-z0-9_]*"]
}
]Use specific, detailed prompts:
# Good - specific and detailed
ananke generate "Create a Python async function to fetch user data from a REST API with retry logic and timeout handling"
# Less effective - vague
ananke generate "Create a function"Adjust temperature for task type:
# Deterministic tasks (parsing, calculation)
ananke generate "Parse CSV data to JSON" --temperature 0.2
# Creative tasks (naming, design)
ananke generate "Generate creative class names for a game" --temperature 1.2
# Balanced (default for most tasks)
ananke generate "Write a REST API handler" --temperature 0.7Use appropriate token limits:
# Small functions
ananke generate "Write a hash function" --max-tokens 256
# Medium implementations
ananke generate "Implement a data parser" --max-tokens 1024
# Complex modules
ananke generate "Build a caching layer" --max-tokens 4096Start with broad constraints, refine iteratively:
# First pass - basic structure
ananke compile constraints.json
# Inspect output, refine constraints.json
# Second pass - refined
ananke compile constraints.jsonValidate constraints before heavy use:
# Test compilation
ananke compile constraints.json
# Generate a small test
ananke generate "Small test prompt" --constraints constraints.json --max-tokens 100
# Then use for full generation
ananke generate "Full prompt" --constraints constraints.jsonReuse compiled constraints:
# Compile once
ananke compile constraints.json -o cached.json
# Reuse many times (faster than recompiling)
for i in {1..10}; do
ananke generate "Prompt $i" --constraints cached.json
doneCache frequently used constraint sets:
# Keep compiled versions in version control
git add cached_constraints/
git commit -m "Add compiled constraint cache"
# Reuse in CI/CD
ananke generate "Prompt" --constraints cached_constraints/api_rules.jsonMonitor cache usage:
# Check cache size
ananke cache
# Clear if needed
ananke cache --clearCheck health before batch operations:
#!/bin/bash
set -e
if ! ananke health; then
echo "Service unavailable, aborting batch"
exit 1
fi
# Proceed with generation
for file in prompts/*.txt; do
ananke generate "$(cat $file)" -o "output/$(basename $file).py"
doneANANKE_MODAL_ENDPOINT not set
Error: Ananke module not installed or endpoint not configured.
Solution: Set the environment variable before running commands:
export ANANKE_MODAL_ENDPOINT="https://your-app.modal.run"
ananke config # Verify it's set
ananke generate "Your prompt"Connection refused
Error: Generation failed: Connection refused
Solution: Check your endpoint URL is correct and the service is running:
ananke health # Check if service is responsiveVerify the endpoint URL:
ananke config --endpoint https://your-app.modal.runConstraint compilation fails
Error: Compilation failed: Invalid constraint format
Solution: Validate your constraint file format:
# Check file is valid JSON
jq . constraints.json
# Look for required fields
cat constraints.json | jq 'keys'Out of memory during generation
Error: Generation failed: Out of memory
Solution: Reduce --max-tokens:
# Current (too large)
ananke generate "Prompt" --max-tokens 8192
# Reduced
ananke generate "Prompt" --max-tokens 2048Timeout during generation
Error: Generation failed: Request timeout
Solution: Check service health and try with a shorter prompt:
ananke health
# Simpler prompt might be faster
ananke generate "Small focused prompt" --max-tokens 1024Verify configuration:
ananke config
# Output should show your endpoint and modelTest with minimal input:
# Simplest possible generation
ananke generate "Hello" --max-tokens 10Check service health:
ananke health
# Should show HEALTHY statusInspect constraint format:
# Validate JSON
jq . constraints.json
# Try compilation
ananke compile constraints.jsonEnable verbose output (if available):
# Some commands support verbose flags
ananke generate "Prompt" -v- Command help:
ananke <command> --help - General help:
ananke --help - Version:
ananke --version - Service status:
ananke health