Small command-line control surfaces for app and editor integrations.
Boring JSON surgery for tools that should not each own it.
ctl is a shiv-installable CLI for app and editor integrations that need a small, reusable command surface. Its first namespace manages Zed task and keymap JSON.
The immediate extraction target is comments integrations zed: it should not own generic Zed JSON upsert logic forever. ctl zed tasks ... gives that logic one home so other tools can reuse it.
This is intentionally not a plugin framework. Add the next app namespace only after a concrete workflow proves the shape.
shiv install ctl# Print the caller project's Zed tasks file path.
ctl zed tasks path
# Print tasks as JSON. Missing file means [].
ctl zed tasks list
# Insert or replace one task by label.
ctl zed tasks upsert \
--label "comments: dispatch current file" \
--command comments \
--arg dispatch \
--arg '$ZED_FILE' \
--save current \
--reveal never \
--hide on_success \
--shell-program /bin/zsh \
--shell-arg=-f \
--env COMMENT_CHAT_AS=or
# Remove tasks with a matching label.
ctl zed tasks remove --label "comments: dispatch current file"All commands target the caller directory's .zed/tasks.json. Existing tasks are preserved. Upsert replaces tasks with the same label and appends when the label is new. Optional reveal, shell, and environment fields are emitted only when the caller supplies them. Invalid values, invalid JSON, or a non-array tasks file fail without clobbering the file.
# Print the global Zed keymap file path.
ctl zed keymap path
# Check whether a binding can be installed without conflicts.
ctl zed keymap check-task --keystroke cmd-shift-d --task "comments: dispatch current file"
# Bind a key to spawn a named task.
ctl zed keymap bind-task --keystroke cmd-shift-d --task "comments: dispatch current file"
# Check/bind rerun with fresh Zed context.
ctl zed keymap check-rerun --keystroke cmd-shift-r
ctl zed keymap bind-rerun --keystroke cmd-shift-r --reevaluate-context
# Check/bind a concrete inline snippet action.
ctl zed keymap check-snippet --context 'Editor && extension == md' --keystroke 'cmd-k i' --snippet '<!-- ! "@ikma ${1:feedback}" | mise comment -->$0'
ctl zed keymap bind-snippet --context 'Editor && extension == md' --keystroke 'cmd-k i' --snippet '<!-- ! "@ikma ${1:feedback}" | mise comment -->$0'Keymap commands target Zed's global keymap.json. Existing bindings are preserved. If a requested keystroke already has a different binding in the target context, ctl fails without clobbering it unless --force is passed.
Shiv resolves space-separated commands to mise's colon-delimited task names. Inside this repo, call the tasks directly:
mise run zed:tasks:path
mise run zed:tasks:list
mise run zed:tasks:upsert --label example --command echo --arg hello
mise run zed:tasks:remove --label example
mise run zed:keymap:path
mise run zed:keymap:check-task --keystroke cmd-shift-d --task example
mise run zed:keymap:bind-task --keystroke cmd-shift-d --task example
mise run zed:keymap:check-rerun --keystroke cmd-shift-r
mise run zed:keymap:bind-rerun --keystroke cmd-shift-r
mise run zed:keymap:check-snippet --context Editor --keystroke 'cmd-k i' --snippet 'Hello ${1:there}$0'
mise run zed:keymap:bind-snippet --context Editor --keystroke 'cmd-k i' --snippet 'Hello ${1:there}$0'When installed by shiv, the shim exports CTL_CALLER_PWD before running the task. ctl uses that package-scoped variable to decide which project owns .zed/tasks.json. It does not read generic CALLER_PWD.
| Task | Description |
|---|---|
mise run doctor |
Check local development setup |
mise run test |
Run BATS tests |
mise run zed:keymap:bind-rerun |
Bind a Zed key to rerun the last task |
mise run zed:keymap:bind-snippet |
Bind a Zed key to insert an inline snippet |
mise run zed:keymap:bind-task |
Bind a Zed key to spawn a named task |
mise run zed:keymap:check-rerun |
Check whether a Zed rerun key binding can be installed |
mise run zed:keymap:check-snippet |
Check whether a Zed snippet key binding can be installed |
mise run zed:keymap:check-task |
Check whether a Zed task key binding can be installed |
mise run zed:keymap:path |
Print the global Zed keymap.json path |
mise run zed:tasks:list |
Print project-local Zed tasks as JSON |
mise run zed:tasks:path |
Print the project-local Zed tasks.json path |
mise run zed:tasks:remove |
Remove a project-local Zed task by label |
mise run zed:tasks:upsert |
Insert or replace a project-local Zed task by label |
| Path | Status | Purpose |
|---|---|---|
mise.toml |
✓ | tools, settings, and codebase lint config |
README.tsx |
✓ | programmable README source |
CONTRIBUTING.md |
✓ | repo-entry orientation surface |
.mise/tasks/zed/tasks/ |
✓ | Zed tasks.json commands |
.mise/tasks/zed/keymap/ |
✓ | Zed keymap.json commands |
lib/zed/tasks.sh |
✓ | shared Zed task JSON helpers |
lib/zed/keymap.sh |
✓ | shared Zed keymap JSON helpers |
test/ |
✓ | BATS coverage through mise |
.github/workflows/test.yml |
✓ | Ubuntu/macOS CI |
Current convention checks
This repo asks codebase to run these lint rules:
mise-settings
bats-test-helper
bats-test-task
mcr-scope
or-true
shellcheck
gum-table
caller-pwd-contract
github-actions
mise run test
mise run doctor
codebase lint "$PWD"
readme build --check
git diff --checkThe suite currently has 34 tests and 13 public tasks. CI runs on ubuntu-latest + macos-latest.
This README was generated from `README.tsx` with [KnickKnackLabs/readme](https://github.com/KnickKnackLabs/readme).
Keep integrations boring until the second caller proves otherwise.