### What this PR does
**Before this PR**, Cherry Studio managed external CLI binaries through
five uncoordinated mechanisms — each requiring its own download script,
IPC channel, and on-disk layout:
| Mechanism | Where it lived | How it worked |
|---|---|---|
| rtk extraction | `src/main/utils/rtk.ts` + `AgentBootstrapService` |
Copies bundled binary to `~/.cherrystudio/bin/` |
| OpenClaw installer | `resources/scripts/install-openclaw.js` |
Downloads from GitHub/mirror with custom extraction |
| CodeCliService | `src/main/services/CodeCliService.ts` | `bun install
-g` to `~/.cherrystudio/install/global/` |
| ripgrep | `node_modules/@anthropic-ai/claude-agent-sdk/vendor/` |
Vendored, hardcoded path in `FileStorage` |
| (old) MiseService | `src/main/services/MiseService.ts` | Bundled mise
+ `mise use -g` |
**After this PR**, a single `BinaryManager` lifecycle service owns all
third-party CLI binary acquisition. It wraps
[mise](https://mise.jdx.dev) as the only acquisition backend (no custom
`BinaryBackend` interface — mise's polyglot grammar already covers
`npm:`, `pipx:`, `github:`, registry entries). Tools install into an
isolated environment under `~/.cherrystudio/mise/` so user-level mise
installs are never touched. `uv`, `bun`, `rg`, and mise itself ship
bundled at build time for instant first-run availability; everything
else flows through mise on demand.
<img width=\"1304\" height=\"714\" alt=\"BinaryManager settings UI\"
src=\"https://github.com/user-attachments/assets/7a4b78ab-5aa2-4e97-9ab7-134b20a4d78d\"
/>
<img width=\"1165\" height=\"748\" alt=\"Three-state managed vs bundled
vs not-installed\"
src=\"https://github.com/user-attachments/assets/a0dcfb7d-8bc3-4acd-b563-0fc04d99e252\"
/>
<img width=\"523\" height=\"328\" alt=\"Custom tool dialog\"
src=\"https://github.com/user-attachments/assets/90c3ee95-7f2a-4daf-a334-f20de6ff5ca2\"
/>
Fixes#15183. Addresses #15370.
### Why we need it and why it was done in this way
Adding a new managed CLI tool should be a one-line preset entry — not 4+
files of bespoke download/extract/IPC code. mise is a mature polyglot
tool manager that already speaks the backends Cherry needs.
**Tradeoffs made:**
- **mise bundled at build time** (~15 MB per platform) rather than
downloaded at first run — faster first-run UX, no chicken-and-egg on a
fresh install.
- **Fully isolated mise environment** (\`HOME\`/\`XDG_*\`/\`MISE_*\` all
relocated under \`feature.binaries.data\`) — Cherry never reads or
writes the user's own \`~/.config/mise/\` or \`~/.local/share/mise/\`.
- **No custom \`BinaryBackend\` interface.** mise's grammar (\`npm:\`,
\`pipx:\`, \`github:\`, registry) is already polyglot; wrapping it would
be a shallow seam that re-implements what mise owns. Removing this
abstraction makes consumers simpler (deletion test passes).
- **Auth-token policy: opt-in only.** Ambient \`GITHUB_TOKEN\` /
\`GH_TOKEN\` are not forwarded into mise's process env. Users who hit
GitHub's unauthenticated 60 req/hr API limit can set
\`CHERRY_GITHUB_TOKEN\` to raise it to 5000 req/hr without consenting to
share their general shell token.
- **China mirror auto-detection.** \`isUserInChina()\` toggles
\`NPM_CONFIG_REGISTRY=registry.npmmirror.com\` +
\`PIP_INDEX_URL=pypi.tuna.tsinghua.edu.cn\` for every npm/pipx backend
transparently.
**Alternatives considered:**
- *Keep per-tool install scripts.* Doesn't scale — each new tool is 4+
files of duplicated logic.
- *Use mise from user's \`PATH\`.* Would depend on user having mise
installed and could conflict with their config.
- *Custom \`BinaryBackend\` abstraction.* Shallow wrapper over mise's
grammar; no second backend in sight; deletion test passes.
**Scope (what's in / what's out):**
- **In:** uv, bun, ripgrep, claude-code, openclaw, gh, opencode,
gemini-cli, lark, kimi-cli, qwen-code, iflow-cli, github-copilot-cli —
anything mise can install as a single relocatable binary.
- **Out:** \`OvmsManager\` (multi-file server provisioning, hardware
detection, generated config); Tesseract OCR data (not a binary; lives
with \`OvOcrService\`).
### Breaking changes
None at the user-facing layer. v2 data is throwaway per CLAUDE.md, so
the preference-key rename (\`feature.mise.*\` → \`feature.binaries.*\`)
intentionally ships without a migrator.
### Special notes for your reviewer
**Architecture & docs**
- \`docs/references/binary-manager/README.md\` — scope criterion,
persisted/contract surface, bundled-vs-mise state contract, China mirror
behavior, \`CHERRY_GITHUB_TOKEN\` opt-in, adding a new managed binary.
- \`CLAUDE.md\` adds a \`**MUST READ**\` link next to Lifecycle / Window
Manager / Data / Paths.
- The mise-shim-wins-over-\`cherry.bin\` precedence rule is documented
in the README's "State contract" section.
**Code orientation**
- \`src/main/services/BinaryManager.ts\` — the lifecycle service. Wraps
mise via \`runMise()\`; isolated env in \`buildIsolatedEnv()\`; bundled
extraction with atomic tmp+rename; per-tool try/catch so a single
failure can't abort init; \`isManagedBinaryReady()\` verifies the
resolved file is executable (not just that mise thinks it's installed).
- \`packages/shared/data/presets/binary-tools.ts\` —
\`PREDEFINED_BINARY_TOOLS\` registry; \`tool\` field is a mise spec.
-
\`src/renderer/src/pages/settings/McpSettings/EnvironmentDependencies.tsx\`
— three-state UI (\`managed\` / \`bundled\` / \`not-installed\`) backed
by \`Binary_GetState\` + \`Binary_ProbeBundled\`.
- \`scripts/download-binaries.js\` — build-time downloader for mise / uv
/ bun / rg (HTTPS + sha256-verified, archive-aware extraction).
**Migration**
- \`OpenClawService.install()\` is now two lines delegating to
\`BinaryManager\` — \`install-openclaw.js\` is gone.
- \`CodeCliService\` no longer uses \`bun install -g\`; the
\`BUN_INSTALL\` / \`~/.cherrystudio/install/global/\` path is removed.
- \`FileStorage.getRipgrepBinaryPath()\` now resolves via
\`getBinaryPath('rg')\`; the vendored SDK rg is no longer used.
- \`extractRtkBinaries\` + the \`AgentBootstrapService\` call are
deleted. \`rtkRewrite()\` degrades gracefully when rtk is absent;
\`rtkAvailable\` caches with a 60s TTL so install-via-mise takes effect
without restart.
**Multi-round review**
Two adversarial review rounds against this branch (Bug Hunter / Security
/ Architecture / Correctness) ran during development; both rounds'
High-severity findings are addressed in commits \`70afde6af\` and
\`1d864439d\`. R3 known follow-ups (architecture duplications in
\`CodeCliService\`'s switch statements, etc.) are tracked as Medium and
intentionally deferred.
### Checklist
- [x] PR: The PR description is expressive enough and will help future
contributors
- [x] Code: Write code that humans can understand and Keep it simple
- [x] Refactor: Leaves binary acquisition meaningfully cleaner than
before (five mechanisms → one)
- [x] Upgrade: v2 data is throwaway; no migrator needed and the absence
is intentional
- [x] Documentation: \`docs/references/binary-manager/README.md\` +
\`CLAUDE.md\` Architecture section
- [x] Self-review: Two multi-perspective review rounds against the
branch; all Highs addressed
### Release note
\`\`\`release-note
NONE
\`\`\`
---------
Signed-off-by: Vaayne <liu.vaayne@gmail.com>
Signed-off-by: Vaayne Liu <vaayne@macos.shared>
Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com>
### What this PR does
Before this PR:
Local Antigravity CLI files were not ignored and could appear in `git
status`.
After this PR:
`.antigravitycli/*` is ignored so local Antigravity CLI files stay out
of the repository status.
Fixes #N/A
### Why we need it and why it was done in this way
The following tradeoffs were made:
This keeps the fix scoped to a single ignore rule and avoids touching
any runtime or product code.
The following alternatives were considered:
Leaving these files unignored or requiring each contributor to maintain
a personal global ignore rule.
Links to places where the discussion took place: N/A
### Breaking changes
None.
If this PR introduces breaking changes, please describe the changes and
the impact on users.
N/A
### Special notes for your reviewer
None.
### Checklist
This checklist is not enforcing, but it's a reminder of items that could
be relevant to every PR.
Approvers are expected to review this list.
- [x] PR: The PR description is expressive enough and will help future
contributors
- [x] Code: [Write code that humans can
understand](https://en.wikiquote.org/wiki/Martin_Fowler#code-for-humans)
and [Keep it simple](https://en.wikipedia.org/wiki/KISS_principle)
- [ ] Refactor: You have [left the code cleaner than you found it (Boy
Scout
Rule)](https://learning.oreilly.com/library/view/97-things-every/9780596809515/ch08.html)
- [x] Upgrade: Impact of this change on upgrade flows was considered and
addressed if required
- [ ] Documentation: A [user-guide update](https://docs.cherry-ai.com)
was considered and is present (link) or not required. Check this only
when the PR introduces or changes a user-facing feature or behavior.
- [x] Self-review: I have reviewed my own code (e.g., via
[`/gh-pr-review`](/.claude/skills/gh-pr-review/SKILL.md), `gh pr diff`,
or GitHub UI) before requesting review from others
### Release note
```release-note
NONE
```
Signed-off-by: ousugo <dkzyxh@gmail.com>
### What this PR does
Before this PR:
Agent Bash tool calls output raw, verbose shell command results that
consume excessive LLM tokens.
After this PR:
Bash commands are transparently rewritten via
[rtk](https://github.com/rtk-ai/rtk) to produce concise, LLM-friendly
output — reducing token consumption by 60-90% on common shell commands
(`cat`, `grep`, `find`, `ls`, etc.).
<img width="647" height="578" alt="image"
src="https://github.com/user-attachments/assets/438de126-c79d-4b69-bf3b-65a220671900"
/>
Fixes#13600
### Why we need it and why it was done in this way
rtk is a single Rust binary (MIT licensed, zero dependencies) that
rewrites shell commands into optimized versions. When a command has no
rtk equivalent, it passes through unchanged — zero risk of breaking
existing workflows.
The integration follows three layers:
1. **Build time**: `scripts/download-rtk-binaries.js` downloads
platform-specific rtk and jq binaries into `resources/binaries/`
(bundled via existing `asarUnpack: resources/**`)
2. **First run**: `extractRtkBinaries()` copies binaries from app
resources to `~/.cherrystudio/bin/` (follows existing binary
distribution pattern used by bun, uv, openclaw)
3. **Runtime**: A `PreToolUse` hook in the Claude Code service
intercepts Bash tool calls, runs `rtk rewrite "<command>"`, and
substitutes the optimized command if available
The following tradeoffs were made:
- Binaries are bundled in the app package (increases app size ~5MB)
rather than downloaded on demand — ensures rtk is always available
without network dependency
- jq is bundled alongside rtk for potential external hook script usage,
even though the TypeScript hook doesn't need it
- `rtkRewrite()` is async (non-blocking) to avoid stalling the main
process event loop
The following alternatives were considered:
- On-demand download (like bun/uv install scripts) — rejected because
rtk should "always be on" per requirements
- System PATH detection only — rejected because it requires users to
install rtk manually
### Breaking changes
None. The rtk rewrite is transparent and falls back gracefully when rtk
is unavailable or a command has no optimized version.
### Special notes for your reviewer
- The download script is non-fatal: if binary download fails during
build, the build continues without rtk
- The hook runs before the existing `preToolUseHook` (permission
handling), so commands are rewritten before permission checks
- Version guard requires rtk >= 0.23.0 (when `rtk rewrite` subcommand
was introduced)
### Checklist
- [x] PR: The PR description is expressive enough and will help future
contributors
- [x] Code: Write code that humans can understand and Keep it simple
- [x] Refactor: You have left the code cleaner than you found it (Boy
Scout Rule)
- [ ] Upgrade: Impact of this change on upgrade flows was considered and
addressed if required
- [ ] Documentation: A user-guide update was considered and is present
(link) or not required
- [x] Self-review: I have reviewed my own code before requesting review
from others
### Release note
```release-note
Integrate rtk to automatically optimize agent shell commands for 60-90% token savings
```
---------
Signed-off-by: Vaayne <liu.vaayne@gmail.com>
### What this PR does
Before this PR:
- Provider/model icons were scattered image imports (PNG/WebP) with no
unified API
- Avatar primitive was based on HeroUI with hardcoded `shadow-lg` and
`border-[0.5px]`
- Full-bleed and padded avatar variants used different rendering
approaches
- Multiple files duplicated IIFE patterns for rendering CompoundIcon vs
string logos
- No type-safe icon catalogs
After this PR:
- **Compound Icon API**: Each icon exposes `.Color`, `.Mono`, and
`.Avatar` sub-components via a unified `CompoundIcon` interface
- **Auto-generated catalogs**: `PROVIDER_ICON_CATALOG` and
`MODEL_ICON_CATALOG` with `resolveProviderIcon` / `resolveModelIcon`
helpers
- **SVG pipeline**: Codegen processes SVGs → generates Color/Mono/Avatar
components
- **Avatar migrated to shadcn/radix**: Replaced HeroUI Avatar with
`Avatar` + `AvatarFallback` pattern, removed hardcoded shadow/border
- **EmojiAvatar moved**: From `primitives/Avatar/` to
`composites/EmojiAvatar/`
- **LogoAvatar component**: Reusable component replacing repeated IIFE
patterns across 5+ files
- **getMCPProviderLogo helper**: Centralized MCP provider icon mapping
- 80+ monochrome icon components, stroke attribute support, deprecated
logos cleanup
<img width="714" height="820" alt="image"
src="https://github.com/user-attachments/assets/a3f14348-5781-494a-8c3b-1f40391e2ec0"
/>
<img width="1008" height="593" alt="image"
src="https://github.com/user-attachments/assets/8ba7fa42-fa33-4e49-ba76-647ba1438e0c"
/>
### Why we need it and why it was done in this way
The v2 refactoring requires moving away from HeroUI toward shadcn/radix
primitives, and needs a scalable, type-safe icon system to replace
scattered image imports. The compound icon pattern (`Icon.Color`,
`Icon.Mono`, `Icon.Avatar`) provides a consistent API while enabling
tree-shaking. The Avatar primitive now uses radix-based `Avatar` +
`AvatarFallback`, aligning with the project's shadcn migration.
The following tradeoffs were made:
- Each icon is a separate TSX file for tree-shaking and lazy loading
support
- Avatar components use `AvatarFallback` to render icons — no image
loading overhead
The following alternatives were considered:
- Runtime SVG color manipulation — rejected for better performance and
consistency
- Keeping HeroUI Avatar — rejected as it conflicts with v2 shadcn
migration goals
### Breaking changes
- Avatar primitive API changed: `HeroUI Avatar` → shadcn `Avatar` +
`AvatarFallback` + `AvatarImage`
- `EmojiAvatar` moved from `primitives/Avatar` to
`composites/EmojiAvatar`
- `shadow-lg` and `border-[0.5px]` removed from generated avatars — now
opt-in via `className`
### Special notes for your reviewer
- ~214 files changed, but the bulk are auto-generated avatar/icon
components under `packages/ui/src/components/icons/`
- Key files to review:
- `packages/ui/src/components/primitives/avatar.tsx` — new shadcn Avatar
primitive
- `packages/ui/scripts/codegen.ts` — avatar generation using
AvatarFallback
- `src/renderer/src/components/Icons/LogoAvatar.tsx` — reusable logo
renderer
- Renderer files using the new Avatar API (Sidebar, UserPopup,
ModelAvatar, etc.)
### Checklist
- [x] PR: The PR description is expressive enough and will help future
contributors
- [x] Code: Write code that humans can understand and Keep it simple
- [x] Refactor: You have left the code cleaner than you found it (Boy
Scout Rule)
- [ ] Upgrade: Impact of this change on upgrade flows was considered and
addressed if required
- [ ] Documentation: N/A - internal component changes
### Release note
```release-note
NONE
```
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Signed-off-by: suyao <sy20010504@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: icarus <eurfelux@gmail.com>
### What this PR does
Before this PR:
- No Zed editor configuration example existed for contributors using Zed
- Several config files had inconsistent JSON array formatting
- `biome.jsonc` had redundant exclude rules
- Contributing guides did not reference the development guide
- `development.md` (zh) was not translated to Chinese
- Node.js and pnpm versions were hardcoded in the development guide
After this PR:
- Added `.zed/settings.json.example` with Biome formatter,
oxc/eslint/biome fixAll, and import organization
- Cleaned up redundant Biome exclude rules and unified JSON array
formatting
- Added "Setting Up Your Development Environment" section to
`CONTRIBUTING.md` (en/zh) linking to the development guide
- Added Zed editor setup guide to `development.md` (en/zh)
- Translated `docs/zh/guides/development.md` to Chinese
- Node.js version now references `.node-version`; pnpm version
references `packageManager` in `package.json`
- VSCode extensions now reference `.vscode/extensions.json`
### Why we need it and why it was done in this way
The following tradeoffs were made:
- The Zed settings file is provided as an `.example` rather than a
direct `.zed/settings.json` to avoid overriding individual contributor
preferences.
- Versions reference their source of truth files rather than being
hardcoded, so docs stay in sync automatically.
The following alternatives were considered:
- N/A
### Breaking changes
None
### Special notes for your reviewer
- The JSON formatting changes are purely cosmetic — no behavior changes.
They align with Biome's default formatting rules.
- The `.zed/settings.json.example` includes `source.fixAll.eslint` and
`source.fixAll.oxc` alongside Biome, matching the project's
triple-linter setup.
### Checklist
- [x] PR: The PR description is expressive enough and will help future
contributors
- [x] Code: [Write code that humans can
understand](https://en.wikiquote.org/wiki/Martin_Fowler#code-for-humans)
and [Keep it simple](https://en.wikipedia.org/wiki/KISS_principle)
- [x] Refactor: You have [left the code cleaner than you found it (Boy
Scout
Rule)](https://learning.oreilly.com/library/view/97-things-every/9780596809515/ch08.html)
- [x] Upgrade: Impact of this change on upgrade flows was considered and
addressed if required
- [x] Documentation: A [user-guide update](https://docs.cherry-ai.com)
was considered and is present (link) or not required. Check this only
when the PR introduces or changes a user-facing feature or behavior.
- [x] Self-review: I have reviewed my own code (e.g., via
[`/gh-pr-review`](/.claude/skills/gh-pr-review/SKILL.md), `gh pr diff`,
or GitHub UI) before requesting review from others
### Release note
```release-note
NONE
```
---------
Signed-off-by: icarus <eurfelux@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
### What this PR does
Before this PR:
Agent and Assistant were mixed in a single `UnifiedList` in the home
page sidebar. Users had difficulty discovering the Agent entry. The two
have fundamentally different data models (Redux vs SQLite), interaction
patterns (topic vs session), and component hierarchies, yet shared the
same UI components and Redux state (`activeTopicOrSession`).
After this PR:
Agent is separated into an independent module with its own sidebar
entry, route (`/agents`), page, navbar, and side panel. The home page
only handles Assistants. Navigation between the two is handled via
sidebar icons and routes, not Redux state.
Fixes#13329
### Why we need it and why it was done in this way
The following tradeoffs were made:
- `AgentSettingsTab` was moved to `pages/agents/` and is used by the
`AgentChatNavbar/Tools/SettingsButton` drawer.
- `Unified*` components were renamed to `Assistant*` (via `git mv`)
rather than just removing agent code, to make naming accurate and
improve readability.
- `activeTopicOrSession` was removed from Redux runtime store entirely,
replaced by route-based detection where needed, avoiding stale state
issues.
The following alternatives were considered:
- Keeping a shared `UnifiedList` with a filter — rejected because the
data models and interaction patterns are too different, leading to
excessive conditional logic.
- Using a tab within the home page — rejected per issue spec; agents
need their own sidebar entry and dedicated page for discoverability.
### Breaking changes
None. This is an internal UI refactoring. The Redux migration (v200 →
v201) automatically adds the `'agents'` sidebar icon to existing user
configurations.
### Special notes for your reviewer
**New directory structure — `pages/agents/`:**
- `AgentPage.tsx` — Top-level page with apiServer.enabled guard (early
return with alert when server disabled)
- `AgentChat.tsx` — Chat area with loading state management (Spin during
initialization, alerts for select/create states)
- `AgentNavbar.tsx` — Top navbar for left-sidebar layout mode
- `AgentSidePanel.tsx` — Left panel with agent list and sessions tabs
- `AgentSettingsTab.tsx` — Moved from home, used by AgentChatNavbar
settings drawer
- `components/AgentChatNavbar/` — Mirrors `home/components/ChatNavBar/`
structure:
- `index.tsx` — Sidebar toggle buttons + content wrapper
- `AgentContent.tsx` — Agent → Session → Model → Workspace breadcrumb
navigation
- `Tools/` — Agent-specific toolbar with `SettingsButton` (uses
`AgentSettingsTab`)
- `OpenExternalAppButton.tsx`, `SessionWorkspaceMeta.tsx` —
AgentContent-only components
- `components/` — Migrated agent-only components: `AgentItem`,
`AgentSessionInputbar`, `AgentSessionMessages`,
`SelectAgentBaseModelButton`, `SessionItem`, `Sessions`
**Hook consolidation:**
- Merged two duplicate `useActiveAgent` hooks into one at
`hooks/agents/useActiveAgent` — now returns both `{ agent, error,
isLoading, setActiveAgentId }`
- Deleted `home/Tabs/hooks/useActiveAgent.ts`
**Loading state improvements:**
- `AgentPage` top-level guard prevents all child components from
rendering when apiServer is disabled
- `AgentChat` tracks `isInitializing` covering: server starting → agents
loading → agent loading → session initializing → auto-select pending
- `useAgentSessionInitializer` now distinguishes `undefined` (not
initialized) vs `null` (initialized, no sessions) in
`activeSessionIdMap`, preventing premature "create session" alerts
**Shared component extraction:**
- `AddButton` moved from `home/Tabs/components/` to
`renderer/src/components/` (used by both pages)
### Checklist
- [x] PR: The PR description is expressive enough and will help future
contributors
- [x] Code: Write code that humans can understand and Keep it simple
- [x] Refactor: You have left the code cleaner than you found it (Boy
Scout Rule)
- [x] Upgrade: Impact of this change on upgrade flows was considered and
addressed if required
- [x] Documentation: A user-guide update was considered and is present
(link) or not required. Check this only when the PR introduces or
changes a user-facing feature or behavior.
- [x] Self-review: I have reviewed my own code before requesting review
from others
### Release note
```release-note
Added a dedicated "Agents" page accessible from the sidebar, separating Agents from the Assistants list for improved discoverability and clearer navigation.
```
---------
Signed-off-by: icarus <eurfelux@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: kangfenmao <kangfenmao@qq.com>
### What this PR does
Before this PR:
- CLAUDE.md contained detailed PR workflow instructions that were loaded
in every agent session, consuming unnecessary tokens
- No unified project-level skills management mechanism; adding public
skills lacked standardization
- No automated checks to prevent non-compliant skills from being merged
- Team members had no convenient way to share skills with each other
After this PR:
- Simplified PR instructions in CLAUDE.md, now loaded on-demand via the
`gh-create-pr` skill
- Introduced project-level skills management (`.agents/skills/`
directory + `public-skills.txt` whitelist)
- Added `scripts/skills-sync.ts` and `scripts/skills-check.ts` for
automated management
- Integrated skills validation into CI to prevent non-whitelisted skills
from being merged
- **Teams can now easily share skills through the project-level
mechanism**, with `skills-sync.ts` automatically syncing skills to all
team members' local environments, streamlining onboarding and avoiding
duplicated configuration efforts
- **Optimized PR creation workflow**: `gh-create-pr` skill enforces
English PR body writing and displays the draft to users for review
before creation, ensuring quality and compliance
Fixes #
### Why we need it and why it was done in this way
The following tradeoffs were made:
- Moved PR workflow from CLAUDE.md to a skill, sacrificing immediate
visibility for token efficiency
- **Introduced whitelist mechanism (`public-skills.txt`) instead of
auto-scanning all files**: Allows developers to freely use private
project-level skills in the `.agents/skills/` directory (e.g.,
team-internal skills, personal customizations). Only skills added to the
whitelist are tracked by git and submitted. This ensures standardization
for shared skills while preserving development flexibility
- Skills exist in both `.agents/skills/` (project-level, shareable) and
`.claude/skills/` (local, private)
- **Symlink only SKILL.md files instead of entire directories**: On some
Windows/restricted filesystems, symlinks may fail or be treated as
regular files. If an entire directory is symlinked, failure results in a
regular file instead of a directory, causing complete skill failure
that's hard to diagnose. Symlinking only SKILL.md allows quick detection
when symlinks fail (file content displays directly or errors), reducing
troubleshooting costs
The following alternatives were considered:
- Keeping PR instructions in CLAUDE.md with collapsible blocks, but this
still consumes context tokens
- Using git hooks for pre-commit checks, but CI checks are more reliable
and don't block local development
Links to places where the discussion took place: N/A
### Breaking changes
None
### Special notes for your reviewer
- `gh-create-pr` skill fully implements the project's PR workflow
requirements (read template → display body → confirm → create)
- `skills-check.ts` validates: 1) tracked skills are in the whitelist;
2) whitelist skills have corresponding files
- Process for adding new public skills: 1) create skill files; 2) add to
`public-skills.txt`; 3) CI auto-validation
- `.claude/skills/` added to `.gitignore` for private skills
### Checklist
This checklist is not enforcing, but it's a reminder of items that could
be relevant to every PR.
Approvers are expected to review this list.
- [x] PR: The PR description is expressive enough and will help future
contributors
- [x] Code: [Write code that humans can
understand](https://en.wikiquote.org/wiki/Martin_Fowler#code-for-humans)
and [Keep it simple](https://en.wikipedia.org/wiki/KISS_principle)
- [x] Refactor: You have [left the code cleaner than you found it (Boy
Scout
Rule)](https://learning.oreilly.com/library/view/97-things-every/9780596809515/ch08.html)
- [x] Upgrade: Impact of this change on upgrade flows was considered and
is present (link) or not required. You want a user-guide update if it's
a user facing feature.
- [ ] Documentation: A user-guide update was considered and is present
(link) or not required. You want a user-guide update if it's a user
facing feature.
### Release note
```release-note
Optimize PR workflow by moving instructions to on-demand skill; introduce project-level skills management with automated validation
```
* Add .codebuddy and .zed to .gitignore and fix formatApiHost
Prevent formatApiHost from processing undefined/empty host values and
ignore editor-specific directories
* Refactor reasoning tag selection logic for providers
Move gpt-oss model handling from aws-bedrock case to openai case and
consolidate tag selection logic into a single if-else chain.
* Extract reasoning tag name into helper function
* fix test
* Replace array indexing with named object properties for reasoning tags
Improves code readability by using descriptive property names instead of
magic array indices when selecting reasoning tag names by model type.
* Move host validation to start of formatApiHost
- Added support for TypeScript incremental builds by enabling the `incremental` option and specifying the `tsBuildInfoFile` in both `tsconfig.node.json` and `tsconfig.web.json`.
- Updated the `typecheck` script in `package.json` to use `concurrently` for running node and web type checks in parallel.
- Added `.tsbuildinfo` to `.gitignore` to prevent build info files from being tracked.
- Introduced a new .env.example file with NODE_OPTIONS configuration.
- Updated .gitignore to exclude .env.example from being ignored.
- Added instructions in dev.md for copying .env.example to .env.
* test: more unit tests
- Adjust vitest configuration to handle main process and renderer process tests separately
- Add unit tests for main process utils
- Add unit tests for the renderer process
- Add three component tests to verify vitest usage: `DragableList`, `Scrollbar`, `QuickPanelView`
- Add an e2e startup test to verify playwright usage
- Extract `splitApiKeyString` and add tests for it
- Add and format some comments
* fix: mock individual properties
* test: add tests for CustomTag
* test: add tests for ExpandableText
* test: conditional rendering tooltip of tag
* chore: update dependencies