feat(adapters): native Qwen Code, iFlow CLI, Trae, Kiro IDE & ECA support#530
Merged
Merged
Conversation
…pters Extends "whatever AI coding agent you run, the Peon shows up — natively" to five more agentic IDEs. Each ships .sh + .ps1 versions with BATS coverage and is wired into session-id routing so sounds attribute to the right IDE. - Qwen Code (Alibaba) & iFlow CLI (iflow-ai): Claude-Code-style stdin-JSON hook passthroughs (qwen-/iflow- session prefix, drop noisy per-tool events); iFlow maps a failed PostToolUse to PostToolUseFailure. - Trae (ByteDance): filesystem-watcher adapter (Amp/Antigravity pattern) since Trae has no synchronous shell-hook API; watched paths overridable via TRAE_DATA_DIR/TRAE_SESSIONS_DIR/TRAE_SESSION_GLOB. - Kiro IDE (Amazon): .kiro/hooks/*.kiro.hook runCommand adapter (event name on argv, no stdin JSON), distinct from the existing Kiro CLI adapter; kiro-ide- session prefix. - ECA (Editor Code Assistant): stdin-JSON shell hooks, eca- prefix derived from db_cache_path; vendored first-party from community contribution PeonPing#261. peon.sh and the embedded Windows runtime (generated by install.ps1) recognize all five via IDE_ALIASES, the session-id prefix_map / Detect-SessionIde, and IDE_DISPLAY_NAMES (kiro-ide- ordered before kiro- so the longer prefix wins). install.sh and install.ps1 ship the adapters; README.md, README_zh.md, and docs/public/llms.txt document setup for each. Bumps VERSION to 2.30.0.
|
@muunkky is attempting to deploy a commit to the Gary Sheng's projects Team on Vercel. A member of the Team first needs to authorize it. |
garysheng
marked this pull request as ready for review
June 8, 2026 14:48
This was referenced Jun 8, 2026
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
peon-ping's promise is "whatever AI coding agent you run, the Peon shows up — natively." Until this branch, five increasingly-common agentic IDEs broke that promise: a Qwen Code or iFlow user got silence, a Trae user got silence, anyone on Kiro's IDE (as opposed to its CLI, which was already supported) got silence, and the ECA community had a working adapter living only in an unmerged PR. This branch closes all five gaps at once. The reason they ship together isn't convenience — it's that each one exercises a different integration shape, and getting all four shapes right in one cut is what makes the routing layer below provably general rather than tuned to one IDE.
After this branch, a session started in any of these five tools attributes its sounds to the right IDE, on both Unix/WSL2 and native Windows, with zero new runtime dependencies on the IDEs that already had a hook API. The change is purely additive — no existing adapter's behavior changes, and the routing additions are new map entries, not edits to existing ones.
Summary
PostToolUsefailure →PostToolUseFailure)runCommandagent hooks, event on argvQwen Code and iFlow CLI — passthroughs over a CESP-shaped hook API
The constraint. Qwen Code (Alibaba) and iFlow CLI (iflow-ai) both ship a hook system modelled directly on Claude Code's: events are piped to the hook command as JSON on stdin, and the event names are already the PascalCase CESP vocabulary peon-ping speaks (
SessionStart,UserPromptSubmit,Stop,Notification, …). The only thing standing between these IDEs and working sounds was that nothing told peon-ping the events came from them.What's now possible. A Qwen or iFlow session now fires peon-ping sounds, and those sounds attribute to "Qwen Code" / "iFlow CLI" rather than falling back to a generic label, because each adapter re-tags the session id with a
qwen-/iflow-prefix the router recognizes.Why this design. The natural alternative when the upstream vocabulary already matches is to register peon-ping's hook script directly in the IDE's settings, no adapter at all. We didn't, for two reasons: peon-ping needs the IDE-attribution prefix on the session id (the raw IDE never adds it), and the raw hook stream is noisy — every
PreToolUse/PostToolUsesuccess would make the Peon chatter on every file read. The adapter is therefore a thin filter: it forwards an allowlist of meaningful lifecycle events unchanged and drops the per-tool-call success chatter. The price is one tiny script per IDE to maintain, which is the floor for any attribution-aware integration.The one place iFlow and Qwen diverge: iFlow surfaces tool failures through a plain
PostToolUsewith an error payload rather than a dedicated failure event, so its adapter remaps that case toPostToolUseFailure(Qwen already emits the dedicated event and needs no remap).What it looks like. The Qwen adapter's core is an allowlist-and-retag:
Setup is a
hooksblock in~/.qwen/settings.json/~/.iflow/settings.json(full JSON in the README setup sections), or the.ps1variant on Windows.How we know it works.
tests/qwen.batsandtests/iflow.batsassert the allowlisted events pass through with the right prefix, the noisy events are dropped, and — for iFlow — that a failedPostToolUsearrives at peon-ping asPostToolUseFailure.Trae — a filesystem watcher, because there are no hooks to register
The constraint. Trae (ByteDance) is a VS Code-derived AI IDE. It exposes MCP and VS Code extensions but no synchronous shell-hook API — there is no settings key where you can register "run this command when the agent stops." A passthrough adapter like Qwen's has nothing to attach to.
What's now possible. Running the Trae watcher in the background gives a Trae user the same "agent finished" / "new session" sounds every other supported IDE gets, despite Trae offering no hook surface — peon-ping infers the lifecycle from Trae's own session files on disk.
Why this design. The watcher reuses the exact pattern already proven for Amp and Antigravity (the project's other hookless integrations): a new session file means
SessionStart; the session file going idle past a timer meansStop. The alternative — a VS Code extension that taps Trae's internal agent events — would be more precise but drags in a whole second distribution channel (a packaged, separately-installed extension) and couples peon-ping to Trae's extension API surface. The watcher needs only a shell loop and ships in the same tarball as every other adapter. The price we accept is that Trae's on-disk layout is undocumented and version-dependent, so the watched paths are environment-overridable rather than hardcoded:TRAE_DATA_DIR~/.traeTRAE_SESSIONS_DIR$TRAE_DATA_DIR/sessionsTRAE_SESSION_GLOB*.jsonWhat it looks like. On Unix the watcher uses
fswatch/inotifywait; on Windows the.ps1uses .NETFileSystemWatcher, so neither platform needs a new dependency it didn't already have for Amp/Antigravity.How we know it works.
tests/trae.batsdrives the watcher against a synthetic sessions directory: creating a file emitsSessionStart, letting it go idle emitsStop, and the env-var overrides redirect the watch.Kiro IDE — distinct from the Kiro CLI, with the event name on argv
The constraint. peon-ping already supported the Kiro CLI (
adapters/kiro.sh), which pipes camelCase JSON on stdin. The Kiro IDE (Amazon) is a different product with a different hook mechanism: its Agent Hooks are.kiro/hooks/*.kiro.hookJSON files whosethen.type: runCommandaction runs a shell command with no stdin JSON at all — the triggering event name is passed to the command as an argv argument. The existing CLI adapter, which reads stdin, gets nothing from it.What's now possible. A Kiro IDE user can wire one
.kiro.hookfile per lifecycle event toadapters/kiro-ide.sh, and peon-ping reacts — without disturbing or being confused with the already-supported Kiro CLI. The two coexist: IDE sessions carry akiro-ide-prefix, CLI sessions carrykiro-.Why this design. The tempting shortcut was to extend the existing
kiro.shto also handle the argv-style invocation — one adapter, one prefix. We kept them separate because they're genuinely different products with different event vocabularies and session-id schemes, and conflating them would make a Kiro-IDE bug a risk to working Kiro-CLI users. The price is a second small adapter and a second prefix the router must distinguish — which surfaces the one real subtlety in this PR, handled in the routing section below.What it looks like. Each event is one hook file; the event name rides on the command line:
{ "version": "1.0.0", "enabled": true, "name": "peon-ping-stop", "when": { "type": "agentStop" }, "then": { "type": "runCommand", "command": "bash ~/.claude/hooks/peon-ping/adapters/kiro-ide.sh agentStop" } }agentStop → Stop,promptSubmit → UserPromptSubmit,preToolUse → PermissionRequest,sessionStart → SessionStart;postToolUseand file/user-triggered hooks carry no peon-relevant signal and exit silently.How we know it works.
tests/kiro-ide.batsasserts eachwhen.typemaps to the right CESP event and that the session id is prefixedkiro-ide-, keeping it disjoint from the CLI'skiro-.ECA — vendoring a community adapter as first-party
The constraint. ECA (Editor Code Assistant, eca.dev) is an editor-agnostic LLM-agent integration. A working adapter for it already existed — as community contribution #261 — but living in an unmerged PR meant ECA users had to find that PR and copy the file by hand; it wasn't shipped, tested, or routed.
What's now possible. ECA support is now first-party: the adapter ships in the tarball, is covered by the test suite, and is recognized by the router with a stable
eca-session prefix, so an ECA user gets sounds via the standard install with no PR-archaeology.Why this design. Rather than re-implement from scratch, we vendored the contributed adapter with attribution to its author, then made it match the conventions the other four follow (CESP event mapping, prefix-tagged session id, a BATS file). The one piece worth calling out: ECA provides no obvious stable session id, so the adapter derives one from ECA's
db_cache_path(constant for the life of a session) rather than minting a random id per event — without that, every event would look like a different session and the no-repeat / attribution logic would misbehave.What it looks like. Events map
sessionStart/chatStart → SessionStart,preRequest → UserPromptSubmit,postRequest/subagentPostRequest/postToolCall → Stop,preToolCall → PermissionRequest,sessionEnd → SessionEnd, and the session id iseca-plus a sanitized slice of the cache path.How we know it works.
tests/eca.batscovers the event mapping and asserts theeca--prefixed session id is derived deterministically fromdb_cache_path.Routing: the longer-prefix-wins ordering
All five IDEs are recognized in one place per platform:
peon.sh(viaIDE_ALIASES, the session-idprefix_map, andIDE_DISPLAY_NAMES) and the embedded Windows runtime thatinstall.ps1generates (viaNormalize-IdeId,Detect-SessionIde, and$ideDisplayNames). Adding an IDE is three new map entries, not a code edit — which is why five IDEs of four different shapes land without touching any existing adapter's path.The one non-obvious detail is prefix collision:
kiro-ide-starts withkiro-. A naïve match would classify every Kiro IDE session as Kiro CLI. The fix is ordering —kiro-ide-is matched beforekiro-, so the longer, more specific prefix wins:This only works if iteration order is guaranteed, which is why the PowerShell side uses
[ordered]@{ ... }rather than a plain hashtable — a regular PowerShell hashtable has non-deterministic key order, andkiro-could win on some runs and not others. The ordered map makes the longer-prefix-first guarantee hold identically on both platforms.Validation
test)tests/{qwen,iflow,trae,kiro-ide,eca}.bats— event mapping, prefix tagging, noise dropping, Trae watcher lifecycle. Passing.test-windows).ps1adapters and assert none useExecutionPolicy Bypass. Passing.Both code CI jobs are green on the head commit. The Vercel check is the only red and is expected for any fork PR against this repo.
Docs and version
README.mdandREADME_zh.md: a setup section per adapter, plus the IDE table rows, badge row, and intro list.docs/public/llms.txtupdated for the five new IDEs.VERSION2.29.0 → 2.30.0 (minor — new platform support, additive), with a matchingCHANGELOG.mdentry.How to review
The diff is 24 files but reads in three passes:
adapters/qwen.sh(simplest) thenadapters/trae.sh(the watcher) to see the two integration shapes; their.ps1siblings mirror them.peon.shandinstall.ps1hunks are pure additive map entries; verifykiro-ide-precedeskiro-in both, and that the PowerShell map is[ordered].llms.txt, version bump. Skim for completeness.