neuron-explorer
Qwen3.5‑4B 전용 조향형 뉴런 탐색기, 모든 MLP 뉴런을 밀어 결과를 보관·탐색
See which project each Claude Code, Codex and Cursor process belongs to, how long it has really been idle, and what it is costing you. Native macOS, no permissions required.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Activity Monitor for Your Local AI Agents
A free, open-source, native macOS app that shows you every Claude Code, Codex,
Cursor, Kiro and Antigravity process on your machine — what project it belongs
to, how long it has been sitting there, and how much of your Mac it is holding.
Open Activity Monitor while you have a few agent sessions going and you get
this:README 전문 보기 ↗Activity Monitor for Your Local AI Agents
A free, open-source, native macOS app that shows you every Claude Code, Codex, Cursor, Kiro and Antigravity process on your machine — what project it belongs to, how long it has been sitting there, and how much of your Mac it is holding.
Open Activity Monitor while you have a few agent sessions going and you get this:
2.1.228 5,8% 6:46:58.81 39 threads
2.1.231 2,0% 1:18:17.04 39 threads
2.1.228 1,5% 1:48:52.33 39 threads
2.1.228 1,5% 1:23:59.63 39 threads
2.1.232 1,2% 1:13:19.57 39 threads
Fifteen identical rows named after a version number. Claude Code installs itself
as ~/.local/share/claude/versions/2.1.228, so the process name is the
version — and nothing on that screen tells you which of them is the session you
abandoned in a repo last Tuesday and which is the one doing your actual work.
So people reach for pkill -9 -f claude, kill everything including the session
they were in the middle of, and move on.
Corral shows you the same processes with the one fact that makes them distinguishable — the working directory — plus how long each has really been idle, what it spawned, and what it is costing you.
The project, not the version. Each agent is identified by its working
directory, so the list reads heroshot, recall, appcleaner — not
2.1.228 five times.
Honest idle time. Not "quiet since this app opened": Corral reads the last
write to each agent's controlling terminal, which the kernel has been stamping
all along. An agent you walked away from on Tuesday says idle 3.1d the first
second you open the window.
The whole footprint. Every agent's children — MCP servers, node helpers,
the caffeinate that has been quietly stopping your Mac from sleeping — and
the memory they hold together.
Where it came from. Executable path, full command line, parent process, controlling terminal, start time.
What each agent has spent. Tokens since the agent started, subagents included, next to its memory and uptime — the counterpart of CPU time, kept from the tool's own logs. Point at it for the last 24 hours, hour by hour, and what the whole project has spent. See What each agent spent.
What is safe to reclaim. Agents idle for over an hour, totalled, behind one button. Anything still working — including an agent waiting on a build it started — is never in that total.
A menu bar item. Corral keeps running with its window closed — and leaves the Dock while it does, so a monitor in the background is not a tile you have to look at. The top right shows the busiest agent's CPU — or just how many are running when nothing is working hard. Hover for the summary, click for the list, click a row to open the window on that agent, and Quit is on the same menu when you want it gone for real.
The tool's own icon. Taken from the copy of Claude, Cursor or ChatGPT already installed on your Mac, the same way Finder draws it. Corral ships no brand artwork; a tool you do not have installed falls back to a symbol.
Where the numbers have been. One graph in the header, plotting CPU by default. Click a figure — agents, memory, projects, cores — to plot that one instead; click the graph to switch between 15 minutes, 1 hour and 3 hours. "2.92 GB" cannot tell you whether that is the calm after you closed six agents or the start of a climb; the graph can. Point at a column to read what it held and how far back it sits.
The axis is fixed: now at the right edge, running back the full range in 10-second, 30-second or 1-minute slices. Two minutes of history fills two minutes of a three-hour graph and leaves the rest empty, rather than being stretched across it — and a stretch when Corral was not running stays empty too, because it will not draw across a sleep it did not observe.
Light or dark. Corral follows the system, or you can pin it either way in Settings (⌘,) — a window you leave open all day is the kind you might want dark on a light desktop.
Sorting. By how long it has been running (the default — the thing you forgot about is the thing you came here to find), by memory, by CPU across the whole group, or by project name. Each order has an obvious direction, so picking one applies it; picking the same one again reverses it. Remembered between launches.
Tabs. ⌘1 Agents, ⌘2 Usage, ⌘3 Insights, ⌘4 On disk — also under View.
Search. ⌘F in either pane. An agent matches on its project, path, tool, version, pid, terminal, command line — and on what it spawned, so searching for an MCP server finds the agent running it.
What they left on disk. A second tab measures every cache, superseded version and log the tools have accumulated, sorted by how safe it is to remove. On the machine this was written on that came to 14 GB.
How you work with them. An Insights tab reads your Claude Code and Codex transcripts and the git history next to them, and turns your habits — planning first, testing before trusting, steering, running agents side by side — into badges, with a card you can share. See Insights.
Supported: Claude Code, Claude (desktop), Codex, Cursor and its CLI agent, Windsurf, Kiro CLI, Kiro Crew, Kiro (the IDE) and Antigravity.
Every row carries a dot. There are five states, and each one is a different decision:
| State | Means | |
|---|---|---|
| 🟢 | working | Using the CPU, or writing to its terminal right now. |
| 🔵 | waiting | The agent is parked, but a build, test run or MCP server it started is busy. It is waiting on its own work. |
| ⚪ | idle | Nothing for under an hour. Normal between prompts. |
| 🟡 | idle (amber) | Nothing for an hour to a day. Worth a look. |
| 🔴 | abandoned | Nothing for over a day. Almost certainly forgotten. |
The same legend is in the app, behind the ? next to the search field.
How it is measured, and what that cannot see. Corral watches two things: how much CPU a process has used since the last sample, and the last write to its controlling terminal. It does not watch the network, so an agent waiting on a reply from the model is, strictly, doing neither. In practice that gap stays green: CLI agents animate a thinking indicator while they wait, and that redraw is a terminal write. Output within the last 30 seconds counts as working.
Two honest limits:
waiting is inferred from children, not from the agent. A swift build
burning a core proves its agent is working; an agent thinking quietly with no
children and no output does not look busy, because nothing observable says it
is. Before this existed, such a group read as plain idle — and was offered
up to the Reclaim button along with the genuinely forgotten ones.corral list makes the same distinction in text.How much have you got left, and how full is each conversation. Two different questions: an allowance belongs to the account and refills on a clock, a context window belongs to one conversation and is the only one of the two you can do something about right now.
They show in three places — a line on the right or left edge of the screen (or a strip at the top) that opens into a ring per vendor when you go near it, a Usage tab in the window, and the fullness of each conversation in its own row of the agent list.
Where the figures come from differs by tool, and Corral says so rather than leaving a gap:
| Allowance | Context | |
|---|---|---|
| Codex | from its own rollout logs, unasked | yes |
| Claude Code | needs the status line, below | yes |
| Cursor | not published anywhere on your Mac | needs the status line |
| Kiro CLI, Kiro Crew | asked of Kiro's servers, if you turn that on | yes, from its session files |
| Antigravity | not published; conversations are encrypted | no |
Codex writes its limits into every session log it keeps, so those are free —
and the plan on the pill comes from its sign-in file rather than from the last
turn, so an upgrade shows the day it happens rather than the next time Codex
runs. The
other two record nothing — but both hand their figures to a status line command
on every update, and Corral can be that command. Turn it on in Settings
(⌘, — or Settings… on the menu bar item), or from the Usage tab. It asks first, shows
the exact setting it will add to ~/.claude/settings.json or
~/.cursor/cli-config.json, keeps a timestamped copy of the file, and refuses
to touch a status line you already set up.
The Usage tab has a Reporting section saying, in a sentence per tool, whether Corral is being told anything and what to do if it is not — including when everything is already on. It used to appear only inside a panel that had no figures, which put it out of sight exactly when someone came looking: a tool reporting nothing because it has not run looks identical to one reporting nothing because it was never asked to. Codex is listed there too, with nothing to press: it writes its limits into its own session logs, and while it does have hooks — the same seven events Claude Code has — their payload carries session and tool metadata and no usage at all, so a status line would add nothing. What refreshes Codex is running Codex.
Kiro is the third kind. Kiro CLI writes every session to
~/.kiro/sessions/cli/ — the working directory, how full the window is and
what each turn cost, in credits — and a lock file naming the process holding
it. That pid is a descendant of the kiro-cli Corral lists, so the match is
exact where every other reader has to reason from paths and times. Kiro Crew's
agents are Kiro CLI engines it starts per session, so they read the same way
and are listed under the Crew app.
What the account has left is not on this Mac at all, and this is one of two
places Corral will use the network (the other is the update check) —
off until you turn it on, from Settings → Ask Kiro for Account Usage or the
Usage tab. It asks first, in a
dialog that says exactly what happens: every five minutes Corral reads the
sign-in token Kiro CLI keeps in its own store, sends one HTTPS request to the
fixed AWS host the Kiro IDE itself uses (GetUsageLimits), and keeps the
numbers that come back — credits used, the plan's limit, when it resets, any
bonus pool. The token is held for one request and never written down or
logged; the request follows no redirects; Corral never refreshes the token, so
when it runs out the panel says to run Kiro CLI, which does. Turning it off
forgets the figures.
Antigravity keeps its conversations encrypted — the bytes are random from the first one — and fetches its per-model rate limits from Google when the app asks. What it does leave readable is its own list of conversations, with a title, a workspace and the time of the last write, and that is what Corral shows: what the agent last worked on, in which project, and how long ago.
What Corral keeps out of what those tools send is the session id, the working directory, the context size and any limit percentages. Not the transcript path, not the branch, not the pull request — the payload describes what you are working on, and none of that is any of its business.
Every figure carries the date the tool wrote it. They are a by-product of the last turn an agent took, so a tool you have not run this week reports a week-old percentage, and one shown bare would read as current.
Under the allowance, the same panel says which models did the spending, over the last five hours and the last seven days. That one is counted rather than reported: every assistant turn in a session log names the model that produced it and the tokens it took, so the arithmetic is Corral's own.
It is a share of output, and it is labelled as one. Input is mostly cache reads — 621 million of them against 2.7 million produced tokens, on the machine this was written on — so a bar drawn on the total would be a bar about caching.
Kiro's is counted in credits, because that is what Kiro writes: every turn carries the metering entries it was billed, and its token fields are zero. The bars for Kiro are shares of credits and say so. Antigravity's are not counted at all — there is nothing readable to count — and the panel says that too.
Codex is read from two places. Its rollout logs give a turn-by-turn split and
are used wherever they exist; alongside them it now keeps a SQLite database with
a row per session, and that is read for sessions no rollout file describes. The
database is opened read-only, and only the four columns this needs are named —
the same table holds the first message of every session, its title and its git
branch. It reports one figure per session with no split anywhere in it, so a
breakdown that draws on it is about tokens rather than output and says
Tokens by model instead. Codex keeps a rollout_migration_state table of its
own, which is it saying the JSONL files are on their way out; when that day
comes, this keeps working.
A limit per model is a different thing, and mostly it is not available.
Claude Code does track seven_day_opus and seven_day_sonnet, but writes
neither to disk nor to its status line. Codex can meter a model family on an
allowance of its own — its protocol names each pool with a limit_id and a
limit_name, and a turn reports the pool the model it ran on draws from — so
Corral keeps the newest reading per pool across recent sessions and shows a
second pool as its own set of bars, named after it. On the machine this was
written on every turn has reported the one default pool, which is what most
accounts will see. The vendors also weight models against each other in ways
nothing local can see, so a model with 40% of the output has not necessarily
taken 40% of the week — and Corral does not say it has.
Still no network. These are files the tools put on your machine.
Every row for Claude Code, Codex, Kiro CLI or Kiro Crew carries a tokens figure: what that agent has gone through since its process started. It is the token counterpart of CPU time — a running total for the life of the process — except that nothing keeps tokens per process, so Corral keeps it, from the logs each tool writes turn by turn.
<session>/subagents/, and none of their turns appear in the
main transcript. On one session on the machine this was written on, the
subagents had done most of the work. Kiro Crew runs several sessions at once,
one engine each; every session whose lock names one of its engines is its.token_count event; Corral differences its running total instead of adding
up turns, which reproduces Codex's own figure for every rollout to the token.
A log belongs to one agent at a time, and a session resumed by a new process
is split at the moment that process started.~/Library/Application Support/Corral/token-ledger.json — numbers, log paths
and project paths, nothing that was said — for 180 days after the agent ends.The figure is the whole total, cache reads included, because that is what the model went through. The popover splits it into output, input, cache writes and cache reads, and says what the pile actually cost, in the one unit that compares with it: tokens read at full price. Cache reads cost a tenth of an input token or less, writes and output more, so on the session this was written against 5.05 billion tokens cost what 423 million read fresh would have — 8%, because nearly all of them were the model re-reading its own context.
The 24-hour history draws that twice. First every token, faint, with the cost on top of it on the same scale, so the part that cost anything is the coloured part of each bar — in a long session, a sliver. Then the cost alone on a scale of its own, because the hour that read most and the hour that cost most are often not the same hour: the first request after a pause long enough for the cache to expire rewrites the whole context at up to twice the input price, and on this machine those hours ran at 99% and 196% of full price against a typical 6–12%.
The ratios come from each model's published list prices — Claude's and OpenAI's, standard tier — and they are ratios, not a bill: nobody on a subscription pays per token. Corral keeps the table, because it moves: cache reads are 0.05× on Opus 5.5 and 0.025× on Fable 5.1 where they were 0.1×, and OpenAI's output multiple runs from 5× to 8×. A model that is not in the table is counted and drawn but not priced, and the popover says how much of the total that is, rather than borrowing a price from the model's family.
Kiro is counted in credits, which is what it records, and credits are already a cost. Cursor writes no running total anywhere, Antigravity's conversations are encrypted and Windsurf writes nothing readable, so their rows have no figure rather than a zero.
A monitor that shows you what is eating your CPU has no business being on that
list. A refresh takes ~8 ms across ~550 processes — 0.4% of one core at the
two-second refresh rate. Measure it yourself with Corral --bench.
That took work. The first version read every process's argument vector every tick, which allocates a megabyte a time, and cost 17% of a core. The fix is that almost nothing about a process changes: its path, its arguments, its terminal and what tool it belongs to are all fixed at birth, so they are asked once and cached against the pid and its start time. Only memory and CPU are re-read.
Counting a week of transcripts for the per-model figures is a different size of
job — 296 MB of session logs on this machine — and it never runs on that timer
or on that thread. Transcripts nobody has written to in a week are not opened;
the rest are read backwards from the end and abandoned as soon as the week runs
out, which is 82 MB rather than 296 MB; and after the first pass each file is
read from where the last one stopped. That is ~3 s once, in the background,
and ~30 ms every refresh after it. Written the obvious way — Data split by
Collection.split, which walks it a byte at a time through the protocol — the
same pass took over four minutes.
The per-agent token figures are the same kind of job and get the same care. The first pass after launch reads each running agent's logs back to the moment it started — 2.8 s for 13 agents on this machine, 1.7 s of it a single session of five billion tokens and 70 subagents — on a queue of its own. After that a pass every five seconds reads only what the agents have written since: ~4 ms.
You write software with agents mostly alone, with no sense of how you do it compared with last month. The transcripts already know: every prompt, every test run, every time you stopped the agent and turned it around. Insights reads them and answers in numbers you can check.
The Verifier — Trusts what passes, not what is promised.
last 30 days · 34 sessions · 1758 prompts · 105 active hours · 434 commits
CRAFT
Locked Plan First 9% Bronze at 15%
Bronze Proof, Not Promises 43% Silver at 55%
Gold Calm Debugger 1%
…
Badges. Nineteen habits in five groups — craft, steering, orchestration, output, rhythm — each with a bronze, silver and gold bar. Every badge says what it measured and what the next tier needs; click one to see all three bars with you placed among them. One with too little behind it (fewer than five sessions that changed code, say) stays locked and says so, rather than rewarding or scolding three sessions.
An archetype — the Architect, the Verifier, the Conductor, the Navigator, the Shipper, the Night Owl — is the group of badges you are strongest in, counting how far each badge is towards its next tier. Calm Debugger stays out of it: whether a failed command is run again blind says more about the agent than about you, and nearly everyone's agent earns that one gold. Under the badges, Next picks the measurable habits still below silver and says one thing to try for each.
Plates. Every badge has a picture, and none of them is a photograph or an
image file. Each is a small generative scene — a blueprint with contour lines
for planning, a wall of test results under a check, a heartbeat settling into a
flat line, a contribution grid, a crescent over a ridge — computed cell by cell
and printed through a Bayer 8×8 ordered dither in the badge's metal, like a
one-bit screen. Some are drawn from your own numbers: the conductor has as many
waves as you ran agents at once, the delegator as many spokes as it sent
subagents, the streak's flame grows with the streak. Each is labelled like a
figure in a manual, FIG.03 · test-first.
English and Turkish. Thanks, pushback and "run the tests" are matched in both, with accents and the dotless ı folded away, because a pattern written for English alone reads a Turkish speaker as someone who never thanks the agent and never pushes back.
Git. A commit counts as made with an agent when it landed in the session's
repository while the session was at work, or when the transcript recorded its
hash. Only your commits: the repository's configured email. Corral uses a real
git binary (Homebrew, the command line tools or Xcode) and never /usr/bin/git,
which on a Mac without developer tools would pop an install dialog.
The card. Share card draws a 1200×630 picture — archetype, best five badges with their plates, active hours, sessions, commits, agents at once, and the archetype's own plate open in a window from the first Macs, striped title bar, close box and all — and offers Copy Image, Save PNG, the system share menu, Post on X and Post on LinkedIn. The last two open the network's own compose page with the text filled in and the card on the clipboard to paste. README Badge saves a self-contained SVG and copies the Markdown to show it. No project names and no prompts are on any of them, and none of them goes anywhere until you send it.
The first look reads every transcript from the last 90 days once — on the machine this was written on, about ten seconds. After that only files that changed are read again. Codex support is lighter than Claude Code's: its newest rollouts run commands from a small script rather than naming them, so Insights reads prompts, commands, failures and interrupts there, and leaves the rest.
20 items · 13,97 GB total
(skipping versions in use: 2.1.227, 2.1.228, 2.1.231, …)
SAFE TO CLEAR — 1,44 GB
554,9 MB Network cache ~/Library/Application Support/Claude/Cache
294,7 MB Superseded versions ~/.local/share/claude/versions/2.1.229
…
WILL BE DOWNLOADED AGAIN — 11,94 GB
10,89 GB Local agent VM image ~/Library/Application Support/Claude/vm_bundles
1,05 GB Plugin cache ~/.claude/plugins/cache
YOUR DATA — 591,9 MB
520,6 MB Conversation history ~/.claude/projects
Three groups, because "reclaimable" is not one thing:
A version that is currently running is never offered, whatever its number says.
Everything goes to the Trash, never unlink.
Download the latest Corral-<version>.dmg from the
releases page, open it and drag
Corral to Applications. Every commit on main publishes a build, each one
listing its SHA-256 and the exact commit it came from — Corral --version
prints that commit back to you, and About Corral shows the same pair as
Version 0.1.5 (a1b2c3d), with the hash linking to that commit on GitHub.
A build made locally with make app has no release number, so it takes one
from git instead: the last release tag plus how far past it the tree is, as
0.1.5+3. If the tree had uncommitted changes the hash carries a -dirty
suffix, and About says the binary matches no commit at all.
Each release says how it was signed. A notarised build opens on a double click; anything else needs right-click → Open the first time. See Signing and notarisation.
Or build from source (macOS 13+, Xcode command line tools):
git clone https://github.com/popyapp/corral.git
cd corral
make app # builds build/Corral.app
open build # then drag Corral.app to /Applications
Or during development:
swift run Corral # the window
swift run Corral --list # the same inventory, printed
The first time a downloaded build opens, it asks whether to check for updates.
Say yes and Corral sends one HTTPS request to api.github.com for the latest
release when it opens and once a day while it stays open — no identifier, no
version, nothing about your agents; GitHub sees a request from your address, as
it would for any page you open. When there is a newer one it says so, once
per release, with a link to the release page; it never downloads or installs
anything itself. Settings → Updates turns it on or off, and Check for
Updates… in the Corral menu and the menu bar item asks once, whenever you like,
either way. A build made with make app or swift run never asks or checks by
itself.
Downloaded apps that Apple has not seen get stopped by Gatekeeper, so releases are signed with a Developer ID certificate and sent to Apple to be notarised. That is not App Store review — nobody reads it. Apple scans the binary and usually answers in minutes, and what it buys is an app that opens on a double click instead of one that has to be right-clicked past a warning.
Usually. The queue belongs to Apple, and it has taken over half an hour for one small app with the service reporting itself healthy — so the build waits thirty minutes and then ships the signed build anyway rather than throwing the release away over weather. A refusal is a different thing: it means something is wrong with what was sent, and it stops the release. So a download is in one of three states and the notes say which — notarised, Developer ID signed with no ticket stapled, or ad-hoc. Only the last one is unsigned in any meaningful sense; the middle one is checked with Apple over the network at first launch instead.
Corral is not on the Mac App Store and cannot be. Two of the calls it is built on are refused inside the App Sandbox, measured rather than assumed:
proc_pid_rusage returns EPERM for every other process, so there is no CPU
and no memory — which is the header, the graph, the idle detection and the
whole Reclaim feature.$HOME is redirected into the app's container, so the logs the agents keep
for themselves are unreachable, and with them every line about what an agent
is doing or how full its context is.Everything else survives the sandbox, including reading the process table, argument vectors, paths and working directories. It is those two that decide it.
Builds are universal — Apple Silicon and Intel — under the hardened runtime, with no entitlements at all. Nothing Corral reads needs one.
A fork needs none of this. With no secrets set the same workflow produces the same artefacts, ad-hoc signed and unnotarised, and says so in its release notes. To sign your own, set six repository secrets:
| Secret | What it is |
|---|---|
MACOS_CERTIFICATE_P12 | Developer ID Application certificate, exported as .p12, base64 |
MACOS_CERTIFICATE_PASSWORD | the password you gave that export |
MACOS_SIGNING_IDENTITY | e.g. Developer ID Application: Name (TEAMID) |
AC_API_KEY_ID | App Store Connect API key id |
AC_API_ISSUER_ID | that key's issuer id |
AC_API_KEY_P8 | the key's .p8 file, base64 |
An API key rather than an Apple ID and password: it has no second factor to get stuck on, and it can be revoked on its own. The workflow imports the certificate into a keychain that dies with the runner, and deletes both the keychain and the key file whatever happens.
Locally:
CODESIGN_IDENTITY="Developer ID Application: Name (TEAMID)" ./scripts/make_app.sh
./scripts/notarize.sh build/Corral.app # skips itself without credentials
Corral --list # human-readable
Corral --list --json # machine-readable
Corral --list --search recall # only agents matching a project, tool or pid
Corral --disk # what is on disk (read-only; nothing is deleted)
Corral --insights # habits and badges from the last 30 days
Corral --insights --days 90 --json # the same figures for a script, or an agent
Corral --bench # how much a refresh costs
17 agents · 98 processes · 2,44 GB · 11 projects · 17 idle
Claude Code 2.1.227 · pid 5777
project ~/code/heroshot
up 6.1d cpu 39.2s mem 88,5 MB idle 15.0h
tty /dev/ttys016
children 4 — node (MCP server, pid 5800), node (MCP server, pid 5801), …
SIGTERM — the agent gets to exit cleanly — then waits and
tells you honestly if anything ignored it.SIGKILL.launchd, where they sit forever with
nobody to talk to — which is exactly the mess this app exists to clean up.launchd
or itself.Corral needs no special permissions — no Full Disk Access, no accessibility,
no entitlements. Every fact it shows is already readable by any process running
as you: sysctl for the process table and argument vectors, proc_pidinfo for
working directories, proc_pid_rusage for CPU and memory.
It reads the argument vector and deliberately stops there — the environment block sits right after it in the same buffer and is full of API keys, so Corral never reads that far.
The token ledger holds counts, the paths of the logs they came from and the project folders they were spent in. Nothing an agent said is copied out of a transcript.
Insights reads transcripts in full, in memory, and keeps what it found in
~/Library/Application Support/Corral/insights.json: counts, times, project
folders and commit hashes. The one thing derived from what you typed is a short
hash of each prompt of eight words or fewer, so the same prompt sent forty times
can be recognised without being written down. It runs git log and
git config user.email in the repositories your sessions ran in, read-only.
Nothing leaves your machine, with two exceptions you have to turn on yourself:
Every other line of the app is file reads.
Sharing an Insights card is something you do, not something Corral does: Post on X and Post on LinkedIn open the network's compose page in your browser with the text filled in, and you decide whether to send it.
Open an issue. The same link is under Report a Problem… in the app's Help menu and in the menu bar item, and About Corral names the exact commit you are running.
swift test
Cursor, Codex and Windsurf have to work on a machine that has never run them, so
most of the suite feeds the catalog the exact executable paths those tools
produce — including CursorUIViewService, the macOS text-input helper that a
naive name match would list as Cursor and offer to kill.
The live tests go further: they compile a small binary named codex, run it
in a temp project directory, and assert Corral finds it, names the project, and
can stop it. Copying /bin/sleep and renaming it does not work — macOS SIGKILLs
an Apple-signed binary running from the wrong place — so the test builds its own.
make build # swift build
make test # swift test
make app # build/Corral.app
make dmg # build/Corral-<version>.dmg, mounted and verified
make list # run the CLI against your own machine
make icon # regenerate the .icns (needs librsvg)
make clean
MIT