feat: auto-discover local shell skills from ./skills/#16
Merged
Conversation
This was referenced Apr 6, 2026
Agents can now load local skill directories (e.g. ~/.claude/skills/) via the shellSkills config key. Each skill's description is auto-read from its SKILL.md frontmatter. A 30s-timeout async subprocess executor handles command execution, respecting per-request timeout_ms when provided. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Skills are now loaded from <repo>/skills/*/SKILL.md at agent init instead of being listed in servers_config.json. - Skill name is taken from the directory name; description is parsed from the SKILL.md YAML frontmatter. - Rewrote _shell_executor to match the SDK ShellCommandRequest API: iterate action.commands and use create_subprocess_shell. - Removed MagicMock-based executor tests; kept config-to-tool mapping tests against a monkeypatched SKILLS_DIR. - Added skills/.gitignore so users can drop their own skills into the directory without polluting the repo.
mypy could not narrow the dict literal {"type": "local", "skills": ...}
to ShellToolLocalEnvironment; use the TypedDict constructors from the
agents SDK so the types are explicit.
72cd2c4 to
cdbbf12
Compare
- Strip matched quotes from YAML frontmatter description values - Use ShellCommandRequest type instead of Any for executor parameter - Use 'is not None' for timeout_ms check to distinguish 0 from None - Catch OSError from create_subprocess_shell and return error message - Append [exit code: N] to output for non-zero exit codes - Add direct unit tests for _parse_skill_description and _shell_executor
Shell skills and ShellTool are now disabled by default. Set SHELL_SKILLS_ENABLED=1 to opt in. Update README with the new env var, add missing instructions.md mount in Docker example, and list shell skills in the Features section.
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
Enables the bot to load local shell skills (like
obsidian-cli) through the agents SDKShellToolwithenvironment={"type": "local", ...}. Skills are auto-discovered from./skills/*/SKILL.mdat agent init — no config entries required.Supersedes #9, which used an explicit
shellSkillsfield inservers_config.json. Auto-discovery keeps the config file focused on MCP servers and instructions only.How it works
bot/agents.pyscans<repo>/skills/for immediate subdirectories containing aSKILL.mdSKILL.mdYAML frontmatterShellToolas aShellToolLocalSkilldict; the shared_shell_executorruns the resulting commands viacreate_subprocess_shellskills/is gitignored (except.gitignoreitself) so users can drop their own skill directories in without polluting the repoConfig example
No config changes required. Drop a skill into
./skills/:Test plan
uv run pytest tests/test_agents.py— 25 tests covering model selection, conversation state, history truncation, MCP config parsing, and_load_shell_skills(missing dir, single skill, multiple skills, dir without SKILL.md, MCP + skill coexistence)obsidian-cliskill and verify it can read/search/append notes🤖 Generated with Claude Code