Skip to contents

Language: English | 简体中文

What are skills?

Skills are reusable prompt templates stored as <name>/SKILL.md. A user can type /name arguments to load one directly. The model can also semantically match the names and descriptions in its system hint and call the use_skill tool, which loads the full body only when needed.

Local slash commands take precedence over skills with the same name. In particular, /compact [instructions] is handled locally by the REPL or Shiny server and invokes the compaction controller; it is not sent as a skill prompt. The package also ships a compact/SKILL.md for semantic tool invocation.

Skills shipped by codeagent

The installed package currently contains these 17 skill directories:

Skill Description
/plan Produce analysis and a step-by-step implementation plan without editing files
/verify Verify the previous action for correctness and completeness
/simplify Review and simplify recent code or output
/compact Request a structured conversation summary; direct /compact syntax is the local command described above
/remember Save durable information to cross-session memory
/loop Interpret a periodic task request such as /loop 5m /verify
/document Run package documentation workflow, including devtools::document()
/roxygen Generate a roxygen2 documentation skeleton
/testthat Create testthat unit tests
/style Format and lint R code consistently
/lint Lint and style R code with lintr and styler
/news Update NEWS.md for a release
/pkgdown Build or update a pkgdown site, reference index, and vignette articles
/explore Explore and analyze a data frame in natural language
/report Export an exploration session to a Quarto document
/no-secrets Guard against printing or committing secrets and concrete infrastructure identifiers
/posit-dev-packages Update the project’s pinned core development packages and report versions

The live list may be larger because btw, installed packages (including Shiny), and user/project directories contribute skills. Inspect it with list_skills_meta() or open the slash-command typeahead by typing / in the chat.

Using skills from the chat

# In the Shiny app or REPL:
/plan add a new summarise_by_group() function
/roxygen summarise_by_group
/testthat summarise_by_group

An unknown /name is parsed as a skill request, but if loading fails the REPL and Shiny paths keep the original slash text and send it as an ordinary prompt. A direct programmatic load_skill_prompt() call instead raises “Skill not found” and lists the currently available names.

Creating custom skills

Use a directory, not a flat Markdown file. These user and project locations are supported:

# User-global (btw native):
~/.btw/skills/my-skill/SKILL.md
~/.config/btw/skills/my-skill/SKILL.md

# Project-local:
.btw/skills/my-skill/SKILL.md          # btw native
.agents/skills/my-skill/SKILL.md       # btw agents dir
.claude/skills/my-skill/SKILL.md       # Claude Code compatibility
.codex/skills/my-skill/SKILL.md        # Codex compatibility

btw also contributes its built-ins and skills from packages it discovers. codeagent supplements those results with the installed codeagent skills, installed Shiny package skills, and the four project-local compatibility paths above. For custom skills, prefer ~/.btw/skills globally and .btw/skills inside a project.

SKILL.md format:

---
name: my-skill
description: Short description shown in skill picker
metadata:
  argument-hint: "<what to type after /my-skill>"
allowed-tools:
  - Read
  - Bash
---

Skill body — instructions for the agent.

Use $ARGUMENTS to insert the user-supplied arguments.

name and description are the key discovery fields. Current btw-compatible skills place argument-hint under metadata; codeagent reparses the file so the hint remains available even when the backend omits non-core frontmatter. allowed-tools is retained as skill metadata and does not bypass the central permission gate.

In the body, $ARGUMENTS expands to the complete argument string. Available $ARG1, $ARG2, and later placeholders expand from whitespace-separated tokens.

Architecture and flow

codeagent uses btw for primary discovery/loading, adds compatibility paths, and uses progressive disclosure: metadata enters the system prompt, while the body is loaded on demand.

                    User types /name args
                            |
                            v
                   .preprocess_input()
        +-------------------+--------------------+
 recognized local command                 otherwise -> skill request
 (for example /compact)                         |
        |                                       v
 handled by REPL/Shiny                load_skill_prompt(name, args, cwd)
 (not sent as a skill prompt)                    ^
                                                 | use_skill tool call
 System prompt <- build_skill_hint()             |
 <available_skills> = name, description, hint    |
        |                                         |
        v                                         |
      model -- semantic match --> use_skill ------+  .make_skill_tool()
                                                 |
                                                 v
             btw:::find_skill() + frontmatter body when available
             otherwise read the discovered path and strip frontmatter
                                                 |
                                                 v
                       substitute $ARGUMENTS and $ARG1 ...
                                                 |
                                                 v
                       full body injected for the agent to follow

 Discovery and two-level metadata cache: list_skills_meta(cwd)

   in-memory .skill_cache, keyed by canonical cwd
        | miss or signature mismatch
        v
   on-disk <codeagent-config>/cache/skills/<cwd-key>.rds
        | miss, corruption, or signature mismatch
        v
   btw:::btw_skills_list()
     + btw built-ins, package, user, and native project directories
     + installed codeagent and Shiny package skills
     + cwd/.btw, .agents, .claude, and .codex skill directories
        |
        v
   named SkillMeta list -> best-effort atomic disk write + memory cache

The signature is the sum, across discovered directories, of each directory’s recursive SKILL.md count plus file modification times. This detects ordinary add/remove/edit changes. Cache I/O is best effort: an absent, corrupt, or unwritable cache falls back to discovery rather than breaking skill listing.

Public signatures and defaults

list_skills_meta(cwd = getwd())

load_skill_prompt(name, args = "", cwd = getwd())

build_skill_hint(cwd = getwd(), max_tokens = 1000L)

install_ds_skills(
  skill = NULL,
  scope = c("user", "project"),
  overwrite = FALSE
)

build_skill_hint() truncates its generated metadata block to approximately max_tokens * 4 characters. install_ds_skills() installs a curated Posit R/data-science set when skill = NULL, every upstream skill for "all", or the specified names; its default scope is user-global.

Skill discovery

# List all available skills
list_skills_meta()

# Load a skill prompt programmatically
load_skill_prompt("plan", args = "add feature X", cwd = getwd())