Commands Reference¶
emend’s public CLI is organized around a small set of top-level commands:
find– unified search, lookup, and summary outputedit– mutating refactors and code transformsanalyze– read-only code analysistool– operational and debugging commandscheck– unified project rules from.emend/rules.yamllint/policy– focused rule runners kept for compatibilitymap– identifier and module mappingsmcp– MCP server for LLM clients
Hidden compatibility aliases still exist. For example, emend rm maps to
emend edit rm, and legacy read commands such as search, grep,
show, get, and lookup route to emend find.
Global options¶
Global options must appear before the command name:
--language/-L– select a source grammar explicitly. This is useful for extensionless files or files whose suffix does not match their contents. The override applies to single files, directories, and globs.--version– print the installed emend version and exit.--verbose/-v– enable informational logging; repeat as-vvfor timestamped debug output.
For example, this treats generated.py as TypeScript throughout the batch
scan and replacement:
emend --language typescript edit replace '$X == $Y' '$X === $Y' generated.py --apply
Diff-scoped analysis¶
All analyze commands, plus lint, policy and check, accept
--diff [RANGE]. Put a bare --diff after positional arguments:
emend analyze deadcode . --diff
emend analyze dupes . --diff main..HEAD -v --min-lines 8
emend check . --diff
Without a range, staged changes take precedence. Otherwise emend compares HEAD
to its merge base with the current PR’s base (when gh is installed and the
PR can be resolved), or the repository’s default branch. Base refs must be
available locally; emend does not fetch or modify Git state. An explicit range
overrides automatic selection.
Combined merge diffs are not supported; select an explicit parent-to-merge range.
Analysis runs on the current working tree, preserving unchanged project context.
Reports select changed lines or overlapping symbol/function spans; duplicate
clusters retain unchanged partners. File-level facts match changed files.
impact instead uses changed symbols as roots and reports their dependents.
Deleted files have no current findings, but can still seed impact analysis.
An empty diff reports no selected findings. --diff cannot be combined with
--fix; it is a report filter, not authorization to edit other findings.
dupes -v includes source excerpts (full function diffs for --near).
--min-lines works for exact, sequence, and near matches; without the option,
the existing defaults remain three lines for exact/sequence and one for near.
find¶
Unified search: auto-detects pattern matching vs symbol lookup.
emend find [OPTIONS] QUERY [FILES]...
Canonical syntax is emend find [FLAGS] QUERY [FILES...].
Mode detection:
Query contains
$metavariables -> pattern modeQuery parses as a selector -> selector lookup mode
Bare file/directory path -> summary mode
PATH::QUERYkeeps file scope explicit while still auto-detecting the right-hand side as selector vs pattern
Useful options:
Option |
Description |
|---|---|
|
Filter symbol kind in lookup/summary mode |
|
Filter symbol names by glob or |
|
Filter by return annotation / inferred return |
|
Filter symbols by parameter name |
|
|
|
Structural containment for pattern mode |
|
Exclude pattern matches inside a structure |
|
Lookup-mode body/decorator filter |
|
Legacy compatibility shorthand |
|
Import-aware filter for pattern mode |
|
Exclude imported symbols in pattern mode |
|
Resolve dotted selectors through mappings |
|
Search embedded SQL/CSS/HTML regions |
Examples:
emend find 'print($X)' src/
emend find 'src/::assert False'
emend find file.py::handler[params]
emend find file.py --output summary::flat
emend find src/ --kind function --matching '@app.command'
emend find 'json.loads($X)' src/ --imported-from json
edit¶
Grouped code changes and refactors.
emend edit COMMAND [ARGS]...
Subcommands:
Subcommand |
Description |
|---|---|
|
Edit or replace existing symbol components |
|
Remove a symbol or component |
|
Safe delete with optional cascading removal |
|
Insert new items into list components |
|
Pattern-based replacement |
|
Copy a symbol to another file |
|
Rename a symbol or module |
|
Move a symbol or module with import updates |
|
Apply YAML/JSON refactoring batches |
|
Experimental equality-saturation rewrites |
Examples:
emend edit set api.py::get_user[returns] "User | None" --apply
emend edit add api.py::get_user[params] "timeout: int = 30" --apply
emend edit rm api.py::deprecated_func --apply
emend edit replace 'print($X)' 'logger.info($X)' src/ --apply
emend edit rename models.py::User --to Account --apply
emend edit mv utils.py::helper helpers/core.py --apply
emend edit cp workflow.py::Builder._build.helper tasks.py --dedent --apply
emend edit batch refactor.yaml --apply
Notes:
All write operations default to dry-run; add
--applyto write changes.Hidden aliases such as
emend rm,emend replace,emend add,emend rename, andemend mvstill work.
analyze¶
Read-only code analysis commands.
emend analyze COMMAND [ARGS]...
Subcommands:
Subcommand |
Description |
|---|---|
|
Find references to a symbol |
|
Generate call graphs |
|
Find potentially unused symbols and modules |
|
Compute transitive impact from a change |
|
Show inferred types |
|
Trace unsafe data flows |
|
Query the relational fact graph |
|
Show control-flow graphs |
|
Debug embedded DSL detection |
|
Find duplicate code via AST canonicalization |
Examples:
emend analyze refs src/api.py::process_request --calls-only
emend analyze graph src/app.py --format dot
emend analyze deadcode src/
emend analyze deadcode src/ --include-test-references
emend analyze deadcode src/ --exclude-private --no-unused-modules
emend analyze impact models.py::User --json
emend analyze impact models.py::User --output tests --json
emend analyze impact --diff HEAD --output graph
emend analyze trace src/ --preset flask --interprocedural
emend analyze facts --type references --symbol package.module.func --json
emend analyze cfg src/module.py --format json
emend analyze dupes src/ # scan whole tree
emend dupes src/ --near # near-clone review diffs
emend analyze dupes --check-file src/emend/foo.py --json # post-write hook
analyze dupes detects exact structural duplicates (alpha-renamed AST
subtrees) and sibling-sequence duplicates (shared statement runs across
functions) in Python, Rust, and TypeScript/JavaScript (including TSX/JSX).
All modes share language-configured parsing and canonicalization; clusters
never mix languages. Optional duplicate-cache prewarming supports the same
languages. Useful flags:
--mode exact|sequence|all– which detector(s) to run.--file PATH– restrict the scan to one file or directory (intra-scope only).--check-file PATH– scan the whole project and report only clusters with at least one member inPATH. Designed for post-write hooks; returns exit code 0 and empty JSON ([]) when nothing is found.--min-lines N/--min-score S– tighten the signal/noise floor.--json– machine-readable output with line ranges, scores, and members.
emend dupes PATH --near compares near-identical Python, Rust, and
TypeScript/JavaScript function bodies (including TSX/JSX) within each language and
prints their differences for review, not confirmed bugs. Use --json for
structured results and --limit to cap pairs (default: 50). Near mode does
not accept exact/sequence filters such as --mode or --check-file.
Post-write hook example (Claude Code settings.json): run the duplicate
check after every successful Edit/Write and surface non-trivial
findings back to the model.
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write|MultiEdit",
"hooks": [
{
"type": "command",
"command": "emend analyze dupes --check-file \"$CLAUDE_TOOL_FILE_PATH\" --min-score 100 --limit 5"
}
]
}
]
}
}
The equivalent MCP tool analyze(mode="duplicates", ...) can be
invoked by the model directly without a shell hook.
tool¶
Operational and debugging commands.
Project source discovery skips dot-directories (including .venv), venv,
node_modules, static, build, dist, and Cargo’s target directory.
Index progress counts all files analyzed for project facts, including non-Python
sources. Use emend tool index -v to log file starts and completions; subsequent
type-analysis and database phases are reported separately.
emend tool COMMAND [ARGS]...
Subcommands:
index– pre-build caches for faster cross-project operationseditor-search– one-shot JSON search for editorseditor-server– long-running stdio JSON-RPC server for the Vim plugin
Examples:
emend tool index
emend tool index src/ --jobs 8
emend tool editor-server
check, lint, and policy¶
check is the canonical rules entry point. It reads
.emend/rules.yaml by default and can run match, flow, deadcode, and type rules.
emend check [PATHS]... [OPTIONS]
Useful options:
--config– path torules.yaml--rule– run one named rule--kind– restrict tomatch,flow,deadcode, ortype--fix– apply auto-fixes for match rules--json– structured output
Examples:
emend check src/
emend check src/ --kind flow
emend check src/ --rule no-print --fix
lint and policy remain available for focused workflows and compatibility
with older configs. They fall back to .emend/rules.yaml when possible.
map¶
Cross-repo identifier and module mappings.
emend map add backend "UserService.create" gateway "POST /api/v1/users" --rel calls
emend map add-module payments --repo org/payments-service
emend map resolve payments.models.Order
mcp¶
Start the MCP server.
emend mcp
emend mcp --transport sse --port 8080
emend mcp --profile core
Profiles:
core– search, transform/references/analyze/check, grammar referencerefactor– alias forcoreexpert–refactorplus mappingsfull– canonical tools plus legacy compatibility tools
Install the optional MCP SDK v2 dependency with pip install 'emend[mcp]'.
MCP mode supports the same standard and free-threaded Python versions as the
core CLI.