---
name: editing-tools
description: CLI tools and patterns for efficient code search and editing. ast-grep for structural patterns, ripgrep for text, sd for batch replace, Context7 / Grep MCP for library docs, ~/.agent-scratch/ logs for long tasks. Use when you need to find, search, or batch-modify code across the repo. Portable.
---

# Editing tools

## Code search

### ripgrep (`rg`) — text search

Faster and saner-by-default than `grep`. Already on most modern dev
machines.

```bash
rg "pattern" --type ts
rg "TODO" --glob "*.tsx"
rg "useState<[^>]+>" -t ts --context 2
```

- `--type ts` / `--type tsx` for scoping
- `--glob` for finer control
- `--context N` for surrounding lines
- Returns nothing on no match (good for scripting)

### ast-grep — structural search

When you need to match on code *shape*, not text. Use for refactors and
"find all calls to X with these arg patterns" type queries.

```bash
# TypeScript
ast-grep --lang typescript -p 'const $VAR = $_'
ast-grep --lang typescript -p 'useState<$T>($$$)'
ast-grep --lang typescript -p 'export function $NAME($$$): $RET { $$$ }'

# TSX
ast-grep --lang tsx -p '<$COMP $$$>$$$</$COMP>'
ast-grep --lang tsx -p '<motion.$EL $$$ />'
```

Pattern syntax:
- `$VAR` — single identifier
- `$_` — single node (anything)
- `$$$` — multiple nodes (one or more)

### `fd` — file finder

Use instead of `find`. Faster, saner defaults.

```bash
fd '\.tsx$' src
fd 'SKILL\.md' .claude
fd . src/components --type f
```

## Batch replace

For mechanical refactors across the tree.

### `sd` — string-replace (preferred)

```bash
fd '\.ts$' src -x sd 'from "zod"' 'from "zod/v4"'
```

### Fallback: `find -exec`

```bash
fd '\.ts$' src -x sed -i '' 's/foo/bar/g'    # macOS BSD sed
```

Always preview before applying:

```bash
fd '\.ts$' src -x rg -l 'pattern' {}         # which files match?
```

## Library docs (when training data isn't enough)

### Context7 MCP

For up-to-date library reference docs. Use the resolve / get-docs flow:

```
resolve-library-id    # find library ID from name
get-library-docs      # focused docs for a topic
```

Trigger phrases: "how does X work in motion/react", "what's the API
for @dnd-kit/core useDraggable", "Capacitor 8 camera plugin signature."

### Grep MCP

For finding usage patterns in real public repos. Useful when docs
are thin and you want to see how others actually use a library.

```
grep    # search millions of public GitHub repos
```

### Fallback: `.d.ts` files

When MCP isn't available or docs are stale:

```bash
fd 'index\.d\.ts' node_modules/motion -t f
cat node_modules/motion/dist/types/index.d.ts | head -100
```

## Long-running tasks

Pipe to a timestamped log under `~/.agent-scratch/` instead of waiting in the
terminal:

```bash
nohup bun run build > $HOME/.agent-scratch/$(date +%Y%m%d-%H%M%S)-build.log 2>&1 &
tail -f $HOME/.agent-scratch/20260510-184532-build.log
```

Convention: `~/.agent-scratch/{YYYYMMDD-HHMMSS}-{task-name}.log`. Makes it easy to
correlate across attempts.

For repeated commands while debugging, write the script to a `~/.agent-scratch/`
file first so you can edit and re-run without retyping:

```bash
cat > $HOME/.agent-scratch/check-types.sh <<'EOF'
#!/usr/bin/env bash
set -e
bun run typecheck 2>&1 | tee $HOME/.agent-scratch/$(date +%H%M%S)-tc.log
EOF
chmod +x $HOME/.agent-scratch/check-types.sh
$HOME/.agent-scratch/check-types.sh
```

## ESLint suppressions

Tabbit uses ESLint. Suppressions go inline with a reason:

```ts
// eslint-disable-next-line react-hooks/exhaustive-deps
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- third-party type missing
```

Use sparingly. Prefer fixing the root issue. If a suppression sticks
around, the comment must explain *why* it's permanent, not "TODO".

## Repo-specific commands

These are tabbit's package.json scripts; check `package.json` if any
fail:

```bash
bun run dev              # vite dev server (no api routes)
bun run build            # production build
bun run lint             # eslint
bun run typecheck        # tsc -b on app + api
bun run mobile:sync      # build + cap sync
bun run verify:web:smoke # playwright smoke
bun run verify:smoke     # web + ios + android smoke (the verify harness)
```

For local API testing, `vercel dev` instead of `bun run dev` — the
serverless functions aren't served by Vite.

## When to reach for which tool

| Task | Tool |
|---|---|
| "Find where this function is called" | `rg` |
| "Find all components that use this prop" | `ast-grep` |
| "Find files matching a name pattern" | `fd` |
| "Rename a symbol everywhere" | `ast-grep --rewrite` or `sd` |
| "What's the latest API for X library" | Context7 MCP |
| "Show me how others use X" | Grep MCP |
| "Run a 5-minute build without blocking" | `nohup` to `~/.agent-scratch/` log |
| "Re-run a script I'm iterating on" | save to `~/.agent-scratch/`, chmod, run |

## Anti-patterns

- `grep -r` over a large tree (use `rg`)
- `find . -name X` (use `fd`)
- Piping `bun run build` directly without logging (you'll wish you'd
  captured the output)
- Inline sed scripts with escaped quotes (use a `~/.agent-scratch/` script file)
- `node_modules` deletion and reinstall to debug — almost never the
  fix; check the lockfile first
