Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion agents/base2/base2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ ${
- **Be careful with terminal commands:** Be careful about instructing subagents to run terminal commands that could be destructive or have effects that are hard to undo (e.g. git push, git commit, running any scripts -- especially ones that could alter production environments (!), installing packages globally, etc). Don't run any of these effectful commands unless the user explicitly asks you to.
- **Do what the user asks:** If the user asks you to do something, even running a risky terminal command, do it.
- **Don't use set_output:** The set_output tool is for spawned subagents to report results. Don't use it yourself.
- **Discover and install skills:** Skills are reusable, self-contained instructions for accomplishing a task. Beyond the skills already listed for the \`skill\` tool, you can find and install community skills from the command line: \`npx skills find <query>\` to search, \`npx skills add <owner/repo> --list\` to preview a repo's skills, and \`npx skills add <owner/repo> --skill <name> --yes\` to install one into \`.agents/skills/\`. After installing, load it by name with the \`skill\` tool. These community skills are not vetted, so confirm with the user which skill(s) to install before running \`npx skills add\`.${
- **Discover and install skills:** Skills are reusable, self-contained instructions for accomplishing a task. Pre-loaded skills are already in your system prompt (see "# Pre-loaded Skills" above) — you do NOT need to call the \`skill\` tool to load them. To install new community skills, use the \`/skills install <owner/repo> [--skill <name>]\` slash command, or run \`npx skills add <owner/repo> --skill <name> --yes\` from the terminal. Use \`/skills list\` to see available skills. These community skills are not vetted, so confirm with the user which skill(s) to install before running \`npx skills add\`. Note: Newly installed skills won't appear until the next session — tell the user to restart or start a new chat to pick them up.${
ENABLE_COMPOSIO_TOOLS
? `
- **External apps:** When Composio tools are available and the user asks to work with connected apps or services like Gmail, Google Calendar, GitHub, Slack, Linear, or Notion, use them to search for the right app tools, help the user connect their account (use the render_ui tool to show a button if the user needs to click a link), and execute the requested action.`
Expand Down
116 changes: 115 additions & 1 deletion cli/src/commands/command-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,12 @@ import { AGENT_MODES, END_SESSION_MESSAGE, IS_FREEBUFF } from '../utils/constant
import { exitCliCleanly } from '../utils/exit-cleanly'
import { getSystemMessage, getUserMessage } from '../utils/message-history'
import { capturePendingAttachments } from '../utils/pending-attachments'
import { getSkillByName } from '../utils/skill-registry'
import {
getSkillByName,
getLoadedSkills,
initializeSkillRegistry,
} from '../utils/skill-registry'
import { execSync } from 'child_process'

import type { MultilineInputHandle } from '../components/multiline-input'
import type { InputValue, PendingAttachment } from '../types/store'
Expand Down Expand Up @@ -615,6 +620,115 @@ const ALL_COMMANDS: CommandDefinition[] = [
})
},
}),
// /skills install <owner/repo> [--skill <name>] — install a skill from a GitHub repo
defineCommandWithArgs({
name: 'skills',
aliases: [],
handler: async (params, args) => {
const trimmedArgs = args.trim()
params.saveToHistory(params.inputValue.trim())
clearInput(params)

// Parse subcommand
const parts = trimmedArgs.split(/\s+/)
const subcommand = parts[0]?.toLowerCase()

if (subcommand === 'list') {
const skills = getLoadedSkills()
const skillNames = Object.keys(skills)
if (skillNames.length === 0) {
params.setMessages((prev) => [
...prev,
getSystemMessage(
'No skills installed.\n\nInstall skills with: /skills install <owner/repo> [--skill <name>]\nOr from the terminal: npx skills add <owner/repo> --skill <name> --yes',
),
])
} else {
const list = skillNames
.map(
(name) =>
` • ${name}: ${skills[name].description.slice(0, 80)}`,
)
.join('\n')
params.setMessages((prev) => [
...prev,
getSystemMessage(
`Installed skills (${skillNames.length}):\n${list}\n\nSkills are automatically available to the agent. Install more with: /skills install <owner/repo> [--skill <name>]`,
),
])
}
return
}

if (subcommand === 'install') {
const repo = parts[1]
if (!repo) {
params.setMessages((prev) => [
...prev,
getSystemMessage(
'Usage: /skills install <owner/repo> [--skill <name>]\n\nExample: /skills install anthropics/skills --skill git-release',
),
])
return
}

// Parse --skill flag
const skillFlagIdx = parts.indexOf('--skill')
const skillName =
skillFlagIdx !== -1 ? parts[skillFlagIdx + 1] : undefined
const extraArgs = skillFlagIdx !== -1 ? parts.slice(skillFlagIdx + 2) : []

const installCmd = [
'npx',
'skills',
'add',
repo,
...(skillName ? ['--skill', skillName] : []),
'--yes',
...extraArgs,
].join(' ')

params.setMessages((prev) => [
...prev,
getSystemMessage(`Installing skill from ${repo}...`),
])

try {
const output = execSync(installCmd, {
encoding: 'utf8',
stdio: 'pipe',
timeout: 60_000,
})
// Refresh the skill registry so newly installed skills are picked up
await initializeSkillRegistry()
params.setMessages((prev) => [
...prev,
getSystemMessage(
`${output.trim()}\n\nSkill installed to .agents/skills/. It will be available in your next session (use /new to start a fresh chat).`,
),
])
} catch (error) {
const errMsg =
error instanceof Error ? error.message : String(error)
params.setMessages((prev) => [
...prev,
getSystemMessage(
`Failed to install skill: ${errMsg}\n\nMake sure you have npx available and the repo exists.`,
),
])
}
return
}

// Unknown subcommand — show help
params.setMessages((prev) => [
...prev,
getSystemMessage(
'Skills commands:\n /skills list — show installed skills\n /skills install <owner/repo> [--skill <name>] — install a skill from GitHub\n\nExample: /skills install anthropics/skills --skill git-release',
),
])
},
}),
]

export const COMMAND_REGISTRY: CommandDefinition[] = IS_FREEBUFF
Expand Down
6 changes: 6 additions & 0 deletions cli/src/data/slash-commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,12 @@ const ALL_SLASH_COMMANDS: SlashCommand[] = [
// label: 'publish',
// description: 'Publish agents to the agent store',
// },
{
id: 'skills',
label: 'skills',
description: 'Install or list automatically-loaded skills',
aliases: [],
},
{
id: 'theme:toggle',
label: 'theme:toggle',
Expand Down
21 changes: 21 additions & 0 deletions packages/agent-runtime/src/run-agent-step.ts
Original file line number Diff line number Diff line change
Expand Up @@ -838,6 +838,27 @@ export async function loopAgentSteps(
system = systemPrompt ?? ''
}

// Inject loaded skills into the system prompt so they are always
// available without needing the agent to call the `skill` tool.
// Skills are installed via `/skills install` or `npx skills add`.
if (!agentTemplate.inheritParentSystemPrompt || !parentSystemPrompt) {
const skills = fileContext.skills ?? {}
const skillEntries = Object.values(skills)
if (skillEntries.length > 0) {
const skillsInstructions = skillEntries
.map(
(skill) => {
// Strip YAML frontmatter from the skill content so the model
// only sees the actual instructions, not metadata noise.
const body = skill.content.replace(/^---[\s\S]*?---\n*/, '').trim()
return `## Skill: ${skill.name}\n\n${body}`
},
)
.join('\n\n---\n\n')
system += `\n\n# Pre-loaded Skills\n\nThe following skills are pre-loaded and always available. You do NOT need to use the \`skill\` tool to load them — their full instructions are already part of your context. Use \`/skills install <owner/repo> [--skill <name>]\` to install more, or \`/skills list\` to see available skills.\n\n---\n\n${skillsInstructions}`
}
}

// Build agent tools (agents as direct tool calls) for non-inherited tools
const agentTools = useParentTools
? {}
Expand Down