Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
196 changes: 110 additions & 86 deletions cli/docs/claude-code-web.md
Original file line number Diff line number Diff line change
@@ -1,129 +1,153 @@
# Setting Up Haskell Development Environment
# Haskell Setup for Claude Code Web

The CLI project uses Stack as its build tool. To set up your development environment:
**For Claude:** This is your reference for setting up Haskell in web environments. Copy-paste the commands and move on.

## Installing Stack
## First Time Setup

We recommend using ghcup to install Stack:
Run this once per environment:

1. Install ghcup (the Haskell toolchain installer):
```bash
curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | BOOTSTRAP_HASKELL_NONINTERACTIVE=1 BOOTSTRAP_HASKELL_MINIMAL=1 sh
```
```bash
# Install toolchain
curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | \
BOOTSTRAP_HASKELL_NONINTERACTIVE=1 BOOTSTRAP_HASKELL_MINIMAL=1 sh

# Activate (do this in EVERY new shell)
source ~/.ghcup/env

# Install Stack
ghcup install stack

# CRITICAL: Configure proxy (Stack won't work without this)
mkdir -p ~/.stack
cat > ~/.stack/config.yaml << 'EOF'
http-proxy: http://egress.public-claude-proxy.svc.cluster.local:80
https-proxy: http://egress.public-claude-proxy.svc.cluster.local:80
EOF
```

2. Source the ghcup environment:
```bash
source ~/.ghcup/env
```
**Verify it worked:**
```bash
stack --version # Should show: Version 3.3.1 or similar
cat ~/.stack/config.yaml # Should show the proxy config
```

3. Install Stack using ghcup:
```bash
ghcup install stack
```
## Every New Shell Session

4. Add the ghcup environment to your shell configuration (e.g., `~/.bashrc` or `~/.zshrc`):
```bash
echo 'source ~/.ghcup/env' >> ~/.bashrc # or ~/.zshrc
```
```bash
source ~/.ghcup/env
```

## Running Tests
That's it. The proxy config persists, ghcup/stack binaries persist, but the PATH doesn't.

From the `cli/` directory, run:
## Common Commands

```bash
STACK_ROOT=~/.stack stack test
```
# Build the project
cd cli && stack build

**Note:** The `STACK_ROOT=~/.stack` prefix is required in web/container environments to avoid permission issues with the default Stack root directory.
# Fast build (no optimizations, use during development)
stack build --fast

On first run, Stack will:
- Download and install GHC (Glasgow Haskell Compiler)
- Download the Hackage package index
- Build all project dependencies
- Build and run the tests
# Run tests
stack test

This initial setup can take several minutes. Subsequent runs will be much faster.
# Run tests fast
stack test --fast

## Building the CLI
# Run the CLI
stack exec graph -- <args>
stack exec graph -- --help
stack exec graph -- ls

To build the CLI executable:
# Format code (REQUIRED before commits)
ghcup install ormolu # once
find cli -name '*.hs' -exec ormolu --mode inplace {} \;

```bash
cd cli
STACK_ROOT=~/.stack stack build
# Lint code
stack install hlint # once
hlint cli/
```

To run the CLI:
## Errors You'll See (and Can Ignore)

```bash
STACK_ROOT=~/.stack stack exec graph -- <arguments>
**This is NORMAL:**
```
Warning: /root/.stack/config.yaml: Unrecognized fields in ConfigMonoid: http-proxy, https-proxy
```
Stack doesn't officially support these fields but uses them anyway. Ignore.

# Code Quality

## Formatting Code - Ormolu
This project uses [ormolu](https://github.com/tweag/ormolu) for consistent Haskell code formatting. All Haskell files must be formatted with ormolu before committing.

### Installing Ormolu
**This is NORMAL on first build:**
```
Preparing to download ghc-tinfo6-9.6.7 ...
ghc-tinfo6-9.6.7: download has begun
ghc-tinfo6-9.6.7: ... (lots of progress lines)
```
First build downloads ~200MB of GHC. Takes a few minutes. Subsequent builds are fast.

Install ormolu using ghcup:
## Errors That Mean Something Is Wrong

```bash
ghcup install ormolu
**TLS/SSL handshake failures:**
```
TLS HandshakeFailed (Error_Protocol ... HandshakeFailure)
```
**Fix:** You forgot the proxy config. Run the proxy config commands from "First Time Setup" above.

Or download it directly:

```bash
curl -L https://github.com/tweag/ormolu/releases/download/0.7.4.0/ormolu-x86_64-linux.zip -o ormolu.zip
unzip ormolu.zip
chmod +x ormolu
sudo mv ormolu /usr/local/bin/
**stack: command not found:**
```
/bin/bash: stack: command not found
```
**Fix:** Run `source ~/.ghcup/env`

### Formatting Files
**Permission denied on ~/.stack:**
```
Permission denied ... ~/.stack
```
**Fix:** This shouldn't happen with the config above, but if it does: `chmod -R u+w ~/.stack`

To format a single Haskell file:
## How It Works (for debugging)

```bash
ormolu --mode inplace path/to/File.hs
```
1. **ghcup** installs to `~/.ghcup/` and manages GHC/Stack/etc versions
2. **Stack** installs to `~/.ghcup/bin/stack` and stores its data in `~/.stack/`
3. The `~/.stack/config.yaml` file forces Stack to use the egress proxy
4. Without the proxy, Stack can't reach downloads.haskell.org or hackage.haskell.org
5. `source ~/.ghcup/env` adds `~/.ghcup/bin` to PATH

To format all Haskell files in the project:
## Quick Checks

```bash
find . -name '*.hs' -type f -print0 | xargs -0 ormolu --mode inplace
```
# Is ghcup installed?
ls ~/.ghcup/bin/

To check if files are formatted correctly without modifying them:
# Is Stack installed?
source ~/.ghcup/env && stack --version

```bash
find . -name '*.hs' -type f -print0 | xargs -0 ormolu --mode check
# Is proxy configured?
cat ~/.stack/config.yaml

# Can Stack reach the internet?
stack update # Should download Hackage index
```

**Note:** The GitHub CI will automatically check that all Haskell files are properly formatted. Make sure to format your code before pushing.
## Build Times Reference

## HLint
HLint is a linting tool that suggests improvements to Haskell code. The project is configured with a `.hlint.yaml` file at the repository root, and a GitHub Actions workflow enforces that shows HLint warnings on PRs.
- **First build:** 5-15 minutes (downloads GHC + all dependencies)
- **Subsequent clean builds:** 3-5 minutes
- **Incremental builds:** 10-30 seconds
- **Fast incremental builds:** 5-15 seconds

**Installing HLint:**
```bash
# Using Stack (recommended for this project)
stack install hlint apply-refact
```
## Code Quality Requirements

**Running HLint locally:**
```bash
# Check all Haskell files in the cli directory
hlint cli/
Before committing:
1. Format with ormolu: `find cli -name '*.hs' -exec ormolu --mode inplace {} \;`
2. Check lint: `hlint cli/` (fix what's reasonable)
3. Tests pass: `stack test`

# Check a specific file
hlint cli/src/Graph/Command.hs
GitHub CI will fail if formatting is wrong.

# Apply suggestions automatically (use with caution, only applicable to individual files)
hlint cli/src/Graph/Command.hs --refactor --refactor-options="--inplace"
```
## Pro Tips

**Common workflow:**
1. Run `hlint cli/` before committing your changes
2. Review the suggestions and apply fixes manually or using `--refactor`
- Use `--fast` during development, full builds only for final testing
- Install ormolu once: `ghcup install ormolu`
- The first Stack command in a new environment is slow (downloads GHC), be patient
- If builds seem stuck, they're probably downloading packages - check with `ps aux | grep stack`
- Stack caches aggressively - if something seems wrong, `stack clean` and rebuild
Loading