hx

mcp
Guvenlik Denetimi
Gecti
Health Gecti
  • License — License: MIT
  • Description — Repository has a description
  • Active repo — Last push 0 days ago
  • Community trust — 36 GitHub stars
Code Gecti
  • Code scan — Scanned 12 files during light audit, no dangerous patterns found
Permissions Gecti
  • Permissions — No dangerous permissions requested

Bu listing icin henuz AI raporu yok.

SUMMARY

The whole Haskell toolchain in one fast binary. Installs GHC and Cabal, builds, tests, formats, locks and publishes Haskell projects. Written in Rust.

README.md

hx

Haskell, finally fast.
One opinionated, batteries-included toolchain for Haskell.
Fast, unified, futuristic.

Rust Haskell License

Documentation • Features • Benchmarks • Contributing


Haskell's tooling is powerful — and scattered. Starting a project means juggling ghcup, cabal, stack, fourmolu, hlint, and hpc, each with its own flags, config, and failure modes.

hx collapses all of it into a single, fast binary. Written in Rust, it drives the tools you already trust behind one coherent interface — with deterministic builds, errors that tell you how to fix them, and a feedback loop quick enough to stay out of your way.

One command to install. One file to configure. One tool to learn.

hx demo

Why hx?

  • Batteries included — Build, test, run, format, lint, profile, and publish. Watch mode, coverage reports, and IDE setup. Everything in one tool.
  • Managed toolchains — Automatic GHC installation and per-project version pinning in hx.toml. No ghcup required.
  • Deterministic builds — TOML lockfiles with fingerprint verification. Reproducible across machines and CI — correct by construction, not by luck.
  • Excellent errors — Actionable messages with fix suggestions. hx doctor diagnoses your setup and tells you exactly what to do.
  • Drop-in compatible — Works with existing .cabal files and Hackage. Import from Stack or Cabal — your workflow stays the same, just better.
  • Extensible — Plugin system with Steel (Scheme), pre/post-build hooks, and Nix integration.
  • Agent-ready — A built-in MCP server (hx mcp), an AGENTS.md, and a Claude skill let AI agents drive the whole toolchain.
  • Blazingly fast — Native builds bypass Cabal overhead: ~5.6× faster cold builds, ~4.8× faster no-op rebuilds, measured on hx 0.9.2 — see docs/BENCHMARKS.md.
  • Futuristic — A first-class BHC backend: a next-generation Haskell compiler with curated Platform snapshots.

Installation

From releases

# macOS/Linux
curl -fsSL https://arcanist.sh/hx/install.sh | sh

# Or download from releases
https://github.com/arcanist-sh/hx/releases

Windows

winget install raskell-io.hx

From source

cargo install --git https://github.com/arcanist-sh/hx hx-cli

If you already use Helix

The Helix editor's binary is also called hx. When the installer finds an
hx on your PATH that isn't hx, it installs as hxs instead so both
stay reachable, and tells you it did. Every command below then works the
same, just spelled hxs.

To take the hx name anyway:

curl -fsSL https://arcanist.sh/hx/install.sh | HX_BINARY_NAME=hx sh

Or to choose the name yourself:

curl -fsSL https://arcanist.sh/hx/install.sh | sh -s -- --binary-name hxs

Installing from source or from a release archive gives you hx regardless;
rename the binary if it would collide. hx doctor reports either direction
of collision if one appears later.

Verify installation

hx --version
hx doctor

Quick Start

# Create a new project
hx init myapp
cd myapp

# Build and run
hx build
hx run

# Lock dependencies for reproducibility
hx lock
hx sync

# Watch for changes
hx watch

Commands

Project Management

hx init                      # Initialize in current directory
hx init myapp                # Create myapp/ and initialize
hx init --lib                # Create a library project
hx init --ci                 # Include GitHub Actions workflow

hx new webapp myapp          # Create web app (Servant)
hx new cli myapp             # Create CLI app (optparse-applicative)
hx new library mylib         # Create library with docs setup
hx new template <url> <name> # Create from git template

Building

hx build                     # Build the project (all packages in a workspace)
hx build --package mylib     # Build a single workspace member
hx build --release           # Build with optimizations
hx build --native            # Use native GHC build (no cabal)
hx build -j4                 # Parallel build with 4 jobs
hx check                     # Fast type-check
hx clean                     # Clean build artifacts

Workspaces

hx workspace init            # Make this directory a multi-package workspace root
hx workspace add ./lib-a     # Add a member (cabal.project stays the member list)
hx workspace list            # Members, versions, dependencies between them
hx build -p lib-a -p app     # Build selected members
hx test --changed origin/main  # Test only members a branch affects (+ dependents)

At the root, hx build/test/check cover every member. Inside a member
directory they target that member, still using the root lockfile and
toolchain. See docs/WORKSPACES.md.

Running & Testing

hx run                       # Build and run the executable
hx run -- arg1 arg2          # Pass arguments to the program
hx repl                      # Start an interactive GHCi session
hx test                      # Run tests (all packages in a workspace)
hx test --package mylib      # Test a single workspace member
hx test --pattern "Unit"     # Filter tests by pattern
hx bench                     # Run benchmarks

Watch Mode

hx watch                     # Auto-rebuild on file changes
hx watch --test              # Auto-run tests on changes
hx watch --clear             # Clear terminal between runs

Dependencies

hx lock                      # Generate/update hx.lock
hx lock --update             # Update all dependencies
hx lock --check              # Verify hx.lock (for CI; non-zero exit on mismatch)
hx sync                      # Build with locked dependencies
hx fetch                     # Download + verify locked sources in parallel
hx sync --offline            # Build from cached sources only (after hx fetch)

hx add text                  # Add a dependency
hx add aeson ">=2.0"         # Add with version constraint
hx add --dev hspec           # Add dev dependency
hx rm text                   # Remove a dependency

hx why text                  # Show why a package is a dependency
hx info aeson                # Show package details from Hackage
hx info aeson --versions     # Include all available versions
hx outdated                  # Check for outdated dependencies
hx outdated --direct         # Only show direct dependencies
hx update                    # Update dependencies (minor/patch)
hx update --major            # Allow major version updates
hx update --dry-run          # Preview updates without applying
hx update aeson text         # Update specific packages

hx tree                      # Show dependency tree
hx tree --depth 2            # Limit tree depth
hx list                      # List all dependencies
hx list --direct             # List direct dependencies only

hx deps graph --format dot   # Generate Graphviz graph (also: tree, list, json)

hx search aeson              # Search Hackage for packages
hx search aeson --registry arcanist  # Search the arcanist.sh registry instead
hx audit                     # Check for deprecated dependencies
hx audit --outdated          # Check for outdated packages

Code Quality

hx fmt                       # Format code with fourmolu
hx fmt --check               # Check formatting without changes
hx lint                      # Run hlint
hx lint --fix                # Apply automatic fixes

Test Coverage

hx coverage                  # Run tests with coverage
hx coverage --html           # Generate HTML report
hx coverage --html --open    # Generate and open in browser
hx coverage --threshold 80   # Fail if below 80% coverage
hx coverage --json           # Output JSON for CI

Profiling

hx profile                   # Run with time profiling
hx profile --heap            # Run with heap profiling
hx profile --time --heap     # Both time and heap

Documentation

hx docs                      # Generate documentation
hx docs --open               # Generate and open in browser
hx docs --deps               # Include dependency docs
hx docs --serve              # Serve locally on port 8080

Toolchain Management

hx toolchain status          # Show installed versions
hx toolchain list            # Installed, recommended and latest GHC/Cabal
hx toolchain list --available # All available versions
hx toolchain list --installed # List installed versions only

hx toolchain install 9.8.2   # Install GHC version
hx toolchain install --set   # Install and set as active
hx toolchain install --bhc <version> # Install the BHC toolchain
hx toolchain remove 9.6.4    # Remove a GHC version

hx toolchain use 9.8.2       # Switch GHC version
hx toolchain use project     # Use project's toolchain

hx stackage list             # List Stackage snapshots
hx bhc-platform list         # List BHC Platform snapshots
hx server start              # Start the persistent build server
hx server status             # Show build server status

Installing Executables

Like cargo install: build a package's executables and put them in
~/.hx/bin (add that directory to your PATH).

hx install hlint             # Latest version from Hackage
hx install [email protected]   # A specific version
hx install --git <url> --rev v1.2 # From a git repository
hx install --path .          # From a local project
hx install --ghc 9.8.2 hlint # Build with a specific (installed) GHC
hx install --list            # Show installed packages and executables
hx uninstall hlint           # Remove exactly what `hx install` put there

The build runs cabal install with hx's GHC and Cabal; hx records what it
installed in ~/.hx/installed.toml. Re-running hx install for an installed
version is a no-op (use --force to rebuild). An executable that would
overwrite one owned by another package, or a file hx install didn't put
there, is reported instead of replaced, unless you pass --force.

IDE & Agent Integration

hx ide setup                 # Generate hie.yaml for HLS
hx ide status                # Check IDE configuration
hx lsp                       # Start language server
hx mcp                       # Start an MCP server for AI agents (JSON-RPC/stdio)

hx mcp exposes build/test/run/lock/doctor/dependency tools over the
Model Context Protocol. See
AGENTS.md for how to drive hx from an AI agent, the Claude skill at
.claude/skills/hx/SKILL.md for slash-command
workflows, and the llms.txt project map
(served at arcanist.sh/hx/llms.txt) for a compact, agent-friendly overview.

Publishing

hx publish                   # Publish to Hackage
hx publish --dry-run         # Validate without uploading
hx publish --docs            # Include documentation
hx changelog                 # Generate CHANGELOG from commits
hx changelog --preview       # Preview without writing

Package registries (preview)

Hackage stays the default. You can also target a package registry such as
the arcanist.sh registry (https://registry.arcanist.sh, not live yet), or
any URL. Plain cabal consumes these registries as a secure (hackage-security)
repository, so builds work without hx. See docs/REGISTRY.md.

hx registry login --registry arcanist          # store an API token (prompted, kept 0600)
hx publish --registry arcanist                 # same checks, then upload the sdist
hx registry info my-lib                        # versions, owners, BHC verification
hx registry yank my-lib 1.2.0 [--undo]         # cabal avoids yanked versions
hx registry owner add my-lib alice
hx registry token create ci --scope publish --package my-lib
hx registry add --registry arcanist            # add the repository stanza to cabal.project

Name registries in hx.toml or the global config.toml:

[registries.arcanist]
url = "https://registry.arcanist.sh"   # built in; override it here, e.g. for a local server

Distribution

hx dist                      # Build release archive
hx dist --target x86_64-unknown-linux-musl  # Cross-compile
hx dist formula              # Generate Homebrew formula
hx dist install-script       # Generate install script

Utilities

hx doctor                    # Diagnose setup issues
hx script file.hs            # Run single-file script
hx import --from cabal       # Import a Cabal project (cabal.project or bare .cabal)
hx import --from stack       # Import from stack.yaml
hx nix flake                 # Generate flake.nix
hx nix shell                 # Generate shell.nix
hx completions install       # Auto-install completions for your shell
hx completions generate bash # Generate completions to stdout
hx upgrade                   # Upgrade hx to latest version

hx import --from cabal works with a full cabal.project or just a bare
.cabal file — in the latter case the directory is adopted as a single-package
project. hx import --from stack adopts an existing Stack project. Running a
project command outside an hx project but inside a Cabal or Stack project
reports "project not found" and suggests hx import to adopt it.

Cache Management

hx cache status              # Show cache statistics
hx cache artifacts           # Show artifact cache statistics
hx cache prune --days 30     # Remove entries older than 30 days
hx cache clean               # Clear entire cache
hx index update              # Update Hackage package index
hx index clear               # Remove the local index
hx index status              # Show index status

Plugins

hx plugins list              # List available plugins
hx plugins status            # Show plugin system status
hx plugins run script.scm    # Run a Steel script
hx plugins trust             # Allow this project's local plugins to run
hx plugins untrust           # Revoke that permission

Project-local plugins (.hx/plugins/*.scm) only run after you trust the
project with hx plugins trust - cloning a repository never grants its
scripts execution rights.

Configuration

hx uses hx.toml for project configuration:

[project]
name = "myapp"
kind = "bin"         # or "lib"
resolver = "cabal"

[toolchain]
ghc = "9.8.2"
cabal = "3.12.1.0"
hls = "2.9.0.0"

[build]
optimization = 2     # 0, 1, or 2
warnings = true
native = false       # Use native GHC builds

[format]
formatter = "fourmolu"

[lint]
hlint = true

[plugins]
enabled = true
hook_timeout_ms = 30000

[plugins.hooks]
pre_build = ["./scripts/check.scm"]
post_test = ["./scripts/notify.scm"]

Global Configuration

hx supports global configuration at ~/.config/hx/config.toml (Linux), ~/Library/Application Support/io.raskell.hx/config.toml (macOS), or %APPDATA%\raskell\hx\config\config.toml (Windows).

Global settings provide defaults that can be overridden by project-local hx.toml:

# ~/.config/hx/config.toml

[toolchain]
ghc = "9.8.2"
cabal = "3.12.1.0"

[build]
optimization = 1
warnings = true

[format]
formatter = "fourmolu"

[lint]
hlint = true

Managing Global Config

hx config show           # Show current global configuration
hx config path           # Show path to global config file
hx config path --all     # Show every location hx uses, and why
hx config edit           # Open config file in your $EDITOR
hx config init           # Create default config file
hx config set <key> <val> # Set a configuration value
hx config get <key>      # Get a configuration value

# Examples:
hx config set toolchain.ghc 9.8.2
hx config set build.optimization 2
hx config set format.formatter ormolu

Where hx Stores Things

hx config path --all prints every location below as it applies on your
machine, with the setting that chose it (default, $XDG_CACHE_HOME,
$HX_HOME, ...).

Defaults

What Linux macOS Windows
Global config file ~/.config/hx/config.toml ~/Library/Application Support/io.raskell.hx/config.toml %APPDATA%\raskell\hx\config\config.toml
Global plugins ~/.config/hx/plugins ~/Library/Application Support/io.raskell.hx/plugins %APPDATA%\raskell\hx\config\plugins
Cache root (artifacts, store indexes) ~/.cache/hx ~/Library/Caches/io.raskell.hx %LOCALAPPDATA%\raskell\hx\cache
Cabal store ~/.cache/hx/cabal/store <cache root>/cabal/store <cache root>\cabal\store
Resolution cache ~/.cache/hx/solver ~/.cache/hx/solver %USERPROFILE%\.cache\hx\solver
Package sources and native package store ~/.cache/hx/packages ~/.cache/hx/packages %USERPROFILE%\.cache\hx\packages
Hackage index mirror ~/.cache/hx/index ~/.cache/hx/index %USERPROFILE%\.cache\hx\index
Stackage snapshots ~/.cache/hx/stackage ~/Library/Caches/hx/stackage %LOCALAPPDATA%\hx\stackage
BHC Platform snapshots ~/.cache/hx/bhc-platform ~/Library/Caches/hx/bhc-platform %LOCALAPPDATA%\hx\bhc-platform
hx script builds ~/.cache/hx/scripts ~/Library/Caches/hx/scripts %LOCALAPPDATA%\hx\scripts
GHC / Cabal / HLS installs ~/.hx/toolchains ~/.hx/toolchains %USERPROFILE%\.hx\toolchains
Active tool symlinks ~/.hx/bin ~/.hx/bin %USERPROFILE%\.hx\bin
BHC installs ~/.bhc ~/.bhc %USERPROFILE%\.bhc
Per-project build state <project>/.hx/ <project>/.hx/ <project>\.hx\

On macOS and Windows a few caches keep the location earlier releases used, so
upgrading never strands downloaded or built data. Plugins in the pre-0.9.3
global location (~/Library/Application Support/hx/plugins,
%APPDATA%\hx\plugins) are still loaded. Toolchains live under ~/.hx
on every platform because GHC's build system cannot handle the space in
Application Support.

Overrides

Variable Moves
HX_CACHE_DIR Every cache location, which then lives directly under it ($HX_CACHE_DIR/solver, $HX_CACHE_DIR/cabal/store, ...)
XDG_CACHE_HOME Same as HX_CACHE_DIR, rooted at $XDG_CACHE_HOME/hx (any platform)
HX_STORE_DIR The Cabal store only
XDG_CONFIG_HOME Config file and global plugins, to $XDG_CONFIG_HOME/hx (any platform)
HX_CONFIG_FILE / --config-file The global config file only
HX_HOME ~/.hx: toolchains and tool symlinks

HX_* variables take precedence over XDG_* ones. Empty values, and
XDG_* values that are not absolute paths, are ignored. XDG_DATA_HOME
does not move ~/.hx, so existing toolchain installs stay where they are;
set HX_HOME to relocate them, and move the directory yourself.

hx cache clean removes every cache location listed above, including the
older-layout ones.

Lockfile

The hx.lock file ensures reproducible builds. It pins every dependency's
exact version, the SHA-256 of its source tarball, the Hackage .cabal
revision it was resolved with, and the Hackage index state:

version = 2
created_at = "2026-10-19T08:09:08Z"

[toolchain]
ghc = "9.8.2"
cabal = "3.12.1.0"

[plan]
compiler_id = "ghc-9.8.2"
platform = "x86_64-linux"
index_state = "2026-10-19T07:18:30Z"
hash = "sha256:..."

[[packages]]
name = "containers"
version = "0.8.1"
source = "hackage"
sha256 = "9bd0f5156306b04a799c32ff49a6129f7c8dd6ec96c6ddeb7885975ffffc9e99"
revision = 0
cabal_sha256 = "11cc66be32854dc6b9c04c1e4f9a3ecb4939399a3b54bf00c6c085d538470b12"

hx sync builds with exactly these pins. For offline or air-gapped builds,
run hx fetch once while online (it downloads and verifies every source),
then hx sync --offline (or HX_OFFLINE=1). In CI, hx lock --check fails
when hx.lock is stale or a cached source does not match its hash. See
docs/LOCKFILE.md for the full format and workflow.

The native solver evaluates .cabal conditionals (os, arch, impl(ghc),
and flag) and excludes dependencies of disabled components (buildable: False),
so platform- and compiler-specific packages never leak into the lockfile.
Single-package projects (including bare .cabal adoptions) get a real lockfile
too, so hx why, hx deps, and hx outdated work there as well.

Packages with a custom Setup.hs (build-type: Custom) build correctly via
delegation to Cabal.

Environment Variables

Variable Description
HX_VERBOSE Enable verbose output
HX_QUIET Suppress output
HX_NO_COLOR Disable colored output
HX_CONFIG_FILE Path to config file
HX_CACHE_DIR Cache directory location (see Where hx Stores Things)
HX_STORE_DIR Cabal store location
HX_HOME hx home (default ~/.hx): toolchains, bin and the hx install manifest
XDG_CACHE_HOME, XDG_CONFIG_HOME Honoured on every platform
HX_AUTO_INSTALL Auto-install missing toolchains
HX_NO_AUTO_INSTALL Never auto-install toolchains
HX_ALLOW_UNVERIFIED_DOWNLOADS Allow toolchain installs without a published checksum
HX_OFFLINE Work offline: never refresh ghcup release metadata (use the cache or built-in tables), and build hx sync from cached sources only (like --offline)
HX_GHCUP_METADATA_URL Alternative ghcup metadata file (mirror, or file:// path)
HX_BHC_PLATFORM_PUBKEY Pinned Ed25519 key for BHC Platform snapshot verification
HX_BHC_PLATFORM_URL BHC Platform snapshot registry URL (default https://arcanist.sh/bhc-platform/index.json)
HTTPS_PROXY / HTTP_PROXY / NO_PROXY Route hx's downloads through a proxy (system proxy settings are also honoured)
SSL_CERT_FILE / SSL_CERT_DIR On Linux, read CA certificates from these locations instead of the system store. hx trusts the operating system's certificate store plus a bundled Mozilla root set, so a CA installed system-wide (for example a corporate TLS proxy's) is trusted on every platform
HX_REGISTRY_TOKEN API token for --registry commands (overrides credentials.toml)
HX_HACKAGE_URL Hackage mirror hx fetch downloads from (file:// mirrors work)

Exit Codes

Code Meaning
0 Success
1 General error
2 Usage error
3 Configuration error
4 Toolchain error
5 Build/test failure
6 Plugin hook failure

Architecture

hx is a Rust workspace with these crates:

Crate Purpose
hx-cli Command-line interface
hx-core Shared types and utilities
hx-config Configuration parsing
hx-lock Lockfile management
hx-toolchain GHC/Cabal detection and installation
hx-cabal Cabal wrapper and native builds
hx-cache Build cache management
hx-doctor Diagnostic checks
hx-solver Native dependency resolver
hx-lsp Language server protocol
hx-plugins Steel plugin runtime
hx-ui Terminal output utilities
hx-warnings Warning system
hx-telemetry Tracing and metrics
hx-compiler Compiler backend abstraction (GHC, BHC)
hx-bhc BHC (Basel Haskell Compiler) native build pipeline

Development

# Build
cargo build

# Run tests
cargo test --workspace

# Run clippy
cargo clippy --workspace -- -D warnings

# Format
cargo fmt

# Run hx locally
cargo run -p hx-cli -- --help

Philosophy

hx follows the Astral playbook — earn trust by improving what exists before replacing any of it:

  1. Wrap first — Drive the tools you already rely on (GHC, Cabal) instead of reimplementing them.
  2. Tame second — Layer on better UX, error messages, and workflows until the rough edges disappear.
  3. Replace last — Swap in faster paths (native builds) and a next-generation compiler (BHC) only where they earn their place.

The destination: a Haskell toolchain that's fast, unified, and futuristic — without asking you to throw away what already works.

License

MIT — part of arcanist.sh.

Yorumlar (0)

Sonuc bulunamadi