@chorded/chord 0.54.0 → 0.55.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +141 -554
- package/package.json +19 -5
package/README.md
CHANGED
|
@@ -1,591 +1,178 @@
|
|
|
1
|
-
|
|
1
|
+
<h1 align="center">chord</h1>
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<strong>One terminal for every coding agent.</strong><br>
|
|
5
|
+
Claude Code, Codex, Gemini CLI, Cursor, OpenCode and 30 more, in one
|
|
6
|
+
keyboard-driven window, side by side, working as a team.
|
|
7
|
+
</p>
|
|
8
|
+
|
|
9
|
+
<p align="center">
|
|
10
|
+
<a href="https://www.npmjs.com/package/@chorded/chord"><img alt="npm" src="https://img.shields.io/npm/v/@chorded/chord?color=47e7a5&label=npm"></a>
|
|
11
|
+
<a href="https://github.com/IKatsuba/chord/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/IKatsuba/chord/actions/workflows/ci.yml/badge.svg"></a>
|
|
12
|
+
<a href="LICENSE"><img alt="MIT licence" src="https://img.shields.io/badge/licence-MIT-blue"></a>
|
|
13
|
+
<img alt="macOS and Linux" src="https://img.shields.io/badge/platform-macOS%20%7C%20Linux-lightgrey">
|
|
14
|
+
</p>
|
|
15
|
+
|
|
16
|
+
<p align="center">
|
|
17
|
+
<img src="docs/images/team.png" alt="chord handing an issue to a team: a lead, a tester on Claude and a coder on Codex, each with its state in the list under the prompt" width="900">
|
|
18
|
+
</p>
|
|
19
|
+
|
|
20
|
+
chord brings Claude Code, Codex, Gemini CLI and other coding agents into one
|
|
21
|
+
terminal interface: the same transcript, diffs, permission prompts, slash
|
|
22
|
+
commands, `@` mentions and plans. It connects to agents through the
|
|
23
|
+
[Agent Client Protocol](https://agentclientprotocol.com).
|
|
24
|
+
|
|
25
|
+
Run agents side by side or give a task to a team. For example, have Codex
|
|
26
|
+
write a fix and Claude review it, each with its own model and role. Agents
|
|
27
|
+
exchange messages, permission requests come to you, and a saved team can
|
|
28
|
+
take on your next task.
|
|
2
29
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
of it.
|
|
30
|
+
```sh
|
|
31
|
+
npm install -g @chorded/chord
|
|
32
|
+
chord # Claude Code, here
|
|
33
|
+
chord codex # or any other agent
|
|
34
|
+
```
|
|
9
35
|
|
|
10
|
-
|
|
11
|
-
> text, and answer the agent's permission requests and forms; tool calls and
|
|
12
|
-
> the rest are on their way.
|
|
13
|
-
> `docs/FEATURES.md` is the map of what is coming and in which order.
|
|
36
|
+
## Why chord
|
|
14
37
|
|
|
15
|
-
|
|
38
|
+
- **Any agent, one interface.** 35 agents out of the box, from the
|
|
39
|
+
[ACP Registry](https://agentclientprotocol.com) and their own CLIs. Switch
|
|
40
|
+
agents without relearning keys.
|
|
41
|
+
- **Agents that work together.** Open a second agent beside the one you talk
|
|
42
|
+
to, hand a job to a saved team, and watch each of them in a list under the
|
|
43
|
+
prompt. Messages go between them; permissions still come to you.
|
|
44
|
+
- **Every action has a key.** Nothing on screen needs a mouse. `?` lists them
|
|
45
|
+
all, and a keybindings file moves them.
|
|
46
|
+
- **Nothing to set up.** One binary, no account, no daemon. chord starts the
|
|
47
|
+
agent, keeps the session, and gives it back with `chord --continue`.
|
|
48
|
+
- **Open source.** MIT, built on [OpenTUI](https://github.com/anomalyco/opentui)
|
|
49
|
+
and the [ACP SDK](https://github.com/agentclientprotocol/typescript-sdk).
|
|
16
50
|
|
|
17
|
-
|
|
18
|
-
coding agent, and it only talks to Claude. ACP separates the agent from the
|
|
19
|
-
interface, so the interface can be one program and the agent anything. chord is
|
|
20
|
-
that program: open source, one binary, one window, any agent.
|
|
51
|
+
## A tour
|
|
21
52
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
53
|
+
### Diffs you can read
|
|
54
|
+
|
|
55
|
+
Edits arrive as numbered, highlighted diffs, folded until you want the whole
|
|
56
|
+
thing (`ctrl+o`).
|
|
57
|
+
|
|
58
|
+
<img src="docs/images/edit.png" alt="An Edit tool call drawn as a coloured diff" width="900">
|
|
59
|
+
|
|
60
|
+
### You stay in charge
|
|
61
|
+
|
|
62
|
+
Each permission the agent asks for is a choice under the transcript, answered
|
|
63
|
+
with a number or the arrows. `shift+tab` cycles the agent's permission modes.
|
|
64
|
+
|
|
65
|
+
<img src="docs/images/permission.png" alt="The permission prompt: Allow, Always allow, Deny" width="900">
|
|
66
|
+
|
|
67
|
+
### Many agents in one window
|
|
68
|
+
|
|
69
|
+
Up to nine sessions as tabs, each with its own agent, transcript and draft.
|
|
70
|
+
A tab in the background marks what it waits for, and `ctrl+x a` takes you
|
|
71
|
+
there.
|
|
72
|
+
|
|
73
|
+
<img src="docs/images/tabs.png" alt="Two tabs, claude waiting on a permission behind, codex in front" width="900">
|
|
74
|
+
|
|
75
|
+
### Subagents, folded
|
|
76
|
+
|
|
77
|
+
When the agent fans out, its subagents run as one tree with their latest call
|
|
78
|
+
each, and their full work is a key away.
|
|
79
|
+
|
|
80
|
+
<img src="docs/images/subagents.png" alt="Two subagents running in parallel under one block" width="900">
|
|
81
|
+
|
|
82
|
+
### Teams
|
|
83
|
+
|
|
84
|
+
Describe how you work and the agent proposes a team: a lead and its members,
|
|
85
|
+
each on the runtime, model and mode you want. Save it once, then hand it any
|
|
86
|
+
job with `/team run bugfix <job>`.
|
|
87
|
+
|
|
88
|
+
<img src="docs/images/proposal.png" alt="A proposed team as a table of agents, with a box asking where to save it" width="900">
|
|
89
|
+
|
|
90
|
+
### Pick up where you left off
|
|
91
|
+
|
|
92
|
+
`/resume` lists this directory's earlier sessions and saved windows; quit a
|
|
93
|
+
window of several tabs and chord prints the one command that brings them all
|
|
94
|
+
back.
|
|
95
|
+
|
|
96
|
+
<img src="docs/images/resume.png" alt="The resume picker listing earlier sessions" width="900">
|
|
26
97
|
|
|
27
98
|
## Install
|
|
28
99
|
|
|
29
100
|
```sh
|
|
30
|
-
npm install -g @chorded/chord
|
|
101
|
+
npm install -g @chorded/chord # or bun, pnpm, yarn
|
|
31
102
|
```
|
|
32
103
|
|
|
33
|
-
The
|
|
34
|
-
|
|
35
|
-
|
|
104
|
+
The package is a small shim around a prebuilt binary for macOS and Linux,
|
|
105
|
+
arm64 and x64; the macOS binaries are signed and notarised. `chord upgrade`
|
|
106
|
+
updates it through the package manager that installed it.
|
|
36
107
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
108
|
+
chord starts each agent for you (through `npx` or `uvx`, or the agent's own
|
|
109
|
+
CLI where it has one), so the agent's own login is all it needs: sign in to
|
|
110
|
+
Claude Code, Codex or Gemini as you normally would.
|
|
40
111
|
|
|
41
|
-
|
|
112
|
+
To build from source, with [Bun](https://bun.sh) 1.4.2 or newer:
|
|
42
113
|
|
|
43
114
|
```sh
|
|
115
|
+
git clone https://github.com/IKatsuba/chord && cd chord
|
|
44
116
|
bun install
|
|
45
|
-
bun run compile --install #
|
|
117
|
+
bun run compile --install # into ~/.local/bin/chord
|
|
46
118
|
```
|
|
47
119
|
|
|
48
120
|
## Use
|
|
49
121
|
|
|
50
122
|
```sh
|
|
51
|
-
chord
|
|
52
|
-
chord codex # any agent `chord agents` lists
|
|
123
|
+
chord # your default agent in this directory
|
|
53
124
|
chord gemini -C ~/src/app
|
|
54
|
-
chord
|
|
55
|
-
chord --
|
|
56
|
-
chord
|
|
57
|
-
chord
|
|
58
|
-
chord --resume # pick an earlier session or a saved window first
|
|
59
|
-
chord agents # the agents chord can start: name, what starts each, and whether PATH has its CLI
|
|
60
|
-
chord -p "Explain src/main.tsx" # the reply on stdout, then exit
|
|
125
|
+
chord agents # every agent chord can start, and whether it is installed
|
|
126
|
+
chord --continue # the latest session here, again
|
|
127
|
+
chord --resume # pick an earlier session or window
|
|
128
|
+
chord -p "Explain src/main.tsx" # one reply on stdout, for scripts
|
|
61
129
|
git diff | chord -p "Review this" --output-format json
|
|
62
130
|
```
|
|
63
131
|
|
|
64
|
-
Inside
|
|
65
|
-
windows in one list, newest first, each with when it was last used and its
|
|
66
|
-
first prompt, after its name for an agent another agent started; a window reads `▣ 3 sessions · claude, codex, claude` and its
|
|
67
|
-
front tab's first prompt, and its sessions are on the list too, just under
|
|
68
|
-
it. Enter opens the highlighted session in the same window and Esc leaves
|
|
69
|
-
things as they were. Enter on a window opens its tabs beside those open, at
|
|
70
|
-
the end of the strip, with its front tab in front; one already open is not
|
|
71
|
-
opened twice, and a front tab no prompt went to gives its place. A window
|
|
72
|
-
that would take more than nine tabs opens none, and the status line says
|
|
73
|
-
how many to close. ctrl+a lists every directory's, as Claude Code's does,
|
|
74
|
-
each row naming its directory from `~` (a window's front tab's, `+1` for
|
|
75
|
-
each other directory its tabs work in), and ctrl+a again goes back to this
|
|
76
|
-
one. A session or window from another directory is not opened in this
|
|
77
|
-
window, whose settings, MCP servers and files are that directory's; chord
|
|
78
|
-
says so and gives the `chord <agent> --resume <id>` or
|
|
79
|
-
`chord --resume w-<id>` that opens it where it works.
|
|
80
|
-
|
|
81
|
-
`chord --resume` with no id opens the same picker before any agent starts,
|
|
82
|
-
as `claude --resume` does; Enter opens what it picks, from any directory,
|
|
83
|
-
as its own `--resume` would, and Esc quits with nothing started.
|
|
84
|
-
|
|
85
|
-
ctrl+x c opens another session of the same agent in the same directory,
|
|
86
|
-
in front, beside the one already open, up to nine; `/new` does the same, and
|
|
87
|
-
`/new codex` opens one of the agent it names, on that agent's command, model
|
|
88
|
-
and mode from the settings files; `/new ` and part of a name lists the agents
|
|
89
|
-
chord can start, those only your settings name among them, an agent whose own
|
|
90
|
-
CLI is not on your `PATH` marked so, and Tab or Enter picks one. An agent chord cannot start is refused in
|
|
91
|
-
the transcript, and a tenth session on the status line. With two or more open the
|
|
92
|
-
window's top row has a tab for each, the one in front in inverse; a tab behind marks a
|
|
93
|
-
turn running (`✻`), a reply not yet seen (`✓`), a failure (`✗`) or a
|
|
94
|
-
permission or form waiting (`●`). ctrl+x n and ctrl+x p go to the next and
|
|
95
|
-
the previous tab, ctrl+x 1 to 9 to a tab by its number, each with its own
|
|
96
|
-
transcript, draft and prompt as it was left. After ctrl+x the status line
|
|
97
|
-
names the keys that can follow, and Esc lets it go. A session behind that
|
|
98
|
-
asks for permission or a form, or ends its turn, never comes to the front by
|
|
99
|
-
itself: the status line says so
|
|
100
|
-
(`● 2 claude needs your permission · ctrl+x a`), and ctrl+x a goes to the one
|
|
101
|
-
that has waited longest, then the next on each press. ctrl+x k closes the
|
|
102
|
-
session in front, the one to its left coming forward; one that is working
|
|
103
|
-
or running a `!` command, waits on you, has prompts queued, or task agents
|
|
104
|
-
running or long-lived agents working or waiting asks for a
|
|
105
|
-
second ctrl+x k first, and its command stops with it. Its long-lived agents
|
|
106
|
-
close with it. Closing the last one
|
|
107
|
-
quits. With several open and any of them busy, ctrl+d
|
|
108
|
-
and `/exit` ask for a second press too and name the busy ones. Quitting
|
|
109
|
-
closes every session, waits for each agent to exit, and prints a
|
|
110
|
-
`chord <agent> --resume <id>` for the session a prompt went to. With two or
|
|
111
|
-
more such sessions it saves the window instead
|
|
112
|
-
(`~/.local/state/chord/windows/`) and prints one command for all of them,
|
|
113
|
-
`chord --resume w-<id>`, which opens every tab again in its order, each on
|
|
114
|
-
its own agent where it works, the one that was in front in front. A window
|
|
115
|
-
opened that way and quit again is saved over its own record, as it is then.
|
|
116
|
-
A tab whose session record has gone is left out, and the status line says
|
|
117
|
-
which; a window id goes on its own, never among session ids.
|
|
118
|
-
|
|
119
|
-
A resumed session shows its earlier prompts, replies and tool calls, an
|
|
120
|
-
edit with its diff, and the next prompt goes on in the same session. chord
|
|
121
|
-
keeps a record of every session a prompt was sent in, in its state directory
|
|
122
|
-
(`~/.local/state/chord/records/`), which `--continue`, `--resume` and
|
|
123
|
-
`/resume` read, and the past is drawn from it whichever way the agent
|
|
124
|
-
reopens the session. The id is the agent's own: for Claude Code, the one
|
|
125
|
-
`claude --resume` takes, so `--resume <id>` also opens a session chord never
|
|
126
|
-
saw, its past as the agent replays it.
|
|
127
|
-
|
|
128
|
-
`--resume` (`-r`), given once per id, takes up to nine, the most one window
|
|
129
|
-
holds, and opens each
|
|
130
|
-
in a tab of its own, in the order given, the first in front. Each tab runs
|
|
131
|
-
its session's own agent in its session's own directory, with that
|
|
132
|
-
directory's settings and MCP servers; `@`, `!` commands, `/status` and the
|
|
133
|
-
header follow the tab in front, and ctrl+x c and `/new` open beside it in
|
|
134
|
-
its directory. Several ids open only sessions chord has a record of: an
|
|
135
|
-
unknown id, the same id twice or a tenth refuses the whole command before
|
|
136
|
-
the window opens. Each `--resume` takes one id or none, so the agent goes
|
|
137
|
-
anywhere around them: `chord codex -r <id> -r <id>`. As the id is optional,
|
|
138
|
-
a word after `--resume` that names one of chord's own flags (`model`, `c`)
|
|
139
|
-
is not read as an id.
|
|
140
|
-
|
|
141
|
-
ctrl+g opens the prompt in your editor (`$VISUAL`, then `$EDITOR`, then
|
|
142
|
-
`vi`), run through your shell; what it saves comes back as the prompt when
|
|
143
|
-
it exits. An editor that exits with an error or is killed leaves the
|
|
144
|
-
prompt as it was, and the status line says so.
|
|
145
|
-
|
|
146
|
-
ctrl+v puts the image on the clipboard into the prompt as `[Image #1]`, at
|
|
147
|
-
the cursor, and Enter sends it after the text. So does the terminal's own
|
|
148
|
-
paste (cmd+V) where the terminal sends an empty paste for a clipboard that
|
|
149
|
-
holds only an image, as Ghostty does; one with nothing on the clipboard
|
|
150
|
-
changes nothing. A path to a PNG, JPEG, GIF
|
|
151
|
-
or WebP file pasted or typed into the prompt (`/…`, `~/…`, `file://…`, as a
|
|
152
|
-
terminal writes a dropped file) is taken the same way. Backspace after
|
|
153
|
-
the placeholder, or delete before it, takes it whole, and the image stays
|
|
154
|
-
behind. An agent that says it takes no
|
|
155
|
-
images gets none, and the status line says so.
|
|
156
|
-
|
|
157
|
-
`/config` lists the agent's own settings for the session other than its
|
|
158
|
-
model and mode, such as Claude's effort, each with its value; Enter on one
|
|
159
|
-
lists its values and Enter on a value sets it.
|
|
160
|
-
|
|
161
|
-
Each session's transcript opens with a header: Chorded's mark in its
|
|
162
|
-
gradient, drawn in half blocks, and beside it chord's version, the agent and
|
|
163
|
-
the model the session started on, its directory and the keys to `?` and
|
|
164
|
-
`/help`; a resumed session's says when it was last used and its first
|
|
165
|
-
prompt. It stands at the top, the window's first row with one session open
|
|
166
|
-
and under the row of tabs with more, and the conversation grows down from it;
|
|
167
|
-
once the conversation fills the window the header scrolls away, and `home`
|
|
168
|
-
brings it back.
|
|
169
|
-
|
|
170
|
-
`/theme` chooses chord's colours: Auto, Dark, Light, each of those two
|
|
171
|
-
colour-blind friendly, or in the terminal's own 16 colours. Moving through
|
|
172
|
-
the list shows the whole window in the highlighted theme; Enter keeps it and
|
|
173
|
-
saves it to your settings file, and Esc goes back. Auto, the default, asks
|
|
174
|
-
the terminal for its background as chord starts. chord never colours plain
|
|
175
|
-
text, so it stays your terminal's own, and `NO_COLOR` turns every colour off
|
|
176
|
-
whatever the theme.
|
|
177
|
-
|
|
178
|
-
`/vim` turns vim mode on for the prompt, and off again; the choice is kept
|
|
179
|
-
for the next start. The box starts in insert mode, where it types as ever,
|
|
180
|
-
and `-- INSERT --` or `-- NORMAL --` under it says which mode it is in. Esc
|
|
181
|
-
goes to normal mode, which takes `h j k l`, `w b e`, `0 $ ^`, `x`, `dd`,
|
|
182
|
-
`dw`, `cw`, `D`, `C`, `i a I A o O`, `u`, `p` and counts such as `3w` or
|
|
183
|
-
`d2w`; an `[Image #N]` goes whole under `x` and `dw`. Enter sends from
|
|
184
|
-
either mode. Esc in normal mode does what it does without vim mode, so
|
|
185
|
-
interrupting a turn takes Esc twice from insert mode; an open list, picker
|
|
186
|
-
or panel still closes on the first Esc.
|
|
187
|
-
|
|
188
|
-
`-p` draws no window: it sends one prompt, with anything piped in after it
|
|
189
|
-
on a line of its own, writes the reply to stdout as it streams, and exits 0
|
|
190
|
-
when the agent ends its turn, or 1 with the error on stderr. Nobody is there
|
|
191
|
-
to answer a permission, so each one is refused and stderr says so.
|
|
192
|
-
`--permission-mode`, or `permissionMode` in the settings files, starts the
|
|
193
|
-
turn in that mode, and `--effort`, or `effort`, on that effort; one the
|
|
194
|
-
agent does not take is a `chord: could not start in <mode> mode, …` or
|
|
195
|
-
`chord: could not start on <effort> effort, …` line on stderr, and the turn
|
|
196
|
-
runs as the agent chose. `--dangerously-skip-permissions`, only with `-p` and never a setting,
|
|
197
|
-
allows every permission instead, each with a `chord: allowed <title>.` line
|
|
198
|
-
on stderr; with both, the mode is asked for and whatever the agent still asks
|
|
199
|
-
is allowed.
|
|
200
|
-
`--output-format json` prints one object at the end instead: `result`,
|
|
201
|
-
`session_id` (which `--resume` takes), `stop_reason`, `is_error`, and `usage`
|
|
202
|
-
and `total_cost_usd` when the agent reports them. An agent that reports its
|
|
203
|
-
tokens but no cost, as Codex can, gets a cost chord works out from the
|
|
204
|
-
model's price, with `cost_estimated: true` beside it; `/cost` says
|
|
205
|
-
`(chord's estimate)` after such a cost, and a context window chord took from
|
|
206
|
-
the model's data is marked `~` on the status line.
|
|
207
|
-
|
|
208
|
-
## Settings
|
|
209
|
-
|
|
210
|
-
chord reads two settings files before it starts: the user's,
|
|
211
|
-
`~/.config/chord/settings.json` (under `$XDG_CONFIG_HOME` when that is set),
|
|
212
|
-
and the project's, `.chord/settings.json` in the directory the session works
|
|
213
|
-
in. The project's file overrides the user's, and a command-line flag overrides
|
|
214
|
-
both.
|
|
215
|
-
|
|
216
|
-
```json
|
|
217
|
-
{
|
|
218
|
-
"agent": "codex",
|
|
219
|
-
"agents": {
|
|
220
|
-
"claude": { "effort": "high", "permissionMode": "plan" },
|
|
221
|
-
"my-agent": { "command": "my-agent --acp" }
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
```
|
|
132
|
+
Inside the window:
|
|
225
133
|
|
|
226
|
-
| Key
|
|
227
|
-
|
|
|
228
|
-
|
|
|
229
|
-
|
|
|
230
|
-
|
|
|
231
|
-
|
|
|
232
|
-
| `
|
|
233
|
-
| `
|
|
234
|
-
| `
|
|
235
|
-
| `
|
|
236
|
-
| `
|
|
237
|
-
| `mcpServers` | MCP servers handed to the agent, as `.mcp.json` writes them | |
|
|
238
|
-
|
|
239
|
-
When a turn ends, a permission is asked or the agent asks you to fill in a form
|
|
240
|
-
or open a link, chord tells the terminal, so a window in the background can say
|
|
241
|
-
so. `preferredNotifChannel` is `auto` by default: OSC 9, a desktop
|
|
242
|
-
notification, in iTerm2, WezTerm, Ghostty and kitty;
|
|
243
|
-
OSC 777 in foot; the bell elsewhere and inside tmux. `bell`, `osc9`, `osc777`
|
|
244
|
-
choose one, and `off` turns it off. A turn you interrupt with Esc is not
|
|
245
|
-
announced. With several sessions open, the notification names the tab:
|
|
246
|
-
`fake (2) needs your permission: Write notes.txt`.
|
|
247
|
-
|
|
248
|
-
`theme` takes Claude Code's ids: `auto` (the default), `dark`, `light`,
|
|
249
|
-
`dark-daltonized`, `light-daltonized`, `dark-ansi` and `light-ansi`. It is
|
|
250
|
-
about your terminal and your eyes rather than a project, so it is read only
|
|
251
|
-
from the user's file, and one in a project's file is reported and left out.
|
|
252
|
-
`/theme` writes it there, keeping the file's other keys. `editorMode`,
|
|
253
|
-
`normal` (the default) or `vim` as Claude Code names them, is read from the
|
|
254
|
-
user's file alone for the same reason, and `/vim` writes it there the same
|
|
255
|
-
way.
|
|
256
|
-
|
|
257
|
-
chord reads the mouse, so the wheel and the trackpad scroll the
|
|
258
|
-
transcript, as pgup, pgdn and shift+↑/↓ do, and ↑/↓ stay with your earlier
|
|
259
|
-
prompts. To select text, hold your terminal's modifier while you drag:
|
|
260
|
-
option in iTerm2, fn in Terminal.app (or turn mouse reporting off with
|
|
261
|
-
⌘R), shift in most others. Inside tmux, the wheel reaches chord only with
|
|
262
|
-
`set -g mouse on`; without it the terminal sends ↑/↓. `"mouse": false`, read
|
|
263
|
-
from the user's file only, leaves the mouse to the terminal, as before.
|
|
264
|
-
|
|
265
|
-
### Keybindings
|
|
266
|
-
|
|
267
|
-
`~/.config/chord/keybindings.json`, beside the settings file, rebinds
|
|
268
|
-
chord's keys. It has the shape of Claude Code's `~/.claude/keybindings.json`
|
|
269
|
-
and the same action names, so a block copied from there means the same
|
|
270
|
-
here; chord never reads Claude Code's file itself.
|
|
271
|
-
|
|
272
|
-
```json
|
|
273
|
-
{
|
|
274
|
-
"bindings": [
|
|
275
|
-
{
|
|
276
|
-
"context": "Chat",
|
|
277
|
-
"bindings": {
|
|
278
|
-
"enter": "chat:newline",
|
|
279
|
-
"ctrl+s": "chat:submit",
|
|
280
|
-
"ctrl+g": null,
|
|
281
|
-
"ctrl+x ctrl+e": "chat:externalEditor"
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
]
|
|
285
|
-
}
|
|
286
|
-
```
|
|
134
|
+
| Key | Does |
|
|
135
|
+
| ----------------- | -------------------------------------------- |
|
|
136
|
+
| `?` | every key, on an empty prompt |
|
|
137
|
+
| `/` | slash commands, chord's and the agent's |
|
|
138
|
+
| `@` | mention a file |
|
|
139
|
+
| `!` | run a shell command, its output for the agent |
|
|
140
|
+
| `shift+tab` | cycle the permission mode |
|
|
141
|
+
| `ctrl+o` | expand tool calls and subagents |
|
|
142
|
+
| `ctrl+x c` / `/new codex` | open another session as a tab |
|
|
143
|
+
| `ctrl+x 1`…`9` | go to a tab |
|
|
144
|
+
| `esc` | interrupt the turn |
|
|
287
145
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
`chat:cycleMode`, `chat:externalEditor`, `chat:imagePaste`,
|
|
292
|
-
`history:previous`, `history:next` and `help:toggle` in `Chat`;
|
|
293
|
-
`app:toggleTranscript`, `history:search`, and chord's own `session:new`,
|
|
294
|
-
`session:next`, `session:previous`, `session:goto1` to `session:goto9`,
|
|
295
|
-
`session:list`, `session:attention` and `session:close` in `Global`;
|
|
296
|
-
chord's own `agents:close` (`x`) in `Agents`, the list of a session's
|
|
297
|
-
agents and monitors, where it closes an agent or stops a monitor;
|
|
298
|
-
`autocomplete:accept`, `dismiss`, `previous` and `next` in `Autocomplete`;
|
|
299
|
-
`historySearch:next`, `accept` and `cancel` in `HistorySearch`;
|
|
300
|
-
`confirm:no` in `Confirmation`; `help:dismiss` in `Help`; `select:cancel`
|
|
301
|
-
and `select:toggleScope` (`/resume`'s ctrl+a, chord's own name) in `Select`; and `scroll:pageUp`, `pageDown`, `lineUp`, `lineDown`, `top`
|
|
302
|
-
and `bottom` in `Scroll`. ctrl+c and ctrl+d cannot be rebound, nor can the
|
|
303
|
-
keys inside lists, forms and vim mode. An unknown context, action or key,
|
|
304
|
-
and a key that would mean two actions at once, such as a key the
|
|
305
|
-
transcript scrolls on bound in `Chat`, is left out and named as a
|
|
306
|
-
warning in the transcript and on stderr, and the status line counts them; the
|
|
307
|
-
rest of the file still applies. The `?` panel and the hints name the keys as
|
|
308
|
-
bound, and `\ + enter for a newline` names the key that sends.
|
|
309
|
-
|
|
310
|
-
The keys work on a Russian layout too, the defaults and the file's alike: a
|
|
311
|
-
press that does nothing as typed is read as the US key in the same place,
|
|
312
|
-
so ctrl+ч is ctrl+x, `с` after it opens a session and vim's normal mode
|
|
313
|
-
moves on р о л д. Text is never read again: Cyrillic typed in the prompt,
|
|
314
|
-
a form, the search line or vim's insert mode stays as typed, and a key the
|
|
315
|
-
file binds in Cyrillic is its own. Punctuation a US layout also types stays
|
|
316
|
-
itself, so on "Russian – PC", where the key in `?`'s place types `,`,
|
|
317
|
-
shift+7's `?` opens the panel. In a terminal speaking the kitty keyboard
|
|
318
|
-
protocol (kitty, Ghostty, WezTerm, iTerm2 with CSI u on), every key is
|
|
319
|
-
found on any layout, Greek, Ukrainian or Hebrew as well, by the key in its
|
|
320
|
-
place that the terminal names, so there the key in `?`'s place opens the
|
|
321
|
-
panel on an empty prompt too, and types its `,` after a draft.
|
|
322
|
-
|
|
323
|
-
chord hands the agent MCP servers for each session it opens, new or
|
|
324
|
-
resumed, from three places, each over the one before: `mcpServers` in the
|
|
325
|
-
user's settings file, the `.mcp.json` in the directory the session works in
|
|
326
|
-
(the file Claude Code and other tools share), and `mcpServers` in the
|
|
327
|
-
project's `.chord/settings.json`. A server named twice is the later one,
|
|
328
|
-
whole. Each is written the way `.mcp.json` writes it:
|
|
329
|
-
|
|
330
|
-
```json
|
|
331
|
-
{
|
|
332
|
-
"mcpServers": {
|
|
333
|
-
"filesystem": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "."], "env": { "DEBUG": "1" } },
|
|
334
|
-
"docs": { "type": "http", "url": "https://mcp.example.com/mcp", "headers": { "Authorization": "Bearer …" } }
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
```
|
|
146
|
+
Settings live in `~/.config/chord/settings.json` and the project's
|
|
147
|
+
`.chord/settings.json`: the default agent, each agent's model, effort and
|
|
148
|
+
mode, MCP servers, theme and notifications.
|
|
338
149
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
transport, its command or URL, and the file that defined it; Esc closes it.
|
|
343
|
-
It does not show `env` or `headers`. Whether the agent then connected to
|
|
344
|
-
them, ACP does not say, and neither does `/mcp`. chord only reads these
|
|
345
|
-
files; it never writes `.mcp.json` or the agent's own configuration. A
|
|
346
|
-
server that is wrong is named with its file and left out, and the others
|
|
347
|
-
still count; a `.mcp.json` that is not a JSON object is named and ignored.
|
|
348
|
-
`/mcp` says under its list how many servers each file lost that way.
|
|
349
|
-
`-p` passes the same servers.
|
|
350
|
-
|
|
351
|
-
Beside them, every session the window opens gets an MCP server of chord's
|
|
352
|
-
own, named `chord` (or `chord-2`, … where one of the user's already is), where
|
|
353
|
-
its agent takes MCP over HTTP: chord serves it on
|
|
354
|
-
the loopback while the window is open, and each session reaches it with a
|
|
355
|
-
token of its own, so nothing else on the machine can call it. Its tools let
|
|
356
|
-
an agent see what it could start: `list_agents` names every agent chord can
|
|
357
|
-
start and the models and modes of those already read, or, given an agent's
|
|
358
|
-
name, that one's, starting it briefly to read them if no session of it is
|
|
359
|
-
open;
|
|
360
|
-
`list_sessions` names the window's open sessions with their agent, model and
|
|
361
|
-
tab. `spawn_task` starts a task agent: another agent, on any runtime chord
|
|
362
|
-
knows and a model it offers, does one job with no tab of its own. Its work
|
|
363
|
-
draws in its parent's turn as a subagent's block does, `Agent(<name>) ·
|
|
364
|
-
codex · gpt-5.3-codex`, its permission requests, forms and links come to you
|
|
365
|
-
in the parent's tab, and what it tells its parent with `send_message`, its
|
|
366
|
-
one tool, and the report its first turn ends with reach the parent as
|
|
367
|
-
messages, drawn as a `←` row: a turn of the parent's, or, while one runs,
|
|
368
|
-
what the task tells it goes into that turn, and the report waits behind it
|
|
369
|
-
the way a prompt does. Every agent chord opens but a task has `spawn_task` and
|
|
370
|
-
`list_agents`, so a long-lived child starts task agents of its own, drawn in
|
|
371
|
-
its own turn and closed with it; a task starts none. Esc stops the turn's
|
|
372
|
-
task agents with it, and they
|
|
373
|
-
send no report; `/clear` closes them with the session it lets go. A task
|
|
374
|
-
asked for a model its runtime refuses fails before it starts work. Asked
|
|
375
|
-
for an effort too, as `list_agents` lists them, it starts on it, and its
|
|
376
|
-
block says it after the model; one the runtime does not take leaves it on
|
|
377
|
-
the runtime's own, which the block says instead, and the refusal is a line
|
|
378
|
-
in the parent's transcript and in the answer, which waits for the task to
|
|
379
|
-
be up.
|
|
380
|
-
|
|
381
|
-
`open_agent` opens a long-lived agent the same way, with the prompt as its
|
|
382
|
-
first turn, a message from `main`. It gets no tab: while a session has one,
|
|
383
|
-
a list of its agents sits under the status line, `main` and each child in
|
|
384
|
-
the order it opened, each child in a colour of its own, with its runtime,
|
|
385
|
-
model, the effort it is on (`open_agent` takes one as `spawn_task` does)
|
|
386
|
-
and state (`✻ working 41s`, `● permission 12s`, `← message from
|
|
387
|
-
@main`, `✓ replied 2m ago`). ↓ on an empty prompt that is not walking
|
|
388
|
-
history moves into the list, where ↑ ↓ or j k pick; Enter or Esc goes back
|
|
389
|
-
to the box with the pick kept. The picked agent's chat fills the window,
|
|
390
|
-
the box takes its colour and its name on the top border, and the status line
|
|
391
|
-
its model, effort and context: what you type goes to it as your own prompt. `send_message` from the parent reaches a
|
|
392
|
-
child, and from a child its parent alone, each a turn of the recipient's,
|
|
393
|
-
as many as they trade; `list_sessions` gives each session's children. A
|
|
394
|
-
message to an agent that is working goes into its turn at once, where its
|
|
395
|
-
runtime takes that (Claude's and Codex's adapters advertise ACP's
|
|
396
|
-
`_session/steering`), and draws there, among the turn's calls; while the
|
|
397
|
-
turn waits on your answer to a permission, form or link, it waits under the
|
|
398
|
-
working line as `← @main · after your answer: …` and goes in once you
|
|
399
|
-
answer. A runtime without steering takes it as the next turn, as the queue
|
|
400
|
-
under the working line shows. Should the message reach the agent just as
|
|
401
|
-
its turn ended, and the agent start a turn of its own with it, as Codex's
|
|
402
|
-
adapter does, chord cancels that turn at once, closes it with a dim
|
|
403
|
-
`Interrupted · the agent started this on its own` line, and sends the
|
|
404
|
-
message as the next turn. A monitor's events and your own prompts
|
|
405
|
-
always wait for the turn's end. A
|
|
406
|
-
child that waits on you is named on the status line, ctrl+x a picks it, and
|
|
407
|
-
its permission box opens there. `x` in the list closes the picked child, a
|
|
408
|
-
second time while it works or waits, and chord tells the parent so;
|
|
409
|
-
`close_agent` closes one from the parent, and a message to a closed one is
|
|
410
|
-
refused. A child whose agent exits, or whose turn fails, is news to its
|
|
411
|
-
parent too: a `← chord` message, a turn of the parent's, says
|
|
412
|
-
`parser's agent exited: <the end of its stderr>. open_agent opens it
|
|
413
|
-
again.`, or that its turn failed and why, so a parent waiting on a report
|
|
414
|
-
does not wait for ever. A session holds eight children at most, a team's
|
|
415
|
-
lead counting as one and its members as none. `/clear` with a child
|
|
416
|
-
picked is refused; on `main` it closes the children with the session.
|
|
417
|
-
|
|
418
|
-
A team saved in `.chord/teams/<name>.md`, or in `teams/` beside your
|
|
419
|
-
settings file for every project, takes a job from the session you talk to:
|
|
420
|
-
say "hand it to bugfix" and the agent calls `run_team`, which chord draws
|
|
421
|
-
as `Team(bugfix) · claude · opus` with the job under it. `list_teams` names
|
|
422
|
-
the saved teams and their runs open. The team's lead is a long-lived child
|
|
423
|
-
named after the team, on the lead's runtime, model, effort and mode; a second run
|
|
424
|
-
of a running team is `bugfix 2`. Its first prompt is the team's
|
|
425
|
-
instructions, drawn as one line (`bugfix's instructions for the lead · 58
|
|
426
|
-
lines`, ctrl+o for all of them), then the job as a message from `@main`.
|
|
427
|
-
The lead's `open_agent` takes a member's name and opens only the file's
|
|
428
|
-
members, on the file's runtime, model, effort and mode (`Open(tester) ·
|
|
429
|
-
claude · sonnet · high · acceptEdits`); an effort the runtime does not take
|
|
430
|
-
leaves the agent on its own, which the answer and the agent's transcript
|
|
431
|
-
say; its `send_message` reaches main, its members and
|
|
432
|
-
the other runs' leads, and each message to main is a turn of main's. A
|
|
433
|
-
member messages its lead and the team's other open members by name,
|
|
434
|
-
directly. In the list the lead's row reads `team · claude · Opus` and its
|
|
435
|
-
open members are nested under it (`├─ tester`); when the list does not fit
|
|
436
|
-
its rows, each team folds to its lead's row, `team · claude · 4 agents` and
|
|
437
|
-
its most urgent state with the member's name (`● tester: permission 12s`),
|
|
438
|
-
and the team you are in unfolds. A member picked has its box read `tester ·
|
|
439
|
-
bugfix`; its permissions are yours to answer, as a child's are, the
|
|
440
|
-
notification says `tester (bugfix) needs your permission`, and with two
|
|
441
|
-
runs open the status line says which run's `tester` asks. `x` on a lead
|
|
442
|
-
closes the team, members and all, twice while any of it works, and chord
|
|
443
|
-
tells main; a member closed tells the lead, and a lead whose agent exits
|
|
444
|
-
closes its members and tells main.
|
|
445
|
-
|
|
446
|
-
A team is made by asking for one: the agent you talk to calls
|
|
447
|
-
`propose_team`, and chord draws its proposal as `Team(bugfix) · proposal`,
|
|
448
|
-
a row per agent with its runtime, model, effort where any agent sets one,
|
|
449
|
-
mode and role, each mode whole and
|
|
450
|
-
one that skips your ok in the warning colour, then how the team works,
|
|
451
|
-
folded. A box shaped like the permission box asks `Save team bugfix?`: for
|
|
452
|
-
this project (`.chord/teams/bugfix.md`), for every project
|
|
453
|
-
(`~/.config/chord/teams/bugfix.md`), or no, tell the agent what to change,
|
|
454
|
-
which Esc picks too. chord writes the file, never the agent; the call ends
|
|
455
|
-
`Saved to …` or `Not saved`, and your next words go to the agent. A
|
|
456
|
-
proposal under a saved team's name is `Team(bugfix) · change`, its changed
|
|
457
|
-
rows marked, a changed effort or mode with the one it had (`high was
|
|
458
|
-
medium`), and its body's change
|
|
459
|
-
counted and drawn as a diff (whole with ctrl+o), and saves back in place.
|
|
460
|
-
|
|
461
|
-
`/team` is chord's own command for teams, and talks to the session you
|
|
462
|
-
opened whatever agent is picked. `/team` alone (or `/team list`) opens the
|
|
463
|
-
teams picker: each saved team with its size and runtimes, where it is
|
|
464
|
-
saved, `✻ working 6m` or `✻ 2 runs` while it runs in the window, and its
|
|
465
|
-
description, and a file that is not a team with its first problem. Enter
|
|
466
|
-
puts `/team run bugfix ` in the box for you to type the job. `/team new
|
|
467
|
-
<words>` asks the agent for a team through `propose_team`; to change one,
|
|
468
|
-
ask the agent in plain words, and it proposes the change against the saved
|
|
469
|
-
team through the same tool. `/team show bugfix`
|
|
470
|
-
reports the team under the command, and while it runs each agent's state
|
|
471
|
-
and latest call or message. `/team run bugfix <job>` hands it your words as
|
|
472
|
-
they are, drawn as `run_team`'s `Team(bugfix)` row, with no turn of the
|
|
473
|
-
agent's; the agent hears of it with your next prompt. `/team stop bugfix`
|
|
474
|
-
closes that run and its members at once, and chord tells the agent. A
|
|
475
|
-
team's name is completed after `show`, `run` and `stop`.
|
|
476
|
-
|
|
477
|
-
`monitor` runs a command in the background for the agent that asks, a
|
|
478
|
-
session's or a long-lived child's, and each batch of lines it prints reaches
|
|
479
|
-
that agent later as a message: a turn of its own, drawn `← dev server errors
|
|
480
|
-
· monitor` with the lines as printed, folded after six. Its end is one more,
|
|
481
|
-
`· exit code 1`, `· timed out`, `· flooded` or `· stopped`, with chord's
|
|
482
|
-
sentence last. While one runs it is a row in the list under the prompt, after
|
|
483
|
-
the agents, with its command and how long it has run, a child's ending with
|
|
484
|
-
its name; ↓ reaches it, and `x` on it stops it at once. A turn an event
|
|
485
|
-
started does not ring the terminal when it ends. `stop_monitor` and
|
|
486
|
-
`list_monitors` are the agent's own, and a resumed session draws its events
|
|
487
|
-
again and names the monitors it left running, which are not restarted.
|
|
488
|
-
|
|
489
|
-
A session resumed after its agents ran draws them as they were: each task
|
|
490
|
-
agent's block, its work behind ctrl+o (read from the task's own record,
|
|
491
|
-
so a task whose record was deleted keeps its block and how long it ran,
|
|
492
|
-
without the work), a
|
|
493
|
-
task still running when the
|
|
494
|
-
session was left ending `Disconnected`, every message both ways, and the
|
|
495
|
-
`Open`, `Close` and `→` calls. Its long-lived agents are not reopened with
|
|
496
|
-
it; a closing line names those still open when it was left, which
|
|
497
|
-
`/resume` lists like any session, and a message the parent sends one is
|
|
498
|
-
refused. Opened from `/resume`, such a child is your own session, in a tab,
|
|
499
|
-
with no parent to message. A team run is one of them, named with how many of
|
|
500
|
-
its agents were open (`team bugfix (4 agents)`), and the line ends with
|
|
501
|
-
`/team run bugfix starts the team again`: a fresh run, with no memory of
|
|
502
|
-
the last but the working tree and what main was told. `/resume` lists its
|
|
503
|
-
lead and members like any child. A task agent gets no command on quit.
|
|
504
|
-
chord's own calls draw as `List agents`, `List sessions`, `Open(parser)`
|
|
505
|
-
and `Close(parser)`, and a message sent as `→ @main` or `→ @parser`, never as
|
|
506
|
-
their MCP names. A name after an arrow takes `@` where `send_message` reaches
|
|
507
|
-
it, `main` and a long-lived child; a task, named by its title, and chord's
|
|
508
|
-
own `← chord` stay bare. `/mcp` lists chord's server first,
|
|
509
|
-
and says what it gives the agent, or that the agent does not take HTTP and
|
|
510
|
-
got none. `-p` gets no such server.
|
|
511
|
-
|
|
512
|
-
Models, efforts and modes are set per agent because their ids are the
|
|
513
|
-
agent's own: `/model`, `/config` and shift+tab show what an agent offers, and
|
|
514
|
-
`chord agents` lists the names. An effort is one the model the session starts
|
|
515
|
-
on offers. A starting model, effort or mode the agent refuses is said in the
|
|
516
|
-
transcript, with where it was set and what the agent offers, and the session
|
|
517
|
-
goes on as the agent chose; an agent with no effort starts on its own, and
|
|
518
|
-
the line says it offers none. An unknown key, or a key with the wrong kind of value, is
|
|
519
|
-
named with its file and left out, and the rest of the file still counts; a
|
|
520
|
-
file that is not a JSON object is named and ignored. Either way chord starts:
|
|
521
|
-
the problem is a line on stderr and a yellow line at the top of the
|
|
522
|
-
transcript. `-p` takes `agent`, `command`, `effort` and `permissionMode`
|
|
523
|
-
from the files, and says a refused effort or mode on stderr; `--model` is for
|
|
524
|
-
the window. `--agent-command`, `--model`, `--effort` and `--permission-mode`
|
|
525
|
-
speak for the agent the command line names: a session `/new` opens of another agent starts on that
|
|
526
|
-
agent's settings alone.
|
|
527
|
-
|
|
528
|
-
chord knows the agents the [ACP Registry](https://agentclientprotocol.com/registry)
|
|
529
|
-
offers through npx or uvx, each at the version chord's source pins: `claude`
|
|
530
|
-
and `codex` for Claude's and Codex's adapters, every other one by its
|
|
531
|
-
registry id. It starts one as `npx -y <package>@<version>` or
|
|
532
|
-
`uvx <package>@<version>`, so `npx` or `uvx` must be on your `PATH`.
|
|
533
|
-
|
|
534
|
-
Some agents ship their own CLI, which speaks ACP itself: `cursor`, `devin`,
|
|
535
|
-
`fx`, `goose`, `junie`, `kimi`, `kiro`, `openclaw`, `opencode`, `poolside`
|
|
536
|
-
and `zeroclaw`. chord starts each by the command its docs give (Cursor's
|
|
537
|
-
`agent acp`, goose's `goose acp`, …), which you install yourself; when it is
|
|
538
|
-
not on your `PATH`, chord says which command it looked for and where the
|
|
539
|
-
agent says to install it, and exits before the window. chord downloads
|
|
540
|
-
nothing for them: the registry also offers most of these as archives to
|
|
541
|
-
unpack, but a CLI you installed and keep up to date is the one you already
|
|
542
|
-
signed in to. Any other ACP agent starts with `agents.<name>.command` or
|
|
543
|
-
`--agent-command`, which also replace the command chord knows for a name; a
|
|
544
|
-
name your settings files alone give a command starts as `chord <name>` and
|
|
545
|
-
opens with `/new <name>`. `chord agents` lists them all: each one's name and
|
|
546
|
-
title (`from settings` for a name only they define), `npx` or `uvx` for the
|
|
547
|
-
registry's, `own CLI · found` or `own CLI · not on PATH` for those that need
|
|
548
|
-
their own CLI, and `settings` where a settings file's command starts it, then
|
|
549
|
-
what starts it, that command in the table's or the registry's place, wrapped
|
|
550
|
-
within its column on a terminal and one line per agent when piped.
|
|
551
|
-
You sign in to the agent the way it expects: chord starts the agent's ACP
|
|
552
|
-
adapter or CLI, it does not sign you in to anybody.
|
|
553
|
-
|
|
554
|
-
## Development
|
|
150
|
+
**[The guide](docs/guide.md)** has everything else: every flag, setting, key,
|
|
151
|
+
the team file format, chord's MCP tools for agents, and how sessions are
|
|
152
|
+
recorded.
|
|
555
153
|
|
|
556
|
-
|
|
557
|
-
bun install # the dependencies
|
|
558
|
-
bun run chord # run from source
|
|
559
|
-
bun run check # types, lint, format, tests — must pass before every commit
|
|
560
|
-
bun run compile # this machine's binary into dist/
|
|
561
|
-
bun run registry # refetch the ACP Registry's agents into src/registry.ts
|
|
562
|
-
```
|
|
154
|
+
## Supported agents
|
|
563
155
|
|
|
564
|
-
|
|
565
|
-
|
|
156
|
+
Claude Code, Codex, Gemini CLI, GitHub Copilot, Cursor, OpenCode, Cline, Qwen
|
|
157
|
+
Code, Kimi Code, Kiro, Goose, Junie, Factory Droid, Auggie, Kilo, Devin, fx
|
|
158
|
+
and more: `chord agents` prints the full list, and any other ACP agent runs
|
|
159
|
+
with `chord --agent-command "my-agent --acp"`.
|
|
566
160
|
|
|
567
|
-
|
|
568
|
-
it, without stopping it, into `heaps/` in chord's state directory, for
|
|
569
|
-
Chrome's DevTools. `docs/memory.md` has how, and the long-run memory check
|
|
570
|
-
(`bun scripts/memory.ts`).
|
|
161
|
+
## Contributing
|
|
571
162
|
|
|
572
|
-
|
|
163
|
+
Issues and pull requests are welcome. [CONTRIBUTING.md](CONTRIBUTING.md) has
|
|
164
|
+
how to run chord from source against its scripted test agent, choose checks
|
|
165
|
+
for a change, and follow the code conventions. Found a security issue?
|
|
166
|
+
See [SECURITY.md](SECURITY.md).
|
|
573
167
|
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
`src/clis.ts`'s agents started by their own CLI.
|
|
577
|
-
- [OpenTUI](https://github.com/anomalyco/opentui) — the terminal interface, through
|
|
578
|
-
its React bindings.
|
|
579
|
-
- [Agent Client Protocol SDK](https://github.com/agentclientprotocol/typescript-sdk)
|
|
580
|
-
— the connection to the agent, and the protocol types.
|
|
581
|
-
- [Cliffy](https://cliffy.io) — the command line.
|
|
168
|
+
The screenshots above are chord itself, run against that test agent and
|
|
169
|
+
captured by `bun run screenshots`.
|
|
582
170
|
|
|
583
171
|
## Licence
|
|
584
172
|
|
|
585
|
-
chord's code is [MIT](LICENSE).
|
|
173
|
+
chord's code is [MIT](LICENSE). The Chorded name and the chevron mark are
|
|
174
|
+
trademarks of Igor Katsuba and are not covered by the licence; a fork should
|
|
175
|
+
draw its own ([TRADEMARKS.md](TRADEMARKS.md)).
|
|
586
176
|
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
trademarks of Igor Katsuba. The MIT licence does not cover them: a fork may
|
|
590
|
-
keep the code, but should take the mark out and draw its own. See
|
|
591
|
-
[TRADEMARKS.md](TRADEMARKS.md).
|
|
177
|
+
chord is the open sibling of [Chorded](https://chorded.app), a native macOS
|
|
178
|
+
workspace for agent sessions driven by key chords.
|
package/package.json
CHANGED
|
@@ -1,12 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chorded/chord",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.55.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/IKatsuba/chord.git"
|
|
8
8
|
},
|
|
9
|
+
"homepage": "https://github.com/IKatsuba/chord#readme",
|
|
10
|
+
"bugs": {
|
|
11
|
+
"url": "https://github.com/IKatsuba/chord/issues"
|
|
12
|
+
},
|
|
9
13
|
"description": "A full-screen terminal client for ACP coding agents.",
|
|
14
|
+
"keywords": [
|
|
15
|
+
"acp",
|
|
16
|
+
"agent-client-protocol",
|
|
17
|
+
"claude-code",
|
|
18
|
+
"codex",
|
|
19
|
+
"gemini-cli",
|
|
20
|
+
"coding-agent",
|
|
21
|
+
"terminal",
|
|
22
|
+
"tui"
|
|
23
|
+
],
|
|
10
24
|
"bin": {
|
|
11
25
|
"chord": "bin/chord.js"
|
|
12
26
|
},
|
|
@@ -14,9 +28,9 @@
|
|
|
14
28
|
"bin/"
|
|
15
29
|
],
|
|
16
30
|
"optionalDependencies": {
|
|
17
|
-
"@chorded/chord-darwin-arm64": "0.
|
|
18
|
-
"@chorded/chord-darwin-x64": "0.
|
|
19
|
-
"@chorded/chord-linux-x64": "0.
|
|
20
|
-
"@chorded/chord-linux-arm64": "0.
|
|
31
|
+
"@chorded/chord-darwin-arm64": "0.55.0",
|
|
32
|
+
"@chorded/chord-darwin-x64": "0.55.0",
|
|
33
|
+
"@chorded/chord-linux-x64": "0.55.0",
|
|
34
|
+
"@chorded/chord-linux-arm64": "0.55.0"
|
|
21
35
|
}
|
|
22
36
|
}
|