@azghr/crux
v1.0.4
Published
A decision engine for developers. State a tooling/library/architecture choice; it infers what matters, researches current facts on the web, and returns one ruling — flagging what it could not verify.
Maintainers
Readme
Crux
A decision engine for developers. State a tooling/library/architecture choice; Crux researches current facts, analyzes what matters for your specific situation, and returns one clear recommendation with explicit uncertainties.
How it works
Crux analyzes your decision in stages:
- Analyze your repository (optional) - understands your tech stack and constraints
- Research current facts - gathers latest information from the web
- Evaluate options - scores candidates against weighted criteria
- Return one ruling - single recommendation with runner-up and explicit uncertainties
Installation
npm install -g @azghr/cruxOr use zero-install:
npx @azghr/crux "your decision here"Setup
Only two variables are required — endpoints and models are chosen automatically per provider:
export CRUX_PROVIDER=anthropic # anthropic | openrouter | openai-compat | groq
export CRUX_API_KEY=sk-... # your provider's API keyOptional overrides for custom setups (Ollama, vLLM, custom proxies):
export CRUX_BASE_URL=http://localhost:11434/v1 # generic (mainly for openai-compat)
export CRUX_GROQ_BASE_URL=https://api.groq.com/openai/v1 # per-provider, wins over the generic var
export CRUX_ANTHROPIC_BASE_URL=https://api.anthropic.com/v1A generic CRUX_BASE_URL that points at a different provider's known host is ignored — it can never send your key to the wrong API. Use the per-provider var in that case. See .env.example for ready-to-copy setups.
Usage
# Simple decision
crux "Zustand vs Redux vs Jotai" -c "TypeScript, solo dev, SSR"
# Structured JSON output (pipe to jq)
crux --json "pick an HTTP client" -c "Node 20, ESM" | jq .verdict.recommendation
# Run without web search, or bypass the cache
crux "ORM choice" -r . --offline --no-cache
# Based on your current repository
crux "add a form library" -r .
# For specific programming languages
crux "web framework" -r /path/to/go/repo --eco go
crux "ORM choice" -r /path/to/python/repo --eco pythonThe -r flag analyzes your repository to understand your stack automatically. For local repos use . for current directory, or specify a path. Remote repos may require authentication tokens.
Guardrails for AI Agents
Crux provides three integration layers for coding agents:
1. Rules File (Universal)
crux rules -r . --also-claudeGenerates AGENTS.md with domain-specific guidance for any AI agent.
2. MCP Server
crux mcpExposes tools for MCP-compatible clients (Claude Code, OpenCode, etc.).
3. Code Review
git diff | crux review --diffAnalyzes code changes for potential issues.
Library Usage
import { Crux } from "@azghr/crux";
const verdict = await new Crux().decide(
{ decision: "message queue for a Node service", constraints: "AWS, low ops" },
{ onStage: (s) => console.log(s) },
);
console.log(verdict.recommendation, verdict.uncertainties);Web UI (crux-serve)
Self-hosted server with a terminal-style web UI. No framework, no build step — the UI ships as static assets served by crux-serve.
export CRUX_API_KEY=sk-...
crux-serve # http://localhost:8787
crux-serve --port 8788 # or CRUX_SERVE_PORT / CRUX_SERVE_HOSTThe UI streams pipeline stages live (SSE), lets you pick provider/model per request, and falls back to your server-side env config when no key is supplied. Use it as a library too:
import { startServer } from "@azghr/crux/serve";
const { port, close } = await startServer({ port: 8787 });Providers
| Provider | Web Search | JSON Mode | Notes |
| --------------- | ------------------------ | --------- | --------------------------------------------------------- |
| anthropic | Yes | No | Default. Full web search support. |
| openrouter | Opt-in (CRUX_WEB=true) | Yes | Many free models available. Web search is pay-per-use. |
| groq | No | Yes | Fast inference, no web search. |
| openai-compat | No | Yes | Any OpenAI-compatible API. Override with CRUX_BASE_URL. |
Configuration
A .env file in the directory where you run the CLI is loaded automatically
(real exported env vars always win). CRUX_MODEL, CRUX_MODEL_FAST and
CRUX_MODEL_STRONG override the automatic per-provider model selection; on
groq the current default is openai/gpt-oss-120b (fast tier
openai/gpt-oss-20b).
| Variable | Default | Description |
| ----------------------------- | ----------------- | ----------------------------------------------- |
| CRUX_PROVIDER | anthropic | LLM provider |
| CRUX_API_KEY | (required) | Provider API key |
| CRUX_BASE_URL | Provider-specific | Optional. Override API endpoint (custom setups) |
| CRUX_MODEL | Provider default | Optional. Override model ID |
| CRUX_MODEL_FAST | Provider default | Optional. Override framing/filter/score model |
| CRUX_MODEL_STRONG | Provider default | Optional. Override research/verdict model |
| CRUX_WEB | false | Enable web search (paid on OpenRouter) |
| CRUX_OFFLINE | false | Run without web search |
| CRUX_TIMEOUT_MS | 60000 | Request timeout in ms |
| CRUX_MAX_RETRIES | 3 | Retry attempts for transient failures |
| CRUX_MAX_TOKENS_PER_REQUEST | 4096 | Output token cap per API call |
| CRUX_MAX_CALLS | 50 | Max LLM calls per decision |
| CRUX_MAX_TOKENS | 100000 | Approximate token budget per decision |
| CRUX_CACHE_ENABLED | true | Enable file-backed caching |
| CRUX_NO_CACHE | false | Bypass cache for this run |
| CRUX_CACHE_TTL | 86400000 | Cache entry lifetime (ms) |
| CRUX_SERVE_PORT | 8787 | Web UI listen port |
| CRUX_SERVE_HOST | localhost | Web UI listen host |
| CRUX_SERVE_WEB_DIR | bundled web/ | Override static UI directory |
Logging & Debugging
JSON output: crux --json "decision" emits one JSON record per line on stdout — the verdict on success, a machine-readable { "kind", ... } error record on failure. Diagnostics always go to stderr so both streams stay pipeable.
Quiet mode: crux --quiet "decision" to suppress progress output
Debug: crux --debug "decision" or --log-level debug
No colors: Set NO_COLOR=1 to disable ANSI codes
Output Format
Exit codes: 0 (success), 1 (error / bad config / budget exceeded), 2 (needs clarification), 3 (unparseable model output), 4 (rate limited). crux review exits 1 on a rethink verdict.
Error record kinds in JSON mode: config_error, clarification, budget_exceeded, parse_error, rate_limited, error.
All output automatically redacts API keys, passwords, and sensitive data.
Notes
- Research freshness depends on web search availability
- Uncertainties are explicitly listed - thin margins or weak evidence appear there
- Free models may have limited context and rate limits
- Repository analysis is read-only (except
crux ruleswhich writes AGENTS.md/CLAUDE.md)
Development
Requires just for task automation.
just # Run typecheck + tests + build + smoke test
just test # Unit tests
just coverage # Tests with coverage report
just typecheck # TypeScript type check
just build # Compile to dist/
just smoke # Release smoke test
just dev "..." # Run CLI in dev mode (no build needed)
just eval # Run evaluation suiteRelease Process
Releases are managed with Changesets.
- Add a changeset for user-facing changes:
pnpm changeset - The
ReleaseGitHub Action opens a version PR onmain - Merging that PR publishes
@azghr/cruxto npm automatically
Run the local gates with just check (typecheck + tests + build + smoke) before pushing.
