Skip to content

feat(skills): add per-agent checkbox preferences#28422

Open
alastairsounds wants to merge 1 commit into
raycast:mainfrom
alastairsounds:feat/28377-skills-default-agents-picker
Open

feat(skills): add per-agent checkbox preferences#28422
alastairsounds wants to merge 1 commit into
raycast:mainfrom
alastairsounds:feat/28377-skills-default-agents-picker

Conversation

@alastairsounds
Copy link
Copy Markdown
Contributor

Description

This feature adds preference checkboxes to pre-select non-standard coding agents (Claude Code, Windsurf, etc..) The checkboxes are nested under the "Search Skills" command in preferences for the following reasons: 1.) "Search Skills" is the only command that utilizes the agent picker, and 2.) it allows the 54 checkboxes to be kept in a dropdown, rather than muddying up the entire preferences area.

Note: ray lint requires a description field per checkbox. I opted for each description to follow the pattern "Pre-select [Agent] in the install agent picker", but can adjust if we want to make it less verbose.

Possible README/store update: This feature might be worth updating in the README so users can see it on the Store page. Something like "Search for agent skills (pre-select default agents in Settings → Extensions → Skills → Search Skills)". If not, users may still naturally find it via the preferences menu.

Screencast

image image

Checklist

@raycastbot raycastbot added extension fix / improvement Label for PRs with extension's fix improvements extension: skills Issues related to the skills extension AI Extension platform: macOS platform: Windows labels May 29, 2026
@raycastbot
Copy link
Copy Markdown
Collaborator

Thank you for your contribution! 🎉

🔔 @keito4 @raulgg @DaleSeo @pernielsentikaer @kayotimoteo @alexibuild you might want to have a look.

You can use this guide to learn how to check out the Pull Request locally in order to test it.

📋 Quick checkout commands
BRANCH="feat/28377-skills-default-agents-picker"
FORK_URL="https://github.com/alastairsounds/raycast-extensions.git"
EXTENSION_NAME="skills"
REPO_NAME="raycast-extensions"

git clone -n --depth=1 --filter=tree:0 -b $BRANCH $FORK_URL
cd $REPO_NAME
git sparse-checkout set --no-cone "extensions/$EXTENSION_NAME"
git checkout
cd "extensions/$EXTENSION_NAME"
npm install && npm run dev

We're currently experiencing a high volume of incoming requests. As a result, the initial review may take up to 10-15 business days.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 29, 2026

Greptile Summary

This PR adds 54 per-agent checkbox preferences under the "Search Skills" command, allowing users to pre-select their preferred coding agents (Claude Code, Windsurf, Cursor, etc.) so they are checked by default when the install agent picker opens.

  • package.json: 54 checkbox preferences are added to the search-skills command, each following the agent_<normalized_name> naming convention and defaulting to false.
  • InstallSkillAction.tsx: On mount, the new preferences are read and used to seed the selected state via a name-normalization mapping (lowercase → underscores → strip non-alnum); agent names not present in the preference list simply default to unchecked.
  • CHANGELOG.md: New entry added at the top with the {PR_MERGE_DATE} placeholder.

Confidence Score: 4/5

Safe to merge; the only finding is a minor render-efficiency improvement in the useState initializer.

The feature is straightforward: preferences seed an initial Set that users can still override before submitting. The normalization logic correctly maps all 54 current agent names to their preference keys. The one issue is that getPreferenceValues() and the Set constructor are evaluated on every render rather than once, because a direct value is passed to useState instead of a lazy initializer callback.

extensions/skills/src/components/actions/InstallSkillAction.tsx — the useState initializer

Important Files Changed

Filename Overview
extensions/skills/package.json Adds 54 per-agent checkbox preferences to the "Search Skills" command, enabling users to pre-select agents in the install picker; preference names, types, and descriptions are well-formed.
extensions/skills/src/components/actions/InstallSkillAction.tsx Reads agent preferences and uses them to derive the initial selection state; agentPrefs and the Set constructor are evaluated on every render rather than only on mount.
extensions/skills/CHANGELOG.md New changelog entry correctly uses {PR_MERGE_DATE} and is placed at the top in descending order.
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
extensions/skills/src/components/actions/InstallSkillAction.tsx:177-193
The `agentPrefs` object and the `Set` constructor for the initial state are both recomputed on every render, even though they're only consumed by `useState` on the first render. Using a lazy initializer avoids the redundant work on re-renders triggered by `setSelected`.

```suggestion
  const [selected, setSelected] = useState<Set<string>>(() => {
    const agentPrefs: Record<string, boolean> = {};
    for (const [key, value] of Object.entries(getPreferenceValues<Preferences>())) {
      if (key.startsWith("agent_") && typeof value === "boolean") {
        agentPrefs[key] = value;
      }
    }
    return new Set(
      selectableAgents.filter((a) => {
        const key = `agent_${a
          .toLowerCase()
          .replace(/\s+/g, "_")
          .replace(/[^a-z0-9_]/g, "")}`;
        return agentPrefs[key] === true;
      }),
    );
  });
```

Reviews (1): Last reviewed commit: "feat(skills): add per-agent checkbox pre..." | Re-trigger Greptile

Comment on lines +177 to +193
const agentPrefs: Record<string, boolean> = {};
for (const [key, value] of Object.entries(getPreferenceValues<Preferences>())) {
if (key.startsWith("agent_") && typeof value === "boolean") {
agentPrefs[key] = value;
}
}
const [selected, setSelected] = useState<Set<string>>(
new Set(
selectableAgents.filter((a) => {
const key = `agent_${a
.toLowerCase()
.replace(/\s+/g, "_")
.replace(/[^a-z0-9_]/g, "")}`;
return agentPrefs[key] === true;
}),
),
);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 The agentPrefs object and the Set constructor for the initial state are both recomputed on every render, even though they're only consumed by useState on the first render. Using a lazy initializer avoids the redundant work on re-renders triggered by setSelected.

Suggested change
const agentPrefs: Record<string, boolean> = {};
for (const [key, value] of Object.entries(getPreferenceValues<Preferences>())) {
if (key.startsWith("agent_") && typeof value === "boolean") {
agentPrefs[key] = value;
}
}
const [selected, setSelected] = useState<Set<string>>(
new Set(
selectableAgents.filter((a) => {
const key = `agent_${a
.toLowerCase()
.replace(/\s+/g, "_")
.replace(/[^a-z0-9_]/g, "")}`;
return agentPrefs[key] === true;
}),
),
);
const [selected, setSelected] = useState<Set<string>>(() => {
const agentPrefs: Record<string, boolean> = {};
for (const [key, value] of Object.entries(getPreferenceValues<Preferences>())) {
if (key.startsWith("agent_") && typeof value === "boolean") {
agentPrefs[key] = value;
}
}
return new Set(
selectableAgents.filter((a) => {
const key = `agent_${a
.toLowerCase()
.replace(/\s+/g, "_")
.replace(/[^a-z0-9_]/g, "")}`;
return agentPrefs[key] === true;
}),
);
});
Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/skills/src/components/actions/InstallSkillAction.tsx
Line: 177-193

Comment:
The `agentPrefs` object and the `Set` constructor for the initial state are both recomputed on every render, even though they're only consumed by `useState` on the first render. Using a lazy initializer avoids the redundant work on re-renders triggered by `setSelected`.

```suggestion
  const [selected, setSelected] = useState<Set<string>>(() => {
    const agentPrefs: Record<string, boolean> = {};
    for (const [key, value] of Object.entries(getPreferenceValues<Preferences>())) {
      if (key.startsWith("agent_") && typeof value === "boolean") {
        agentPrefs[key] = value;
      }
    }
    return new Set(
      selectableAgents.filter((a) => {
        const key = `agent_${a
          .toLowerCase()
          .replace(/\s+/g, "_")
          .replace(/[^a-z0-9_]/g, "")}`;
        return agentPrefs[key] === true;
      }),
    );
  });
```

How can I resolve this? If you propose a fix, please make it concise.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI Extension extension fix / improvement Label for PRs with extension's fix improvements extension: skills Issues related to the skills extension platform: macOS platform: Windows

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants