Constraint-driven code generation that transforms AI from probabilistic guessing into controlled search through valid program spaces.
If you can't make it explicit, you can't control it. If you can't control it, you can't trust it. If you can't trust it, you can't ship it.
Ananke enforces constraints at the token level during code generation, ensuring outputs always satisfy specified requirements. No more hoping the model will follow your patterns. You define the rules, Ananke enforces them.
Before using Ananke, ensure you have the following installed:
-
Zig 0.15.0 or later - Download from ziglang.org
zig version # Should show 0.15.0 or later -
tree-sitter - Required for AST-based constraint extraction
# macOS (Homebrew) brew install tree-sitter # Ubuntu/Debian sudo apt-get install libtree-sitter-dev # Arch Linux sudo pacman -S tree-sitter # Verify installation tree-sitter --version
-
Anthropic API Key - For semantic constraint analysis (Claude integration)
export ANTHROPIC_API_KEY='your-key-here'
Get your key at console.anthropic.com
-
OpenAI API Key - Alternative LLM provider
export OPENAI_API_KEY='your-key-here'
-
Git - For cloning the repository
- OS: macOS, Linux (Ubuntu 20.04+, Debian 11+, Arch), Windows WSL2
- Memory: 2GB RAM minimum, 4GB recommended
- Disk: 500MB for installation + dependencies
Get started with constraint extraction and analysis in 10 minutes:
# Clone and build
git clone --recurse-submodules https://github.com/rand/ananke.git
cd ananke
zig build
# Run your first constraint extraction
cd examples/01-simple-extraction
zig build run
# Output: Extracted constraints from TypeScript code
# - Function signatures, types, security patterns
# - All under 100ms, no external services neededWant more? See the complete quickstart guide for:
- Semantic analysis with Claude
- Combining multiple constraint sources
- Understanding the full pipeline
- Troubleshooting tips
Extract constraints from code (no external services needed):
cd examples/01-simple-extraction && zig build run
# Finds: function signatures, types, security patternsAdd semantic analysis (optional, requires Claude API):
export ANTHROPIC_API_KEY='your-key'
cd examples/02-claude-analysis && zig build run
# Finds: business rules, implicit constraints, intentCombine all approaches (production-ready pattern):
cd examples/05-mixed-mode && zig build run
# Merges: extracted + JSON config + Ariadne DSLRead more: QUICKSTART.md | docs/USER_GUIDE.md
Ananke is a two-layer system for intelligent, constrained code generation:
-
Analysis Layer (Clew, Braid, Ariadne): Lightweight Zig binaries that extract constraints from code, tests, and documentation. Can leverage managed APIs (Claude, OpenAI) for semantic understanding.
-
Generation Layer (Maze + vLLM/SGLang + llguidance): GPU-powered constrained generation that applies constraints at the token level. Requires inference server control that managed APIs cannot provide.
This hybrid approach lets you use Claude for what it's great at (understanding code semantics, resolving conflicts) while maintaining token-level control where you need it (generation).
Source Code, Tests, Docs
↓
┌──────────────────┐
│ Clew │ ← Pure Zig structural parsers
│ (Extraction) │ Optional: Claude API for semantic analysis
└────────┬─────────┘ Runs locally (no GPU needed)
↓ Extracted Constraints
┌──────────────────┐
│ Braid │ ← Pure Zig constraint compiler
│ (Compilation) │ - Regex extraction
│ 4 components: │ - JSON Schema generation
│ ✓ Regex matcher │ - Grammar building
│ ✓ Schema build │ - Token mask compilation
│ ✓ Mask creator │ - Caching with clone-on-get
│ ✓ Merger │
└────────┬─────────┘
↓ ConstraintIR
┌──────────────────┐
│ Maze │ ← Rust orchestration layer
│ (Orchestration) │ HTTP API coordination
└────────┬─────────┘
↓ API calls
┌──────────────────────────────┐
│ Modal/vLLM Inference Service │ ← GPU-powered (controlled via llguidance)
│ - Qwen2.5-Coder-32B-Instruct │ Token-level constraint enforcement
│ - ~50μs per token overhead │ Scale-to-zero architecture
└──────────────────────────────┘
↓
Generated Code (Constraint-Validated)
Use for understanding and extracting constraints:
- Clew: Semantic code analysis, pattern recognition from source
- Braid: Conflict resolution between constraints
- Trade-off: Fast, no GPU, per-API-call cost
Examples:
# Understanding test intent to infer constraints
constraints = await clew.extract_from_tests(
test_code,
use_claude=True # Semantic understanding
)
# Resolving conflicting constraints intelligently
resolved = await braid.compile(
constraints,
optimize_with_llm=True # Claude suggests resolution
)Use for token-level controlled generation:
- Maze: Constrained code generation on open models
- Requirement: vLLM + llguidance on GPU infrastructure
- Trade-off: Full control, token-level masking, ~$0.01-0.05/request
Why not Claude here? You need access to raw logits to apply token-by-token constraints. Managed APIs don't expose this level of control.
# This MUST use constrained inference, not Claude
result = await maze.generate(
intent="Add authentication middleware",
constraints=compiled_ir,
# Only works with controlled inference server
)- Zig 0.15.0+ (for building from source)
- Rust 1.70+ (for Maze library)
- For generation: GPU infrastructure (Modal, RunPod, or local)
- Optional: Claude API key for analysis enhancements
git clone https://github.com/rand/ananke.git
cd ananke
# Build all components (Zig + Rust)
zig build
# Build Rust Maze library
cd maze && cargo build --release && cd ..
# Run tests
zig build test
cd maze && cargo test && cd ..
# Build examples
zig build examplesZig Library - Add to your build.zig.zon:
.ananke = .{
.url = "https://github.com/rand/ananke/archive/refs/tags/v0.1.0.tar.gz",
.hash = "12207...",
},Rust Library (Maze) - Add to your Cargo.toml:
[dependencies]
maze = { git = "https://github.com/rand/ananke.git", tag = "v0.1.0" }# Check Ananke CLI
ananke --version
# Test constraint extraction
ananke extract examples/sample.ts
# Check available commands
ananke helpAnanke can use Claude for enhanced semantic analysis of constraints. This is completely optional - Ananke works great with just its built-in structural parsers.
-
Get an API key from Anthropic Console
-
Set the environment variable:
export ANTHROPIC_API_KEY='sk-ant-api...'- Or configure in
.ananke.toml:
[claude]
# API key can be set here or via ANTHROPIC_API_KEY env var
# api_key = "sk-ant-api..." # Not recommended for security
model = "claude-sonnet-4-5-20250929"
enabled = true# Extract with semantic analysis
ananke extract src/main.ts --use-claude
# Claude will analyze for:
# - Business logic constraints
# - Implicit patterns
# - Security requirements
# - Architectural decisionsIf Claude is not configured or unavailable, Ananke automatically falls back to structural analysis only. Your workflow won't be interrupted.
Create .ananke.toml in your project root:
[claude]
# Claude API for semantic analysis (optional)
# api_key sourced from ANTHROPIC_API_KEY env var
model = "claude-sonnet-4-5-20250929"
enabled = true # Auto-enabled if API key present
[modal]
# For code generation (optional)
endpoint = "https://your-app.modal.run"
# api_key sourced from ANANKE_MODAL_API_KEY env var
[defaults]
language = "typescript"
max_tokens = 4096
temperature = 0.7
confidence_threshold = 0.5
output_format = "pretty"
[extract]
use_claude = false # Enable globally or per-command
patterns = ["all"]
[compile]
priority = "medium"
formats = ["json-schema"]| Variable | Description | Required |
|---|---|---|
ANTHROPIC_API_KEY |
Claude API key for semantic analysis | No |
ANANKE_MODAL_API_KEY |
Modal API key for generation | No |
ANANKE_MODAL_ENDPOINT |
Modal endpoint URL | No |
ANANKE_LANGUAGE |
Default source language | No |
ANANKE_CLAUDE_ENDPOINT |
Custom Claude API endpoint | No |
All configuration is optional. Ananke works with zero configuration using its built-in parsers.
Extract constraints from your codebase, no external services:
const ananke = @import("ananke");
const std = @import("std");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
// Initialize Clew (no external services needed)
var clew = try ananke.Clew.init(allocator, null); // null = no Claude API
defer clew.deinit();
// Extract constraints from source code (pure Zig parsers)
const source = @embedFile("handlers/auth.ts");
const constraints = try clew.extractFromCode(source, null);
defer allocator.free(constraints);
// Compile constraints locally
var braid = try ananke.Braid.init(allocator);
defer braid.deinit();
const compiled = try braid.compile(constraints);
std.debug.print("Found {d} constraints\n", .{constraints.len});
// Output: Type safety, security patterns, architectural constraints
// All extracted and compiled locally in <100ms
}Use Claude for semantic understanding while keeping generation local (or deferred):
ananke = Ananke(
claude_api_key=os.getenv("ANTHROPIC_API_KEY"),
# No modal endpoint yet - just analysis
)
# Claude helps understand complex test requirements
constraints = await ananke.extract_from_tests(
test_code,
use_claude=True # "What constraints do these tests imply?"
)
# Claude can help resolve conflicts
compiled = await ananke.compile(
constraints,
optimize_with_llm=True # "How should these constraints be prioritized?"
)End-to-end with both Claude and constrained generation:
ananke = Ananke(
claude_api_key=os.getenv("ANTHROPIC_API_KEY"),
modal_endpoint="https://<YOUR_MODAL_WORKSPACE>--ananke-inference-generate-api.modal.run",
model="Qwen/Qwen2.5-Coder-32B-Instruct",
)
# 1. Extract constraints (optionally with Claude)
constraints = await ananke.extract_from_code(
"./src",
use_llm=True # Claude: "What patterns does this code follow?"
)
# 2. Compile (optionally with Claude for optimization)
compiled = await ananke.compile(
constraints,
optimize_with_llm=True # Claude: "How should these be ordered?"
)
# 3. Generate with constraints (requires vLLM + llguidance)
result = await ananke.generate(
intent="Add JWT validation to the auth handler",
constraints=compiled,
temperature=0.7,
max_tokens=500,
)
print(result.code)
# Output: Type-safe, validated code that follows all constraintsOptionally use our constraint DSL instead of JSON:
constraint secure_api {
requires: authentication;
validates: input_schema;
forbid: ["eval", "exec"];
max_complexity: 10;
temporal: {
timeout: 30s;
retry_policy: exponential_backoff;
}
}
Compile to ConstraintIR:
const compiler = AriadneCompiler{ .llm_client = null };
const ir = try compiler.compile(@embedFile("secure_api.ariadne"));# Extract constraints from codebase
ananke extract ./src --use-claude -o constraints.json
# Compile constraints
ananke compile constraints.json -o compiled.cir
# Generate code with constraints
ananke generate "implement user signup endpoint" \
--constraints compiled.cir \
--inference-url https://<YOUR_MODAL_WORKSPACE>--ananke-inference-generate-api.modal.run \
--temperature 0.7
# Validate generated code
ananke validate output.py compiled.circonst ananke = @import("ananke");
const std = @import("std");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
// Initialize constraint engine
var clew = try ananke.Clew.init(allocator, null); // null = no Claude
defer clew.deinit();
// Extract from source code
const source = @embedFile("handler.py");
const constraints = try clew.extractFromCode(source);
defer allocator.free(constraints);
// Compile constraints
var braid = try ananke.Braid.init(allocator);
const compiled = try braid.compile(constraints);
std.debug.print("Extracted {d} constraints\n", .{constraints.len});
}import asyncio
from ananke import Clew, Braid, Maze
async def main():
# Initialize
clew = Clew(claude_api_key=None)
braid = Braid()
maze = Maze(
endpoint="https://<YOUR_MODAL_WORKSPACE>--ananke-inference-generate-api.modal.run",
model="Qwen/Qwen2.5-Coder-32B-Instruct"
)
# Extract constraints
with open("auth.py") as f:
source = f.read()
constraints = await clew.extract(source)
# Compile
compiled = await braid.compile(constraints)
# Generate
result = await maze.generate(
intent="Add rate limiting",
constraints=compiled,
max_tokens=200
)
print(f"Generated:\n{result.code}")
print(f"Validation: {result.constraint_violations} violations")
if __name__ == "__main__":
asyncio.run(main())# Build everything (default)
zig build
# Build with optimizations (recommended)
zig build -Doptimize=ReleaseFast
# Run all tests
zig build test
# Run specific test suite
zig build test -- src/clew/tests.zig
# Build benchmarks
zig build bench-phase8bananke/
├── src/
│ ├── root.zig # Main module export
│ ├── clew/ # Constraint extraction
│ │ ├── clew.zig
│ │ ├── extractor.zig
│ │ └── tree_sitter.zig
│ ├── braid/ # Constraint compilation
│ │ ├── braid.zig
│ │ ├── graph.zig
│ │ └── compiler.zig
│ ├── ariadne/ # DSL compiler
│ │ ├── ariadne.zig
│ │ └── parser.zig
│ ├── maze/ # Orchestration (Rust)
│ │ └── lib.rs
│ └── types/ # Shared types
│ ├── constraint.zig
│ └── constraint_ir.zig
├── docs/
│ ├── ARCHITECTURE.md # System design
│ └── IMPLEMENTATION_PLAN.md # Development roadmap
├── beads/
│ └── implementation-phases.bead # Task tracking
├── examples/
│ ├── 01-simple-extraction/ # No external services
│ ├── 02-claude-analysis/ # Claude for analysis
│ └── 04-full-pipeline/ # Full end-to-end
└── build.zig # Build configuration
# All tests
zig build test
# Specific test file
zig build test -- src/clew/tests.zig
# With coverage (requires kcov)
zig build test -- --coverage- VS Code: Install
ziglang.vscode-zigextension - Vim/Neovim: Use
zig-lang/zig.vim - Emacs: Use
zig-mode - LSP: Built-in Zig language server support
Phase: v0.1.0 - Beta (Core Ready)
Release: December 2025
Production-Ready Components (v0.1.0):
-
Clew (Constraint Extraction): PRODUCTION READY
- Pure Zig structural parsers with tree-sitter integration
- 101+ constraint patterns across TypeScript/Python
- 40+ unit tests passing, 0 memory leaks
- <100ms extraction time (static analysis)
- Optional Claude API integration for semantic analysis
- Verified working across tutorial and production examples
-
Braid (Constraint Compilation): PRODUCTION READY
- All 4 components fully implemented and tested:
- JSON Schema generator
- Regular expression matcher
- Grammar builder
- Token mask compiler
- 31+ unit tests passing, 0 memory leaks
- LRU caching with deep cloning (clone-on-get strategy)
- 11-13x cache speedup, ~5-15μs cache hit latency
- All 4 components fully implemented and tested:
-
Security Hardening: PRODUCTION READY
- Path traversal protection with symlink validation
- Constraint injection prevention (SQL, XSS, command injection)
- API key memory zeroing with volatile writes
- HTTP retry with exponential backoff and rate limiting
- 23 dedicated security edge case tests
- Full OWASP Top 10 compliance verification
- See docs/SECURITY_TEST_REPORT.md
-
CLI Tool: PRODUCTION READY
- 6 commands fully functional: extract, compile, generate, validate, init, version, help
- Enhanced error messages with actionable suggestions
- Context-aware help and troubleshooting guides
- 43+ CLI tests passing
- Verified working with all examples
- JSON output format for programmatic use (--format json)
-
Modal Inference Service: PRODUCTION READY
- vLLM 0.11.0 + llguidance 0.7.11 deployed
- Endpoint: https://<YOUR_MODAL_WORKSPACE>--ananke-inference-generate-api.modal.run
- Model: Qwen2.5-Coder-32B-Instruct
- Performance: 22.3 tokens/sec with JSON schema constraints
- ~50μs per-token overhead for constraint enforcement
-
Maze (Orchestration): PRODUCTION READY
- Rust-based async orchestration layer
- Complete FFI integration with Zig
- 43+ Rust tests passing
- HTTP API coordination with inference service
- Verified working in full end-to-end examples
Experimental/In-Progress:
-
Ariadne DSL: 70% COMPLETE
- Parsing: Complete
- Type checking and error recovery: Deferred to v0.2
- Basic constraint definitions work well
-
Additional Extractors: NOT YET IMPLEMENTED
- Rust extraction support (Planned v0.2)
- Go extraction support (Planned v0.2)
- Zig extraction support (Planned v0.2)
Test Coverage:
- 301 total tests passing (100% pass rate)
- 258 Zig tests (extraction, compilation, integration, E2E, security)
- 43 CLI/Rust tests (orchestration, FFI, infrastructure)
- 23 dedicated security edge case tests
- Zero critical failures, zero memory leaks
- <2 minutes total test suite runtime
Known Limitations:
- Pure Zig parsers extract syntax patterns only (tree-sitter compatibility deferred to v0.2)
- Token masking uses hash-based IDs (not real cryptographic tokens)
- Ariadne DSL lacks full type checking (v0.2 feature)
- Only TypeScript and Python extractors fully implemented (others in v0.2 roadmap)
Next Release (v0.2.0): Q1 2026
- Full tree-sitter integration for extended language support
- Bidirectional streaming generation
- Multi-model orchestration
- Ariadne DSL type checking and error recovery
- Web UI (beta)
- Complete Rust/Go/Zig extractors
See RELEASE_NOTES.md for v0.1.0 details. See docs/IMPLEMENTATION_PLAN.md for v0.2 roadmap.
Mines constraints from multiple sources using pure Zig structural parsers and optional Claude integration:
Source Code → Pure Zig parsers → Syntactic constraints
Tests → Pure Zig parsers → Type/behavior constraints
Telemetry → Claude analysis → Performance constraints
Docs → Claude analysis → Business rules
Constraint categories:
- Syntactic: Code structure, formatting, naming
- Type: Type safety, null checks, return types
- Semantic: Data flow, control flow, side effects
- Architectural: Module boundaries, layering
- Operational: Performance bounds, resource limits
- Security: Input validation, auth patterns
Transforms extracted constraints into efficient execution:
- Graph Construction: Builds constraint dependency DAG
- Conflict Detection: Identifies contradictions
- Resolution: Finds valid ordering (with optional Claude help)
- Optimization: SIMD-accelerated parallel validation
- Compilation: Outputs ConstraintIR for llguidance
Coordinates generation across the system:
- Manages constraint cache
- Handles inference server communication
- Applies token-level masks via llguidance
- Supports streaming generation
- Validates outputs against constraints
Must be controlled locally for token-level constraint enforcement:
- vLLM/SGLang: High-performance model serving
- llguidance: ~50μs/token constraint application
- Model: Llama, Mistral, DeepSeek, or similar
- GPU: 16GB+ VRAM for 7B models
| Operation | Target | Achieved |
|---|---|---|
| Constraint extraction | <100ms | ✓ ~10ms (static analysis) |
| Constraint compilation | <50ms | ✓ ~1ms |
| Token-level enforcement | <50μs/token | ✓ ~50μs/token |
| Cache hit latency | <20μs | ✓ ~5-15μs |
| Full pipeline | <5s | ✓ ~18ms (without generation) |
- QUICKSTART.md - 10-minute getting started guide
- INSTALL_QUICKREF.md - Quick installation reference
- RELEASE_NOTES.md - v0.1.0 features and highlights
- ARCHITECTURE.md - System design and component details
- ARCHITECTURE_V2.md - Advanced architecture patterns
- API_REFERENCE_ZIG.md - Zig library API reference
- API_REFERENCE_RUST.md - Rust Maze API reference
- CLI_GUIDE.md - Complete CLI command reference
- API_ERROR_HANDLING.md - API error handling and troubleshooting
- COMPILE_COMMAND.md - Comprehensive compile command guide
- MODAL_INFRASTRUCTURE.md - Modal deployment and configuration
- DEPLOYMENT.md - Production deployment guide
- SECURITY.md - Security guidelines and best practices
- SECURITY_TEST_REPORT.md - Comprehensive security testing report
- PERFORMANCE.md - Performance optimization guide
- FFI_GUIDE.md - Cross-language integration
- TEST_STRATEGY.md - Testing approach and strategy
- CONTRIBUTING.md - Contribution guidelines
- DEVELOPMENT_HISTORY.md - Development narrative
- FAQ.md - Frequently asked questions
- TROUBLESHOOTING.md - Common issues and solutions
- IMPLEMENTATION_PLAN.md - Detailed roadmap with phases
- beads/implementation-phases.bead - Task tracking
Language Support:
- Extractors: TypeScript/JavaScript and Python fully supported
- Rust, Go, and Zig extractors planned for v0.2
- Pure Zig parsers limit semantic extraction (full tree-sitter integration in v0.2)
Ariadne DSL:
- Parsing works well for constraint definitions
- Type checking and detailed error messages deferred to v0.2
- Use JSON configuration for production deployments
Token Masking:
- Uses hash-based IDs for token identification
- Real cryptographic tokenization planned for v0.2
- Safe for most use cases but not recommended for cryptographic token handling
Caching:
- Works reliably with clone-on-get strategy
- Single-machine in-process cache (distributed caching in roadmap)
CLI:
- Core commands functional and tested
- Some advanced features (batch processing, config files) in v0.2
- Windows support experimental (full support in v0.2)
See /examples directory for working examples:
- 01-simple-extraction: Constraint extraction with no external services
- 02-claude-analysis: Using Claude for semantic understanding
- 03-ariadne-dsl: Constraint DSL examples and API design patterns
- 04-full-pipeline: End-to-end extraction, compilation, and generation
- 05-mixed-mode: Combining extracted, JSON, and DSL constraints
# Run an example
cd examples/01-simple-extraction
zig build runWe're actively building Ananke. Contributions welcome in:
- Constraint extraction improvements
- Performance optimization
- Model/platform support
- Documentation
- Test coverage
See CONTRIBUTING.md for guidelines.
All Rights Reserved - See LICENSE file for details
Inspired by:
- llguidance: Token-level constraint enforcement
- vLLM: Efficient inference infrastructure
- Tree-sitter: Robust syntax parsing
- Claude: Semantic code understanding
- Foundation & Zig setup
- Constraint extraction (Clew) - TypeScript, Python
- Constraint compilation (Braid) - all 4 components
- Ariadne DSL - parsing complete
- Maze orchestration - Rust FFI integration
- Modal inference service deployment
- CLI tool - 6 commands functional
- Security hardening - OWASP Top 10 compliance
- 301 tests passing, 0 memory leaks
- Full tree-sitter integration for all languages
- Rust, Go, Zig extractors
- Ariadne DSL type checking
- Bidirectional streaming generation
- Multi-model orchestration
- Web UI (beta)
See RELEASE_NOTES.md for v0.1.0 details.
Questions? Open an issue or check the documentation in /docs.