Repository navigation
feat(installer): add QwenPaw and Qoder agent support alongside Claude Code and Codex - #60
Open
Leo (CallMeHFK) wants to merge 7 commits into
Open
Leo (CallMeHFK) wants to merge 7 commits into
Leo (CallMeHFK) wants to merge 7 commits into
Conversation
Author
|
@microsoft-github-policy-service agree |
…Codex Both installers can now provision the Idea/Reel plugins into QwenPaw's shared skill pool: - bin/install.mjs: data-driven agent registry (one entry per agent host), multi-select agent prompt, and a QwenPaw target that copies skills into <QWENPAW_WORKING_DIR>/skill_pool and writes the merged .env into the QwenPaw working dir (its runtime loads it; the skills' own .env walker reaches it from the pool). Best-effort `qwenpaw skills list --pool` nudges a manifest reconcile so manually placed skills register at once. - install.sh: --qwenpaw / --no-qwenpaw with QWENPAW_WORKING_DIR / QWENPAW_POOL_DIR overrides. Pool entries are real copies, not symlinks — QwenPaw's safe_skill_dir rejects resolved paths outside the pool root. - READMEs: document QwenPaw as a supported agent runtime.
… CLI `npx skills add` now requires --agent on non-interactive runs and dropped the legacy .agents/skills scaffold it used to leave behind. Fetch into a throwaway dir with -y --agent claude-code (the agent choice only decides where content lands there), accept both the current .claude/skills/<name> layout and the legacy one, then copy into each selected runtime.
Qoder reads SKILL.md folders from .qoder/skills/ (project scope) and ~/.qoder/skills/ (user scope), and — unlike QwenPaw — it resolves symlinked skill dirs, so Qoder joins the link-based runtimes rather than the copy path. - bin/install.mjs: one AGENTS registry entry; no pool flag, so global and project scope both work unchanged. - install.sh: --qoder / --no-qoder with a QODER_SKILLS_DIR override, symlinked into <repo-root>/.qoder/skills/ alongside the Claude and Codex slots. Also fixes the --help range, which had been silently dropping the env-override list since the QwenPaw flags were added. - READMEs: document Qoder as a supported agent runtime.
The Qoder commit was verified against one host, which hid three things that are not true everywhere: - $PY could be a relative path. The documented `PYTHON=./.venv/bin/python` passes the early checks, then dies at the connector check, which runs in a subshell that has already cd'd elsewhere. Resolve it to sys.executable's absolute path once. Pre-existing on main, not introduced by the Qoder work. - Skill install assumed `ln -s` always succeeds. On a repo sitting on a filesystem without symlink support the link lines print as if the skill were installed while nothing is there. link_into now falls back to a real copy and the caller labels it "(copied)". - --help printed a hardcoded line range, which had already silently swallowed the env-override list once. Derive it from the leading comment block instead. Also stops asserting a specific `/skills reload` subcommand in the closing Qoder hint, pointing at the docs page instead.
…allers The two installers disagreed: install.sh passed hand-written slot names (idea-spark), bin/install.mjs copied the source directory names (idea_spark), so the same install surfaced under two identities depending on which installer ran. Hosts list skills by that name, so a mixed history shows up duplicated. Both now resolve the slot from the skill's own frontmatter `name:` — the identity every host actually displays — falling back to the directory name. No rename table left to go stale when a skill is renamed or added. Writing the resolved name also lets the stale-slot cleanup be derived instead of listed: install.sh only ever cleared a leftover `idea_spark`, so `paper_search` / `scoop_check` slots from a pre-rename install survived forever. It now clears whichever directory-named slot the frontmatter name replaces, for the symlink runtimes and the QwenPaw pool alike.
…ered writeEnv() re-serialised the merged env even when `values` was empty, so a re-run with nothing new to record replaced a hand-edited .env with a bare KEY=value dump — every comment and section header lost, and a surprise .env.bak written next to it. Observed for real: a QwenPaw working-dir .env went 1352 -> 427 bytes with no keys entered. Skip the file entirely when there is nothing to add and one already exists. install.sh has always left an existing .env untouched, so this also removes a disagreement between the two installers. When keys *are* supplied the merge still writes and still backs up.
Leo (CallMeHFK)
force-pushed
the
feat/qwenpaw-agent-support
branch
from
September 22, 2026 05:53
5efa9dd to
c65b6ec
Compare
This branch has not been deployed
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.
Summary
ResearchStudio's plugins (Idea, Reel) are standard Agent Skills (SKILL.md folders), and the installers already supported provisioning them into Claude Code and Codex. This PR adds QwenPaw (agentscope-ai/QwenPaw) and Qoder CLI (docs) as further agent runtimes, and restructures the agent handling in
bin/install.mjsso adding another host is a one-line registry entry. It also fixes four installer defects that the verification work exposed.What the two new runtimes need
QwenPaw organizes skills differently from Claude Code/Codex: a shared skill pool at
$QWENPAW_WORKING_DIR/skill_pool/(default~/.qwenpaw/skill_pool/), from which skills are broadcast into per-agent workspaces (workspaces/<agent_id>/skills/). Two behaviors were verified against QwenPaw's source and docs before implementing:safe_skill_dirresolves skill directories and rejects anything outside the pool root, so symlinked skills (the approachinstall.shuses for Claude/Codex) would be silently dropped by its scanner.<working-dir>/.envinto the env its skills run in — which the skills' own.envwalker also reaches from the pool (≤ 4 levels up).Qoder reads
SKILL.mdfolders from.qoder/skills/(project scope) and~/.qoder/skills/(user scope, which wins on a name conflict), and — unlike QwenPaw — it resolves symlinked skill dirs, so it joins the existing link path rather than needing a copy path. Established by probe before writing code: symlinking one skill into.qoder/skills/made it appear in the discovered-skills list on the next turn.Changes
bin/install.mjsAGENTSmap with a data-driven registry (label+skillsDir(base)+poolflag); adding a new agent host is one entry.RS_AGENTS=claude,codex,qwenpaw,qoderfor non-interactive runs, with graceful skipping of unknown names.constant.pyresolution:QWENPAW_WORKING_DIR→ legacy~/.copaw→~/.qwenpaw), writes the merged.envinto the QwenPaw working dir (other agents keep the skills-dir.env), and best-effort runsqwenpaw skills list --poolto trigger the reconcile immediately. Pool agents have no project-scoped dir, so project scope still targets the pool with an explanatory note.poolflag, so global and project scope both work unchanged.install.sh--qwenpaw / --no-qwenpawand--qoder / --no-qoderflags plusQWENPAW_WORKING_DIR/QWENPAW_POOL_DIR/QODER_SKILLS_DIRenv overrides. Pool entries are copied (cp -R), never linked; Qoder is symlinked into<repo-root>/.qoder/skills/alongside the Claude and Codex slots. Seeds~/.qwenpaw/.envfrom.env.templatewhen absent (re-runs never overwrite), nudges a pool reconcile when the CLI is on PATH, and prints workspace-loading and/skillsguidance.Slot naming, both installers
install.shpassed hand-written slot names (idea-spark) whilebin/install.mjscopied source directory names (idea_spark), so one skill installed under two identities depending on which installer ran. Both now resolve the slot from the skill's own frontmattername:, falling back to the directory name — no rename table to go stale.install.shonly ever cleared a leftoveridea_spark, sopaper_search/scoop_checkslots from a pre-rename install survived indefinitely; now whichever directory-named slot the frontmatter name replaces gets cleared, for the link runtimes and the QwenPaw pool alike.Portability fixes
$PYcould be a relative path: the documentedPYTHON=./.venv/bin/pythonpassed the early checks, then died at the connector check, which runs in a subshell that has alreadycd'd elsewhere. Resolve it tosys.executableonce. (Pre-existing onmain.)ln -salways succeeds. On a filesystem without symlink support the output still printed the link arrow while nothing was installed.link_intonow falls back to a real copy and the line is labelled(copied).--helpprinted a hardcoded line range that had already silently swallowed the env-override list once; it now derives from the leading comment block.writeEnv()re-serialised the merged env even when nothing new was entered, so a re-run replaced a hand-edited.envwith a bareKEY=valuedump — every comment lost. It now leaves an existing file alone when there is nothing to add, matching whatinstall.shhas always done.READMEs — main + Idea + Reel list both new runtimes.
.gitignoreadds.qoder/alongside.claude/and.codex/.Verification
bash -n/node --checkclean;--helprenders the complete flag and env-override lists.HOME/QWENPAW_WORKING_DIRfor all four agents: skills land in~/.claude/skills,~/.codex/skills,<qoder>/skills, and<qwenpaw>/skill_poolrespectively;.envwritten to<qwenpaw>/.envand confirmed reachable by the skills' env walker;qwenpaw skills list --poolreconcile registered the installed skills inskill_pool/skill.json(real copies, no symlinks in the pool).install.sh --idea --qodersymlinked three skills into.qoder/skills/and Qoder's discovered-skills list picked them up in-session (observed, not inferred from files on disk).bin/install.mjswithRS_AGENTS=qoderverified for bothRS_SCOPE=projectandRS_SCOPE=global.paper_searchandpaper-searchwas reduced to the frontmatter name automatically.link_intoexercised against its own source withlnforced to fail: copies, returns 1,SKILL.mdpresent.skill_slot_namechecked against all eight shipped skills plus no-frontmatter and quoted-name:fallbacks..envguard checked both ways: no new keys → file byte-identical while the install still completes; with a key → merge and backup still happen.RS_AGENTSentries are skipped with a hint listing known agents.Note for reviewers
workspaces/<agent_id>/skills/+qwenpaw skills enable ...). That's QwenPaw's own pool→workspace model; the installers print this guidance rather than guessing an agent ID..qoder/settings.jsonis seeded. The Claude and Codex seeds grant broad auto-approval, and silently writing that policy for a new runtime seemed the wrong default.ppt-masteris fetched from GitHub bynpx skills add; that clone failed once on the machine used for testing (registry andgit ls-remotewere reachable, so it looks specific to that CLI's fetch method). The installer's warning path fired correctly and named the manual command.install.sh --reelhas no way to skip itssudo apt-getblock, so an unprivileged Reel install currently has to go throughbin/install.mjs. A--no-nativeflag would close that gap; not attempted here.