| update-when | CLI commands, output format, or installation steps change |
|---|
A CLI and MCP server for querying and editing Elm files β like jq for Elm.
Designed as a next-gen LSP for agents and scripts, not editors. Optimized for token efficiency and structured tool calling.
Status: Active development. Supports reading and writing Elm declarations, imports, and module lines. MCP server available via
elmq mcp. See ROADMAP.md for what's planned.
brew install caseyWebb/tap/elmqRequires Rust:
cargo install --path .elmq list src/Main.elmmodule Main exposing (Model, Msg(..), update, view)
imports:
Html exposing (Html, div, text)
Html.Attributes as Attr
type aliases:
Model L4-8
types:
Msg L11-15
functions:
update Msg -> Model -> Model L18-28
view Model -> Html Msg L31-34
helper L37-38
elmq list src/Main.elm --docstype aliases:
Model L4-8
The model for our app
types:
Msg L11-15
Messages for the update function
...
elmq get src/Main.elm updateupdate : Msg -> Model -> Model
update msg model =
case msg of
Increment ->
{ model | count = model.count + 1 }
Decrement ->
{ model | count = model.count - 1 }
Reset ->
{ model | count = 0 }
Includes doc comments and type annotations when present. Returns non-zero exit code if the declaration is not found.
echo 'helper x =
x + 42' | elmq set src/Main.elmReads a full declaration from stdin, parses the name, and replaces the existing declaration (or appends if new). Use --name to override:
echo 'renamed x = x + 1' | elmq set src/Main.elm --name helperelmq patch src/Main.elm update --old "model.count + 1" --new "model.count + 2"Surgical find-and-replace scoped to a single declaration. The --old string must match exactly once.
elmq rm src/Main.elm helperRemoves the declaration, its type annotation, and doc comment. Cleans up excess blank lines.
elmq import add src/Main.elm "Browser exposing (element)"
elmq import remove src/Main.elm Htmlimport add inserts in alphabetical order or replaces an existing import with the same module name.
elmq expose src/Main.elm update
elmq expose src/Main.elm "Msg(..)"
elmq unexpose src/Main.elm helperGranularly add or remove items from the module's exposing list. If the module has exposing (..), unexpose auto-expands to an explicit list then removes the target. expose is a no-op when exposing (..). Neither command ever produces exposing (..).
elmq mv src/Foo/Bar.elm src/Foo/Baz.elmrenamed src/Foo/Bar.elm -> src/Foo/Baz.elm
updated src/Main.elm
updated src/Page/Home.elm
Renames the file, updates the module declaration, and rewrites all imports and qualified references (Foo.Bar.something -> Foo.Baz.something) across the project. Requires elm.json in a parent directory. Use --dry-run to preview changes without writing.
elmq rename src/Main.elm helper newHelperrenamed helper -> newHelper
updated src/Main.elm
updated src/Page/Home.elm
Renames a declaration (function, type, type alias, port, or variant) in the defining file and updates all references across the project β including qualified (Module.helper), aliased (M.helper), and exposed references. Requires elm.json in a parent directory. Use --dry-run to preview changes without writing.
elmq refs src/Lib/Utils.elmsrc/Main.elm:3
src/Page/Home.elm:5
src/Page/Settings.elm:3
Find all files that import a module. Add a declaration name to find specific usage sites:
elmq refs src/Lib/Utils.elm helpersrc/Page/Home.elm:3: import Lib.Utils exposing (helper)
src/Page/Settings.elm:5: LU.helper config
src/Main.elm:7: Lib.Utils.helper model
Resolves fully-qualified references (Lib.Utils.helper), aliased references (LU.helper), and explicitly-exposed names. Requires elm.json in a parent directory.
elmq rename src/Main.elm helper helperV2renamed helper -> helperV2
updated src/Page/Home.elm
Renames a declaration (or type constructor) and updates all references across the project. Handles qualified, aliased, and bare-exposed references. Use --dry-run to preview changes.
elmq move-decl src/Page/Home.elm --name viewHeader --name viewFooter --to src/Shared/Layout.elmmoved viewHeader
moved viewFooter
auto-included renderNav
updated src/Page/Home.elm
updated src/Shared/Layout.elm
updated src/Main.elm
Moves declarations from one module to another, rewriting the declaration bodies to match the target file's import conventions (aliases, exposed names). Automatically includes unexposed helpers used only by the moved declarations. Creates the target file if it doesn't exist. Auto-upgrades the target to a port module when moving ports.
Use --copy-shared-helpers to duplicate (not move) helpers that are used by both moved and non-moved declarations. Use --dry-run to preview changes.
elmq variant add src/Types.elm --type Msg "SetName String"added SetName to Msg in src/Types.elm
src/Update.elm:22 update β inserted branch
src/View.elm:15 label β inserted branch
src/Main.elm:31 update β skipped (wildcard branch covers new variant)
Appends a constructor to a custom type and inserts Debug.todo branches in all matching case expressions project-wide. Case expressions with wildcard (_) branches are skipped with an info message.
elmq variant rm src/Types.elm --type Msg Decrementremoved Decrement from Msg in src/Types.elm
src/Update.elm:22 update β removed branch
src/View.elm:15 label β removed branch
Removes a constructor and its matching branches from all case expressions. Errors if removing the last variant (use elmq rm instead). Use --dry-run to preview changes.
elmq list src/Main.elm --format json{
"module_line": "module Main exposing (Model, Msg(..), update, view)",
"imports": ["Html exposing (Html, div, text)"],
"declarations": [
{
"name": "update",
"kind": "function",
"type_annotation": "Msg -> Model -> Model",
"start_line": 18,
"end_line": 28
}
]
}Start the MCP server (stdio transport):
elmq mcpExposes 4 tools optimized for LLM agents:
| Tool | Description |
|---|---|
elm_summary |
File overview: module, imports, declarations with types and line numbers |
elm_get |
Extract full source text of a declaration by name |
elm_edit |
All file mutations: set, patch, rm, mv, rename, move_decl, add_variant, rm_variant, add_import, remove_import, expose, unexpose |
elm_refs |
Find all references to a module or declaration across the project |
Configure in your MCP client (e.g. Claude Code settings.json):
{
"mcpServers": {
"elmq": {
"command": "elmq",
"args": ["mcp"]
}
}
}See ROADMAP.md for the phased development plan.