SKILL.md

 1---
 2name: shell-builtins
 3description: Use when creating a new shell builtin command for Crush (internal/shell/), editing an existing one, or when the user needs to understand how commands are intercepted in Crush's embedded shell.
 4---
 5
 6# Shell Builtins
 7
 8Crush's shell (`internal/shell/`) uses `mvdan.cc/sh/v3` for POSIX shell
 9emulation. Commands can be intercepted before they reach the OS by adding
10**builtins** — functions handled in-process.
11
12## How Builtins Work
13
14Builtins live in `Shell.builtinHandler()` in `internal/shell/shell.go`.
15This is an `interp.ExecHandlerFunc` middleware registered in
16`execHandlers()` **before** the block handler, so builtins run even for
17commands that would otherwise be blocked.
18
19The handler is a switch on `args[0]`. Each case either handles the command
20inline or delegates to a helper function.
21
22## Adding a New Builtin
23
241. **Add the case** to the switch in `builtinHandler()` in `shell.go`.
252. **Get I/O from the handler context**, not from `os.Stdin`/`os.Stdout`.
26   This ensures the builtin works with pipes and redirections:
27   ```go
28   case "mycommand":
29       hc := interp.HandlerCtx(ctx)
30       return handleMyCommand(args, hc.Stdin, hc.Stdout, hc.Stderr)
31   ```
323. **Implement the handler** in its own file (e.g.,
33   `internal/shell/mycommand.go`). The function signature should accept
34   args, stdin, stdout, and stderr:
35   ```go
36   func handleMyCommand(args []string, stdin io.Reader, stdout, stderr io.Writer) error {
37       // args[0] is the command name ("mycommand"), args[1:] are arguments.
38       // Write output to stdout, errors to stderr.
39       // Return nil on success, or interp.ExitStatus(n) for non-zero exit codes.
40   }
41   ```
424. **Return values**: return `nil` for success, `interp.ExitStatus(n)` for
43   non-zero exit codes. Write error messages to `stderr` before returning.
445. **No extra wiring needed** — `builtinHandler()` is already registered
45   in `execHandlers()`.
46
47## Existing Builtins
48
49| Command | File | Description |
50|---------|------|-------------|
51| `jq` | `jq.go` | JSON processor using `github.com/itchyny/gojq` |