Skip to content

feat(cli): skill invocation via /skill:name#2037

Merged
Mason Daugherty (mdrxy) merged 16 commits into
mainfrom
mdrxy/direct-skills
Mar 23, 2026
Merged

feat(cli): skill invocation via /skill:name#2037
Mason Daugherty (mdrxy) merged 16 commits into
mainfrom
mdrxy/direct-skills

Conversation

@mdrxy

@mdrxy Mason Daugherty (mdrxy) commented Mar 19, 2026

Copy link
Copy Markdown
Member

Closes #1357


TODO


Add /skill:<name> as a slash command so users can invoke skills directly from the chat input — type the command, and the CLI reads the skill's SKILL.md, wraps it in a prompt envelope with any user-provided arguments, and sends the composed message to the agent. Skill discovery happens at startup (and on /reload).

Changes

  • Resolved SKILL.md paths must live inside a known skill root, blocking symlink traversal. Users can extend the allowlist via DEEPAGENTS_EXTRA_SKILLS_DIRS env var or [skills].extra_allowed_dirs in config.toml
  • Add SkillMessage widget with a collapsible body (frontmatter stripped), preview/expand toggle via click or Ctrl+O, and full markdown rendering when expanded
  • Add ~/.claude/skills/ and {project}/.claude/skills/ as experimental skill discovery sources (highest precedence)
  • Refactor list_skills from repeated per-source try/except blocks into a single loop, adding "claude (experimental)" as a source literal
  • Skill metadata persisted in checkpoint via additional_kwargs.__skill, enabling thread-history reconstruction of skill invocations

@github-actions github-actions Bot added cli Related to `deepagents-cli` feature New feature/enhancement or request for one internal User is a member of the `langchain-ai` GitHub organization size: L 500-999 LOC labels Mar 19, 2026
corridor-security[bot]

This comment was marked as outdated.

@codspeed-hq

codspeed-hq Bot commented Mar 20, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 32 untouched benchmarks


Comparing mdrxy/direct-skills (402638f) with main (db67af0)

Open in CodSpeed

corridor-security[bot]

This comment was marked as resolved.

corridor-security[bot]

This comment was marked as resolved.

corridor-security[bot]

This comment was marked as resolved.

@github-actions github-actions Bot added size: XL 1000+ LOC and removed size: L 500-999 LOC labels Mar 20, 2026
@github-actions github-actions Bot added the p0 Critical priority / immediate response label Mar 20, 2026

@corridor-security corridor-security Bot left a comment

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.

Security Issues

  • Path Traversal / Arbitrary File Read via overly-permissive extra_skills_dirs
    The new extra skills containment allowlist (DEEPAGENTS_EXTRA_SKILLS_DIRS and [skills].extra_allowed_dirs) directly expands the set of roots considered "trusted" by load_skill_content(). If a user (or environment) sets this to a very broad directory (e.g., '/', the user's $HOME, or other high-level system roots), a malicious repository can place a symlinked SKILL.md inside a standard skills directory pointing to any sensitive file within that broad root. Because load_skill_content() resolves symlinks and only checks is_relative_to(allowed_root), using '/' (or similarly broad roots) makes the containment check ineffective, enabling arbitrary file reads and leakage to the LLM provider when the skill is invoked (e.g., /skill:). This is a realistic privilege/misconfiguration risk that can be exploited by a malicious project-level skill.

Recommendations

  • Disallow or warn on dangerous extra_skills_dirs values (e.g., '/', drive roots, or other extremely broad directories). Enforce a safe, bounded allowlist (e.g., require extra roots to be below a dedicated, trusted parent such as ~/.deepagents/extra_skills/).
  • Consider validating extra_skills_dirs at parse time and rejecting overly-broad paths; log a clear warning if ignored.
  • Optionally add an additional check in load_skill_content() that rejects resolved targets whose basename is not SKILL.md and/or enforces that the parent directory is one of the known skill roots (not just any descendant under an extra root).

dirs = [
Path(p.strip()).expanduser().resolve()
for p in env_raw.split(":")
if p.strip()

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.

Overly-permissive extra skill containment roots can nullify the symlink containment check, enabling arbitrary file reads when a malicious SKILL.md symlinks outside the standard skill dirs.

Problem:

  • The parser accepts environment/config-provided directories as-is and resolves them:
if env_raw:
    dirs = [
        Path(p.strip()).expanduser().resolve()
        for p in env_raw.split(":")
        if p.strip()
    ]
    return dirs or None
  • load_skill_content() then permits any resolved target under any of these roots:
if allowed_roots and not any(path.is_relative_to(root) for root in allowed_roots):
    return None

If DEEPAGENTS_EXTRA_SKILLS_DIRS (or config.toml [skills].extra_allowed_dirs) is set to a broad directory like '/' or the user's home dir, a project-level skill can include a symlinked SKILL.md pointing to a sensitive file (e.g., ~/.ssh/id_rsa). Because path.resolve() follows the symlink and '/' is an ancestor of all paths, the containment check passes and the file is read and sent to the LLM provider when the user runs /skill:..., resulting in sensitive data exposure.

Exploitation scenario:

  1. User has DEEPAGENTS_EXTRA_SKILLS_DIRS set to '/' (or $HOME).
  2. Attacker publishes a repo with .deepagents/skills/evil/SKILL.md -> symlink to ~/.ssh/id_rsa.
  3. User opens the repo in the CLI and runs /skill:evil (or uses autocomplete).
  4. load_skill_content() reads the resolved target and the contents are included in the prompt, leaking secrets.

Remediation:

  • Reject or warn on dangerous extra_skills_dirs values (e.g., '/', root drives) and require extra roots to be under a dedicated safe parent (e.g., ~/.deepagents/extra_skills/).
  • Add validation in _parse_extra_skills_dirs() to detect and drop overly-broad directories; log a clear warning to the user.
  • Optionally, strengthen load_skill_content() by asserting the parent directory of SKILL.md is itself a member of a strict root allowlist (not just any descendant) and that the basename is SKILL.md.

For more details, see the finding in Corridor.

Provide feedback: Reply with whether this is a valid vulnerability or false positive to help improve Corridor's accuracy.

@mdrxy Mason Daugherty (mdrxy) changed the title feat(cli): direct skill invocation via slash command feat(cli): skill invocation via /skill:name Mar 23, 2026
@mdrxy
Mason Daugherty (mdrxy) merged commit cc8cce7 into main Mar 23, 2026
39 checks passed
@mdrxy
Mason Daugherty (mdrxy) deleted the mdrxy/direct-skills branch March 23, 2026 05:54
Mason Daugherty (mdrxy) added a commit that referenced this pull request Apr 7, 2026
> [!CAUTION]
> Merging this PR will automatically publish to **PyPI** and create a
**GitHub release**.

For the full release process, see
[`.github/RELEASING.md`](https://github.com/langchain-ai/deepagents/blob/main/.github/RELEASING.md).

---

_Everything below this line will be the GitHub release body._

---


##
[0.0.35](deepagents-cli==0.0.34...deepagents-cli==0.0.35)
(2026-04-07)

### Highlights

* **Skills:** Invoke SDK skills directly from the CLI with `/skill:name`
or at startup via `--skill`. Skills are a composable extension point for
domain-specific agent behaviors.
* **Themes & configuration:** New theme system with color overrides,
global dotenv at `~/.deepagents/.env`, and a `DEEPAGENTS_CLI_` env var
prefix for conflict-free configuration.
* **Auto-updates:** Full update lifecycle — `/update` to upgrade
in-place, `/auto-update` to toggle background checks, and a refreshed
install script UX.
* **Headless workflows:** Agent-friendly UX for scripted/headless
invocations, AgentCore Code Interpreter sandbox provider, and improved
non-interactive tracing and guidance.
* **Performance:** Sub-250ms first paint via aggressive import deferral
(pydantic, adapters, heavy SDK modules), markdown stack prewarming, and
reduced health-poll intervals.

### Features

* Load `~/.deepagents/.env` as global dotenv
([#1909](#1909))
([5a21d0a](5a21d0a))
* Skill invocation via `/skill:name`
([#2037](#2037))
([cc8cce7](cc8cce7))
* `--skill` startup invocation
([#2477](#2477))
([5f0f1d4](5f0f1d4))
* Auto-update lifecycle, `/update` command, install script ux
([#2095](#2095))
([fd92f6e](fd92f6e))
* `/auto-update` to toggle auto-updates
([#2276](#2276))
([ad70bde](ad70bde))
* Themes
([#2134](#2134))
([db67af0](db67af0))
* Allow color overrides on built-in themes, default dark to false
([#2275](#2275))
([8f71865](8f71865))
* Add `DEEPAGENTS_CLI_` env var prefix and fix dotenv load order
([#2303](#2303))
([29647bb](29647bb))
* Add `ls_integration` metadata to langsmith traces
([#2272](#2272))
([5dd8098](5dd8098))
* Add animated spinner to non-interactive verbose mode
([#2001](#2001))
([153f465](153f465))
* Add async backend support to local context middleware
([#2118](#2118))
([a0d623c](a0d623c))
* Agent-friendly ux for scripted/headless workflows
([#2271](#2271))
([386438f](386438f))
* AgentCore Code Interpreter sandbox provider
([#2120](#2120))
([92556c7](92556c7))
* Context-aware connecting banner for resume and local server
([#2092](#2092))
([18b385b](18b385b))
* Default langsmith project to `'deepagents-cli'`
([#2277](#2277))
([7178b87](7178b87))
* Enhance tool-call UI, add `Ctrl+U` shortcut for chat input
([#1757](#1757))
([800c552](800c552))
* Persist token count in graph state across sessions
([#2323](#2323))
([5be352d](5be352d))
* Pop queued messages individually on `esc` instead of clearing all
([#2089](#2089))
([c76d855](c76d855))
* Render ask-user questions as markdown
([#2339](#2339))
([5fbb14a](5fbb14a))
* Show platform-specific ripgrep install command in missing-tool warning
([#1997](#1997))
([f000ce5](f000ce5))
* Support root/MDM installs
([#2346](#2346))
([f618acc](f618acc))
* Surface unsupported input modalities in system prompt
([#2327](#2327))
([95620e7](95620e7))

### Bug Fixes

* Align headless todo guidance with non-interactive mode
([#2459](#2459))
([281899b](281899b))
* Disable markup parsing for blocked-link notifications
([#2170](#2170))
([15867bf](15867bf))
* Dismiss slash command autocomplete on space
([#2478](#2478))
([02e46bc](02e46bc))
* Eliminate autocomplete popup flicker
([#2020](#2020))
([4b2db1e](4b2db1e))
* Eliminate trace fragmentation in non-interactive mode
([#2136](#2136))
([9bddc52](9bddc52))
* Enforce approval toggle when launched with `-y`
([#2278](#2278))
([28a32b7](28a32b7))
* Escape exception text in rich markup error output
([#2307](#2307))
([42bccca](42bccca))
* Escape markup in toast notifications
([#2139](#2139))
([90ccc28](90ccc28))
* Exit app on `ctrl+d` when thread list is empty
([#2270](#2270))
([e859077](e859077))
* Guard against textual cursor/document desync crash
([#2494](#2494))
([c14a748](c14a748))
* Human-readable duration and consistent dim styling on teardown screen
([#1995](#1995))
([901a0a4](901a0a4))
* Mark token count as approximate after interrupted generation
([#2353](#2353))
([cb9a0c7](cb9a0c7))
* Resolve misleading "missing package" error when provider import fails
([#1960](#1960))
([b90fbad](b90fbad))
* Open trace in browser immediately when busy
([#2305](#2305))
([b452032](b452032))
* Patch model identity in system prompt on `/model` swap
([#2024](#2024))
([36aecbf](36aecbf))
* Harden MCP pre-flight health checks
([#2019](#2019))
([2b27055](2b27055))
* Pre-flight health checks for MCP servers
([#2008](#2008))
([30d60e3](30d60e3))
* Prevent premature thinking state with parallel subtasks
([#1858](#1858))
([189104c](189104c))
* Prevent session stats loss on mid-turn exit
([#2238](#2238))
([b1807aa](b1807aa))
* Rebind toggle tool output to `ctrl+o` to unblock `cmd+right`
([#2088](#2088))
([b486fe5](b486fe5))
* Remove duplicate server failure notification
([#2141](#2141))
([c1cfe72](c1cfe72))
* Remove keybinding overrides that shadow textual built-ins
([#2084](#2084))
([08fc5d0](08fc5d0))
* Resolve conflicting langsmith env var precedence
([#2455](#2455))
([b6997d8](b6997d8))
* Show server startup error instead of generic agent message
([#2397](#2397))
([a3e1e93](a3e1e93))
* Certain slash commands should not require server connection
([#1974](#1974))
([32bd814](32bd814))
* Sort MCP tools deterministically for prompt-cache stability
([#2497](#2497))
([39b43cf](39b43cf))
* Squash loading widget timer leak
([#2396](#2396))
([01d3d86](01d3d86))
* Support pre-release versions in update checker
([#2164](#2164))
([e18e9dc](e18e9dc))
* Surface clear error for missing sandbox provider deps
([#1999](#1999))
([939f56a](939f56a))
* Use relative paths in langgraph config for Windows compat
([#2244](#2244))
([d10dfbd](d10dfbd))
* Warn agent that local filesystem is inaccessible in sandbox mode
([#2274](#2274))
([a3b61e5](a3b61e5))
* Wire `enable_ask_user` flag to remove tool in non-interactive mode
([#2105](#2105))
([2399747](2399747))

### Performance Improvements

* Sub 250ms first paint
([#2027](#2027))
([e42e05c](e42e05c))
* Defer `/model` selector data loading off event loop
([#2259](#2259))
([a32ce7f](a32ce7f))
* Defer heavy imports from startup path
([#2022](#2022))
([b7f5a99](b7f5a99))
* Defer pydantic and adapter imports out of startup hot path
([#2269](#2269))
([0a410b4](0a410b4))
* Prewarm markdown stack and cache skill body render
([#2236](#2236))
([0a3ba47](0a3ba47))
* Reduce health poll interval for local langgraph dev server
([#2283](#2283))
([7f5c3de](7f5c3de))

---

_Everything above this line will be the GitHub release body._

---

> [!NOTE]
> A **New Contributors** section is appended to the GitHub release notes
automatically at publish time (see [Release
Pipeline](https://github.com/langchain-ai/deepagents/blob/main/.github/RELEASING.md#release-pipeline),
step 2).

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Mason Daugherty <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cli Related to `deepagents-cli` feature New feature/enhancement or request for one internal User is a member of the `langchain-ai` GitHub organization p0 Critical priority / immediate response size: XL 1000+ LOC

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Direct skill invocation via slash command

1 participant