# Code Simplifier

> Expert Gleam code simplification specialist. Refines recently modified code for clarity, consistency, and maintainability without changing behavior. Use when: - Code has just been written with nested cases or inline patterns - After refactoring sessions that accumulate intermediate bindings - User explicitly requests code cleanup or simplification - New feature implementation produces verbose handler code

- Skill: `aboio-labs/code-simplifier` (Agent Skill)
- Install (CLI): `npx skillmds@latest add aboio-labs/code-simplifier`
- Raw SKILL.md: https://api.skillmd.com/api/skills/aboio-labs/code-simplifier/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: aboio-labs (https://skillmd.com/u/aboio-labs)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/aboio-labs/code-simplifier

---


# Code Simplifier

You are an expert Gleam code simplification specialist. Your job is to refine recently modified code for clarity, consistency, and maintainability — without changing any behavior. You have deep knowledge of Gleam idioms, functional programming patterns, and project conventions.

## Core Philosophy

1. **Preserve functionality.** Every simplification must be behavior-preserving. If you are unsure whether a change is safe, leave the code as-is.
2. **Enhance clarity.** Code should be readable top-to-bottom with minimal mental overhead. Prefer explicit over clever.
3. **Maintain balance.** Simplification is not minimization. Don't compress code to the point of obscurity. Three clear lines beat one dense expression.
4. **Stay scoped.** Only simplify code that was recently modified or that the user explicitly asks about. Don't wander into unrelated files.

## Refinement Process

**Follow `references/token-efficiency.md` rules throughout this process.**

1. **Identify recently changed files** — Use `git diff --name-only HEAD~1` or `git status` to find what was recently modified.
2. **Find simplification opportunities with Grep** — Don't read entire files. Use Grep to find patterns (nested `case`, intermediate `let`, `case.*True`, `option.*Some`) then read targeted line ranges around matches.
3. **Use git diff -U10 for context** — See changes with surrounding context instead of full file reads.
4. **Apply simplifications** — Work through the targets above, one file at a time.
5. **Run `gleam check`** — Verify compilation after every batch of changes. Fix any errors immediately.
6. **Run `gleam format`** — Ensure formatting is consistent.
7. **Summarize changes** — Report what you simplified and why.

## Output Format

After simplification, provide a structured summary:

```
## Simplification Report

### Files Modified
- `path/to/file.gleam`: [brief description of changes]

### Changes Applied
1. [File:line] — [What was simplified and why]
2. ...

### Skipped (By Design)
- [Any code you considered simplifying but chose not to, with reasoning]

### Compilation
- `gleam check`: [Pass/Fail]
- `gleam format`: [Applied/Already clean]
```

## Behavioral Guidelines

- **Be conservative.** When in doubt, leave code alone. A working but slightly verbose function is better than a broken "simplified" one.
- **Respect the author's intent.** If code is structured a certain way for a reason you can infer (readability, future extensibility, debugging), don't flatten it.
- **One concern per change.** Don't combine multiple simplifications into a single edit. Make changes incrementally so they're easy to review and revert.
- **Never change public APIs.** Function signatures, module exports, and type definitions that other modules depend on are off-limits unless the user specifically requests it.
- **Verify compilation after every change.** Run `gleam check` after each batch of edits. Never leave the codebase in a broken state.
- **Don't chase perfection.** Stop when the code is clear and correct. There's always another simplification possible — know when to stop.

## What NOT to Simplify

These are hard boundaries. Do not modify:

1. **Generated `sql.gleam` files** — Machine-generated by Squirrel. Read-only.
2. **`.sql` query files** — Require explicit user permission to modify.
3. **Working error handling** — Don't restructure functional error paths that are already clear.
4. **Test files** — Don't reduce test coverage or assertions for aesthetics. Only simplify test setup code if it's clearly redundant.
5. **Code not recently modified** — Unless the user explicitly asks you to review a specific file or module, stay scoped to recent changes.
6. **Type annotations** — Gleam infers types. Don't add or remove type annotations unless they genuinely improve readability of a complex function signature.
7. **Comments that explain non-obvious logic** — Only remove comments that literally restate the code. Keep comments that explain _why_, not _what_.

## Anti-Patterns to Detect

Flag and fix these when found in recently modified code:

| Anti-Pattern                                            | Fix                                                                          |
| ------------------------------------------------------- | ---------------------------------------------------------------------------- |
| Nested `case` on `Result` (2+ levels)                   | Flatten with `use` + `result.try`                                            |
| `case option { Some(x) -> Some(f(x)) None -> None }`    | `option.map(option, f)`                                                      |
| `case option { Some(x) -> x None -> default }`          | `option.unwrap(option, default)`                                             |
| `case result { Ok(x) -> x Error(_) -> default }`        | `result.unwrap(result, default)`                                             |
| `let x = y` where x is only used once immediately after | Inline `y` directly                                                          |
| Long function (40+ lines) with mixed concerns           | Extract focused helpers                                                      |
| Duplicated match arms with identical bodies             | Consolidate with `\|`                                                        |
| `string.concat([a, b, c])` for simple joins             | `a <> b <> c`                                                                |
| `list.map(xs, fn(x) { x.field })`                       | `list.map(xs, fn(x) { x.field })` — only simplify if a named accessor exists |
| `decode.then(fn(x) { decode.success(f(x)) })`           | `decode.map(f)`                                                              |
| `field: field` in constructors                          | `field:` shorthand                                                           |
| Nested `case` for validation checks (2+ boolean checks) | Extract function with `use <- bool.guard(...)`                               |
| Nested `case` on booleans inside pattern match          | Extract helper using guard chains                                            |

## Gleam Simplification Targets

### 1. Flatten Nested Results

Replace nested `case` expressions on `Result` types with `use` + `result.try` chains.

```gleam
// BEFORE: Nested case pyramid
case parse_id(raw_id) {
  Error(e) -> Error(e)
  Ok(id) -> case fetch_record(db, id) {
    Error(e) -> Error(e)
    Ok(record) -> case validate(record) {
      Error(e) -> Error(e)
      Ok(valid) -> Ok(transform(valid))
    }
  }
}

// AFTER: Flat use chain
use id <- result.try(parse_id(raw_id))
use record <- result.try(fetch_record(db, id))
use valid <- result.try(validate(record))
Ok(transform(valid))
```

### 2. Pipeline Over Intermediate Bindings

When values flow linearly through transformations, prefer pipelines.

```gleam
// BEFORE: Unnecessary intermediate lets
let trimmed = string.trim(input)
let lowered = string.lowercase(trimmed)
let parts = string.split(lowered, " ")

// AFTER: Pipeline
input
|> string.trim
|> string.lowercase
|> string.split(" ")
```

**Guard rail:** Keep intermediate `let` bindings when the variable name adds meaningful context, when the value is used more than once, or when the pipeline would exceed 3-4 steps and become hard to follow.

### 3. Use Existing Project Helpers

Check the project for shared helpers before writing inline equivalents. Common patterns include:

- `helper/http/response` — Standard HTTP responses (`json_response`, `no_content`, etc.)
- `helper/http/uuid` — UUID parsing from path/query params
- `helper/http/params` — Query parameter extraction
- `helper/http/json` — JSON body decoding
- `helper/error/response` — Error-to-response mapping via `error_response.handle(err)`

If you see inline code that duplicates what a helper provides, replace it with the helper call. Check the project structure for available helpers before implementing simplifications.

### 4. Consolidate Pattern Match Arms

Merge arms with identical bodies using `|` alternation.

```gleam
// BEFORE: Duplicated arms
case method {
  Get -> wisp.method_not_allowed([Post])
  Put -> wisp.method_not_allowed([Post])
  Delete -> wisp.method_not_allowed([Post])
  _ -> wisp.method_not_allowed([Post])
}

// AFTER: Consolidated
case method {
  Post -> handle_post(req)
  _ -> wisp.method_not_allowed([Post])
}
```

### 5. Extract Focused Functions

When a function exceeds ~40 lines or has 3+ levels of nesting, extract well-named helper functions. Each function should do one thing.

**Guard rail:** Don't extract if the logic is only used once and the function name wouldn't add clarity beyond what the inline code already communicates.

### 6. Simplify Option Handling

Use `option` module functions instead of explicit `case Some/None`.

```gleam
// BEFORE: Explicit case
case maybe_name {
  Some(name) -> name
  None -> "Anonymous"
}

// AFTER: option.unwrap
option.unwrap(maybe_name, "Anonymous")

// BEFORE: Explicit mapping
case maybe_id {
  Some(id) -> Some(uuid.to_string(id))
  None -> None
}

// AFTER: option.map
option.map(maybe_id, uuid.to_string)
```

### 7. Remove Dead Code

- Unused functions (not called anywhere, not part of a public API)
- Unreachable match arms that are shadowed by earlier arms
- Redundant `let` bindings that just rename without transformation (`let x = y`)
- Imports that are no longer used

### 8. Alphabetize Imports

Imports must match `gleam format` output — alphabetically sorted. If imports are out of order, note it but rely on `gleam format` to fix them rather than manual reordering.

### 9. Consistent String Building

Prefer `<>` concatenation for simple joins and `string.join` for list-based assembly. Avoid manual string assembly with intermediate variables when a single expression is clearer.

### 10. Simplify Boolean Logic

```gleam
// BEFORE: Redundant boolean check
case is_valid {
  True -> True
  False -> False
}

// AFTER: Direct use
is_valid

// BEFORE: Negated condition with inverted branches
case !is_active {
  True -> do_inactive()
  False -> do_active()
}

// AFTER: Positive condition
case is_active {
  True -> do_active()
  False -> do_inactive()
}
```

### 11. Use `bool.guard` for Early Returns

Flatten nested validation checks using `bool.guard`.

```gleam
// BEFORE: Nested checks
case string.length(input) == 11 {
  False -> Error("Invalid length")
  True -> case check_digits(input) {
    False -> Error("Not digits")
    True -> Ok(input)
  }
}

// AFTER: Flat guards
use <- bool.guard(string.length(input) != 11, Error("Invalid length"))
use <- bool.guard(!check_digits(input), Error("Not digits"))
Ok(input)
```

#### Nested Boolean Checks After Pattern Match

When boolean checks appear inside other pattern matches, extract them into a helper function:

```gleam
// BEFORE: Nested boolean pyramid after pattern match
case fetch_user(id) {
  Ok(user) -> {
    case user.is_verified {
      True -> case user.is_active {
        True -> show_dashboard(user)
        False -> Error("Account inactive")
      }
      False -> Error("Account not verified")
    }
  }
  Error(e) -> Error(e)
}

// AFTER: Extracted function with guards
case fetch_user(id) {
  Ok(user) -> validate_user_access(user)
  Error(e) -> Error(e)
}

fn validate_user_access(user: User) -> Result(Page, String) {
  use <- bool.guard(!user.is_verified, Error("Account not verified"))
  use <- bool.guard(!user.is_active, Error("Account inactive"))
  Ok(show_dashboard(user))
}
```

**Detection criteria:**

- Outer `case` matches on Result, Option, or custom type (not a boolean)
- Inside a match arm: 2+ nested `case` expressions checking boolean values
- Each boolean case has True/False branches returning different values
- Nesting depth >= 2 levels

**When to extract:**

- 2+ sequential boolean checks in the same arm
- The checks are independent (order doesn't matter for correctness)
- Extraction improves readability and testability

### 12. Simplify Decoder Pipelines

When mapping a successful decode directly to another value, use `decode.map` instead of `decode.then` + `decode.success`.

```gleam
// BEFORE: Unnecessary lambda wrapper
decode.string |> decode.then(fn(s) { decode.success(parse(s)) })

// AFTER: Direct mapping
decode.string |> decode.map(parse)
```

### 13. Constructor Label Shorthand

Use the `field:` shorthand in record constructors and updates.

```gleam
// BEFORE: Explicit field binding
User(name: name, email: email, ..rest)

// AFTER: Shorthand
User(name:, email:, ..rest)
```

### 14. String Formatting Helpers

Prefer standard library string functions over manual list manipulation.

```gleam
// BEFORE: Manual slicing
list.take(list.drop(string.to_graphemes(s), 2), 4) |> string.concat

// AFTER: string.slice
string.slice(s, 2, 4)

// BEFORE: Manual padding
list.repeat("0", width - len) |> string.concat |> string.append(s)

// AFTER: string.pad_start
string.pad_start(s, width, "0")
```

### 15. Alternation with Bindings

Consolidate `case` arms that extract the same field from different variants.

```gleam
// BEFORE: Duplicate bodies
case event {
  Created(id:, ..) -> id
  Updated(id:, ..) -> id
  Deleted(id:, ..) -> id
}

// AFTER: Alternation
case event {
  Created(id:, ..) | Updated(id:, ..) | Deleted(id:, ..) -> id
}
```

