summaryrefslogtreecommitdiff
path: root/.agent/coding_standards.md
blob: 955ec3592d16008b3453c2095b0e833a61ef8f08 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# Coding Standards — modal-shell

## Shell

- **Default shell:** bash. Shebang is always `#!/usr/bin/env bash`.
- **Strict mode:** Every file starts with `set -euo pipefail`. No exceptions.
- **No bashisms in base.sh:** `base.sh` must also be compatible with zsh (users may source it from their zsh config).
- **Functions over repetition:** If the same logic appears in two modes, move it to `base.sh`.
- **No global side effects in sourced files:** `base.sh` sets env vars; it does not print output, start processes, or modify files.

## Naming

- Mode files: lowercase, hyphen-separated, `.sh` suffix. e.g. `db.sh`, `build.sh`, `reset.sh`.
- Variables in `base.sh`: `UPPER_SNAKE_CASE`. Exported.
- Local variables in mode files: `lower_snake_case`. Use `local` inside functions.
- The dispatcher: `ms` (no extension, executable).

## Mode File Structure

```sh
#!/usr/bin/env bash
# <one-line description of what this mode does>
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/base.sh"

# mode logic here
```

## Confirmation Pattern for Destructive Modes

```sh
echo "This will destroy and rebuild the environment."
read -rp "Continue? [y/N] " confirm
[[ "$confirm" =~ ^[Yy]$ ]] || { echo "Aborted."; exit 1; }
```

## Error Handling

- Let `set -e` do the work. Do not swallow errors with `|| true` unless intentional and commented.
- On expected failure paths, print a helpful message to stderr before exiting: `echo "error: <message>" >&2`
- Do not use `exit 0` at the end of scripts — implicit success is fine.

## Testing

- Syntax check: `bash -n modes/<name>.sh` before committing any mode file.
- Dry-run: modes that exec into an environment can be tested with `bash -c 'source modes/base.sh && echo $PROJECT_ROOT'`.
- No automated test framework required for this project's scope. Manual verification is acceptable.

## The Dispatcher (`ms`)

- Must stay under 40 lines.
- No logic beyond: find the modes directory, match argument to filename, exec.
- If no argument: list available modes (strip `.sh`, sort).
- If unknown mode: print error to stderr, exit 1.
- Never source the mode file — always exec it (so the mode can itself exec into a shell without forking).

## What Not to Do

- No `eval`.
- No `set +e` blocks.
- No hardcoded paths outside of `base.sh`.
- No secrets in any file tracked by git.
- No modes that call other modes.