| Title: | A Toolkit for Connecting R and Large Language Models |
|---|---|
| Description: | A complete toolkit for connecting 'R' environments with Large Language Models (LLMs). Provides utilities for describing 'R' objects, package documentation, and workspace state in plain text formats optimized for LLM consumption. Supports multiple workflows: interactive copy-paste to external chat interfaces, programmatic tool registration with 'ellmer' chat clients, batteries-included chat applications via 'shinychat', and exposure to external coding agents through the Model Context Protocol. Project configuration files enable stable, repeatable conversations with project-specific context and preferred LLM settings. |
| Authors: | Garrick Aden-Buie [aut, cre] (ORCID: <https://orcid.org/0000-0002-7111-0077>), Simon Couch [aut] (ORCID: <https://orcid.org/0000-0001-5676-5107>), Joe Cheng [aut], Posit Software, PBC [cph, fnd], Google [cph] (Material Design Icons), Microsoft [cph] (@vscode/codicons), Jamie Perkins [cph] (countUp.js author) |
| Maintainer: | Garrick Aden-Buie <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 1.2.1.9000 |
| Built: | 2026-05-16 09:33:21 UTC |
| Source: | https://github.com/posit-dev/btw |
This function allows you to quickly describe your computational environment to a model by concatenating plain-text descriptions of "R stuff", from data frames to packages to function documentation.
There are two key ways to use btw():
Use it interactively at the console to gather information about your
environment into prompt text that you can paste into the chat interface of
an LLM, like ChatGPT or Claude. By default, btw() copies the prompt to
the clipboard for you.
btw(vignette("colwise", "dplyr"), dplyr::across, dplyr::starwars)
#> btw copied to the clipboard!
Pair btw() with ellmer::Chat during a chat session to create a prompt
that includes additional context drawn from your environment and help
pages.
library(ellmer)
chat <- chat_anthropic() # requires an Anthropic API key
chat <- chat_ollama(model = "llama3.1:8b") # requires ollama and a local model
chat$chat(btw(
vignette("colwise", "dplyr"),
dplyr::across,
dplyr::starwars,
"Create a few interesting examples that use `dplyr::across()`",
"with the `starwars` data set."
))
Use btw() without arguments to describe all objects in your workspace:
btw() #> btw copied to the clipboard!
Describe a function (it's documentation) and a data frame:
btw(dplyr::mutate, mtcars) #> btw copied to the clipboard!
Use btw() to give additional context to an ellmer::Chat session:
library(ellmer) chat <- chat_ollama(model = "llama3.1:8b") chat$chat( btw(mtcars, "Are there cars with 8 cylinders in this dataset?") )
btw(..., clipboard = TRUE)btw(..., clipboard = TRUE)
... |
Objects to describe from your R environment. You can pass objects
themselves, like data frames or functions, or the function also accepts
output from |
clipboard |
Whether to write the results to the clipboard.
A single logical value; will default to |
Returns an ellmer::ContentText object with the collected prompt. If
clipboard = TRUE, the prompt text is copied to the clipboard when the
returned object is printed for the first time (e.g. calling btw() without
assignment).
# See documentation for detailed examples btw(mtcars)# See documentation for detailed examples btw(mtcars)
Creates an ellmer::tool() from a markdown file that defines a custom agent.
The tool can be registered with a chat client to delegate tasks to a
specialized assistant with its own system prompt and tool configuration.
Agent files use YAML frontmatter to configure the agent, with the markdown
body becoming the agent's system prompt. The file should be named
agent-{name}.md.
name: A valid R identifier (letters, numbers, underscores) that becomes
part of the tool name: btw_tool_agent_{name}. The final name cannot
conflict with any existing btw_tools() names.
description: Tool description shown to the LLM. Defaults to a generic
delegation message.
title: User-facing title for the tool. Defaults to title-cased name.
icon: Icon specification for the agent (see Icon Specification
below). Defaults to the standard agent icon.
client: Model specification like "anthropic/claude-sonnet-4-20250514".
Falls back to btw.subagent.client or btw.client options.
tools: List of tool names or groups available to this agent. Defaults to
all non-agent tools.
The icon field supports three formats:
Plain icon name: Uses shiny::icon() (Font Awesome icons). Example:
icon: robot or icon: code
Raw SVG: Starts with <svg and is used literally. Example:
icon: '<svg viewBox="0 0 24 24">...</svg>'
Package-prefixed icon: Uses pkg::icon-name format to specify icons
from other icon packages. Supported packages:
| Package | Syntax | Function Called |
| fontawesome | fontawesome::home |
fontawesome::fa() |
| bsicons | bsicons::house |
bsicons::bs_icon() |
| phosphoricons | phosphoricons::house |
phosphoricons::ph() |
| rheroicons | rheroicons::home |
rheroicons::rheroicon() |
| tabler | tabler::home |
tabler::icon() |
| shiny | shiny::home |
shiny::icon()
|
The specified package must be installed. If the package is missing or the icon name is invalid, a warning is issued and the default agent icon is used.
--- name: code_reviewer description: Reviews code for best practices and potential issues. title: Code Reviewer icon: magnifying-glass tools: - files - docs --- You are a code reviewer. Analyze code for: - Best practices and style - Potential bugs or issues - Performance considerations Provide specific, actionable feedback.
Agent files are automatically discovered by btw_tools() when placed in
the following locations (in order of priority):
Project level (btw): .btw/agent-*.md in your project directory
User level (btw): ~/.btw/agent-*.md or ~/.config/btw/agent-*.md
Project level (Claude Code): .claude/agents/*.md in your project directory
User level (Claude Code): ~/.claude/agents/*.md
btw-style agents take precedence over Claude Code agents with the same name. When duplicate agent names are found, a warning is issued.
btw supports loading agent files from Claude Code's .claude/agents/
directory for compatibility. However, there are some small differences
when Claude Code agents are used in btw:
Name normalization: Agent names with hyphens (e.g., code-reviewer)
are automatically converted to underscores (code_reviewer) for R
compatibility.
Ignored fields: The following Claude Code fields are ignored (with
a warning): model, tools, permissionMode, skills. Use btw's
client field instead of model, and btw agents use default tools.
client argument: Use the client argument to manually override
the model for any agent file.
btw_agent_tool(path, client = NULL)btw_agent_tool(path, client = NULL)
path |
Path to an agent markdown file. |
client |
Optional. A client specification to override the agent's
configured client. Can be a string like
|
An ellmer::ToolDef object that can be registered with a chat
client, or NULL if the file is invalid (with a warning).
btw_tools() for automatic agent discovery, btw_client() for
creating chat clients with tools.
# Create a btw-style agent file withr::with_tempdir({ dir.create(".btw") writeLines( c( "---", "name: code_reviewer", "description: Reviews code for best practices.", "---", "", "You are a code reviewer. Analyze code for best practices." ), ".btw/agent-code_reviewer.md" ) tool <- btw_agent_tool(".btw/agent-code_reviewer.md") # Use `chat$register_tool(tool)` to register with an ellmer chat client tool }) # Create a Claude Code-style agent file (name with hyphens) withr::with_tempdir({ dir.create(".claude/agents", recursive = TRUE) writeLines( c( "---", "name: test-helper", "description: Helps write tests.", "model: sonnet", "---", "", "You help write tests for R code." ), ".claude/agents/test-helper.md" ) tool <- btw_agent_tool(".claude/agents/test-helper.md") # Use `chat$register_tool(tool)` to register with an ellmer chat client tool })# Create a btw-style agent file withr::with_tempdir({ dir.create(".btw") writeLines( c( "---", "name: code_reviewer", "description: Reviews code for best practices.", "---", "", "You are a code reviewer. Analyze code for best practices." ), ".btw/agent-code_reviewer.md" ) tool <- btw_agent_tool(".btw/agent-code_reviewer.md") # Use `chat$register_tool(tool)` to register with an ellmer chat client tool }) # Create a Claude Code-style agent file (name with hyphens) withr::with_tempdir({ dir.create(".claude/agents", recursive = TRUE) writeLines( c( "---", "name: test-helper", "description: Helps write tests.", "model: sonnet", "---", "", "You help write tests for R code." ), ".claude/agents/test-helper.md" ) tool <- btw_agent_tool(".claude/agents/test-helper.md") # Use `chat$register_tool(tool)` to register with an ellmer chat client tool })
Creates an ellmer::Chat client, enhanced with the tools from
btw_tools(). Use btw_client() to create the chat client for
general or interactive use at the console, or btw_app() to create a chat
client and launch a Shiny app for chatting with a btw-enhanced LLM in your
local workspace.
You can keep track of project-specific rules, guidance and context by adding
a btw.md file, AGENTS.md, or CLAUDE.md in your
project directory. See use_btw_md() for help creating a btw.md file in
your project, or use path_btw to tell btw_client() to use a specific
context file. Note that CLAUDE.md files will have their YAML frontmatter
stripped but not used for configuration.
btw_client() will also include context from an llms.txt file in the
system prompt, if one is found in your project directory or as specified by
the path_llms_txt argument.
Client settings in client and tools from a project-level btw.md or
AGENTS.md file take precedence. If a project file doesn't specify a
setting, btw will fall back to settings in a user-level btw.md file
(typically in ~/btw.md or ~/.config/btw/btw.md). Project-level btw tool
options under the options key are merged with user-level options, with
project-level options taking precedence.
Project-specific instructions from both files are combined with a divider, allowing you to maintain global guidelines in your user file and project-specific rules in your project file.
The following R options are consulted when creating a new btw chat client and
take precedence over settings in a btw.md file:
btw.client: The ellmer::Chat client or a provider/model string (see
ellmer::chat()) to use as the basis for new btw_client() or
btw_app() chats.
btw.tools: The btw tools to include by default when starting a new
btw chat, see btw_tools() for details.'
You can configure multiple client options in your btw.md file. When
btw_client() is called interactively from the console, you'll be presented
with a menu to choose which client to use. In non-interactive contexts, the
first client is used automatically.
Array format (unnamed list):
client: - anthropic/claude-sonnet-4 - openai/gpt-4.1 - aws_bedrock/us.anthropic.claude-sonnet-4-20250514-v1:0
Alias format (named list):
client:
haiku: aws_bedrock/us.anthropic.claude-haiku-4-5-20251001-v1:0
sonnet:
provider: aws_bedrock
model: us.anthropic.claude-sonnet-4-5-20250929-v1:0
With aliases, you can select a client by name in the interactive menu or pass
the alias directly: btw_client(client = "sonnet").
btw_client( ..., client = NULL, tools = NULL, path_btw = NULL, path_llms_txt = NULL ) btw_app(..., client = NULL, tools = NULL, path_btw = NULL, messages = list())btw_client( ..., client = NULL, tools = NULL, path_btw = NULL, path_llms_txt = NULL ) btw_app(..., client = NULL, tools = NULL, path_btw = NULL, messages = list())
... |
In |
client |
An ellmer::Chat client, or a |
tools |
A list of tools to include in the chat, defaults to
|
path_btw |
A path to a |
path_llms_txt |
A path to an |
messages |
A list of initial messages to show in the chat, passed to
|
Returns an ellmer::Chat object with additional tools registered
from btw_tools(). btw_app() returns the chat object invisibly, and
the chat object with the messages added during the chat session.
btw_client(): Create a btw-enhanced ellmer::Chat client
btw_app(): Create a btw-enhanced client and launch a Shiny app to
chat
withr::local_options(list( btw.client = ellmer::chat_ollama(model="llama3.1:8b") )) chat <- btw_client() chat$chat( "How can I replace `stop()` calls with functions from the cli package?" )withr::local_options(list( btw.client = ellmer::chat_ollama(model="llama3.1:8b") )) chat <- btw_client() chat$chat( "How can I replace `stop()` calls with functions from the cli package?" )
Download and install a skill from a GitHub repository. The repository
should contain one or more skill directories, each with a SKILL.md file.
btw_skill_install_github( repo, skill = NULL, scope = "project", overwrite = NULL )btw_skill_install_github( repo, skill = NULL, scope = "project", overwrite = NULL )
repo |
GitHub repository in |
skill |
Optional skill name. If |
scope |
Where to install the skill. One of:
|
overwrite |
Whether to overwrite an existing skill with the same name.
If |
The path to the installed skill directory, invisibly.
Other skills:
btw_skill_install_package(),
btw_skill_install_project(),
btw_tool_skill()
Install a skill bundled in an R package. Packages can bundle skills in
their inst/skills/ directory, where each subdirectory containing a
SKILL.md file is a skill.
Note that if a package is attached with library(), its skills are
automatically available without installation — btw discovers skills
from all attached packages at runtime. Use this function when you want to
permanently copy a skill to your project or user directory so it remains
available regardless of which packages are loaded.
btw_skill_install_package( package, skill = NULL, scope = "project", overwrite = NULL )btw_skill_install_package( package, skill = NULL, scope = "project", overwrite = NULL )
package |
Name of an installed R package that bundles skills. |
skill |
Optional skill name. If |
scope |
Where to install the skill. One of:
|
overwrite |
Whether to overwrite an existing skill with the same name.
If |
The path to the installed skill directory, invisibly.
Other skills:
btw_skill_install_github(),
btw_skill_install_project(),
btw_tool_skill()
Discovers R packages that are dependencies of the current project and
installs skills from any that bundle them in inst/skills/. If a
DESCRIPTION file exists in the working directory, packages are read from
its Imports and Suggests fields. Otherwise, renv::dependencies() is
used as a fallback (requires the renv package).
Packages without skills are silently skipped. If no dependencies bundle skills, a message is printed and nothing is installed.
btw_skill_install_project(path = ".", scope = "project", overwrite = NULL)btw_skill_install_project(path = ".", scope = "project", overwrite = NULL)
path |
Path to the project directory. Defaults to the current working directory. |
scope |
Where to install the skills. See |
overwrite |
Whether to overwrite existing skills. See
|
The paths to all installed skill directories, invisibly.
Other skills:
btw_skill_install_github(),
btw_skill_install_package(),
btw_tool_skill()
Runs a btw task defined in a file with YAML frontmatter configuration and
a markdown body containing the task prompt. The task file format is similar
to btw.md files, with client and tool configuration in the frontmatter and
the task instructions in the body.
Task files use the same format as btw.md files:
---
client:
provider: anthropic
model: claude-sonnet-4
tools: [docs, files]
---
Your task prompt here with {{ variable }} interpolation...
The task prompt body supports template variable interpolation using
{{ variable }} syntax via ellmer::interpolate(). Pass named arguments
to provide values for template variables:
btw_task("my-task.md", package_name = "dplyr", version = "1.1.0")
Unnamed arguments are treated as additional context and converted to text
using btw(). This context is appended to the system prompt:
btw_task("analyze.md", dataset_name = "mtcars", mtcars, my_function)
# ^-- template var ^-- additional context
btw_task( path, ..., client = NULL, mode = c("app", "console", "client", "tool") )btw_task( path, ..., client = NULL, mode = c("app", "console", "client", "tool") )
path |
Path to the task file containing YAML configuration and prompt. |
... |
Named arguments become template variables for interpolation in the
task prompt. Unnamed arguments are treated as additional context objects
and converted to text via |
client |
An ellmer::Chat client to override the task file's client
configuration. If |
mode |
The execution mode for the task:
|
Depending on mode:
"app": Returns the chat client invisibly after launching the app
"console": Returns the chat client after console interaction
"client": Returns the configured chat client
"tool": Returns an ellmer::tool() object
Other task and agent functions:
btw_task_create_btw_md(),
btw_task_create_readme(),
btw_task_create_skill()
# Create a simple task file tmp_task_file <- tempfile(fileext = ".md") cat(file = tmp_task_file, '--- client: anthropic/claude-sonnet-4-6 tools: [docs, files] --- Analyze the {{ package_name }} package and create a summary. ') # Task with template interpolation btw_task(tmp_task_file, package_name = "dplyr", mode = "tool") # Include additional context btw_task( tmp_task_file, package_name = "ggplot2", mtcars, # Additional context mode = "tool" )# Create a simple task file tmp_task_file <- tempfile(fileext = ".md") cat(file = tmp_task_file, '--- client: anthropic/claude-sonnet-4-6 tools: [docs, files] --- Analyze the {{ package_name }} package and create a summary. ') # Task with template interpolation btw_task(tmp_task_file, package_name = "dplyr", mode = "tool") # Include additional context btw_task( tmp_task_file, package_name = "ggplot2", mtcars, # Additional context mode = "tool" )
Create a comprehensive context btw.md or AGENTS.md file for your project.
If launched in app or console mode, this task will start an interactive chat
session to guide you through the process of creating a context file.
This task focuses on documenting project context for developers and agents.
See btw_client() for additional details about the format and usage of the
btw.md context file, including choosing the default LLM provider and model
or the default set of tools to use with btw_client().
btw_task_create_btw_md( ..., path = "btw.md", client = NULL, mode = c("app", "console", "client", "tool") )btw_task_create_btw_md( ..., path = "btw.md", client = NULL, mode = c("app", "console", "client", "tool") )
... |
Additional context to provide to the AI. This can be any text or
R objects that can be converted to text using |
path |
The path to the context file to create. Defaults to |
client |
An ellmer::Chat client, or a |
mode |
The mode to run the task in, which affects what is returned from
this function. |
When mode is "app" or "console", this function launches an
interactive session in the browser or the R console, respectively. The
ellmer chat object with the conversation history is returned invisibly
when the session ends.
When mode is "client", this function returns the configured ellmer
chat client object. When mode is "tool", this function returns an
ellmer tool object that can be used in other chat instances.
Other task and agent functions:
btw_task(),
btw_task_create_readme(),
btw_task_create_skill()
withr::with_envvar(list(ANTHROPIC_API_KEY = "example"), { btw_task_create_btw_md(mode = "tool", client = "anthropic") })withr::with_envvar(list(ANTHROPIC_API_KEY = "example"), { btw_task_create_btw_md(mode = "tool", client = "anthropic") })
Create a compelling, user-focused README file for your project. If launched in app or console mode, this task will start an interactive chat session to guide you through the process of creating a polished README that clearly communicates value and helps potential users make informed decisions.
This task focuses on creating READMEs for END USERS, not developers, with emphasis on clarity, accessibility, and authentic communication of value. The process involves exploring your project files, understanding your target audience and goals, proposing a structure, and then iteratively drafting each section with your input.
btw_task_create_readme( ..., client = NULL, mode = c("app", "console", "client", "tool") )btw_task_create_readme( ..., client = NULL, mode = c("app", "console", "client", "tool") )
... |
Additional context to provide to the AI. This can be any text or
R objects that can be converted to text using |
client |
An ellmer::Chat client, or a |
mode |
The mode to run the task in, which affects what is returned from
this function. |
When mode is "app" or "console", this function launches an
interactive session in the browser or the R console, respectively. The
ellmer chat object with the conversation history is returned invisibly
when the session ends.
When mode is "client", this function returns the configured ellmer
chat client object. When mode is "tool", this function returns an
ellmer tool object that can be used in other chat instances.
Other task and agent functions:
btw_task(),
btw_task_create_btw_md(),
btw_task_create_skill()
withr::with_envvar(list(ANTHROPIC_API_KEY = "example"), { btw_task_create_readme(mode = "tool", client = "anthropic") })withr::with_envvar(list(ANTHROPIC_API_KEY = "example"), { btw_task_create_readme(mode = "tool", client = "anthropic") })
Create a new skill for your project using interactive guidance. If launched in app or console mode, this task will start an interactive chat session to guide you through the process of creating a skill that extends Claude's capabilities with specialized knowledge, workflows, or tool integrations.
btw_task_create_skill( ..., name = NULL, client = NULL, mode = c("app", "console", "client", "tool"), tools = "docs" )btw_task_create_skill( ..., name = NULL, client = NULL, mode = c("app", "console", "client", "tool"), tools = "docs" )
... |
Additional context to provide to the AI. This can be any text or
R objects that can be converted to text using |
name |
Optional skill name. If provided, the AI will skip the naming step and use this name directly. |
client |
An ellmer::Chat client, or a |
mode |
The mode to run the task in, which affects what is returned from
this function. |
tools |
Optional list or character vector of tools to allow the task to use when creating the skill. By default documentation tools are included to allow the task to help create package-based skills. You can include additional tools as needed. Because the task requires file tools to create skills with resources, tools for listing, reading and writing files are always included. |
When mode is "app" or "console", this function launches an
interactive session in the browser or the R console, respectively. The
ellmer chat object with the conversation history is returned invisibly
when the session ends.
When mode is "client", this function returns the configured ellmer
chat client object. When mode is "tool", this function returns an
ellmer tool object that can be used in other chat instances.
Other task and agent functions:
btw_task(),
btw_task_create_btw_md(),
btw_task_create_readme()
withr::with_envvar(list(ANTHROPIC_API_KEY = "example"), { btw_task_create_skill(mode = "tool", client = "anthropic") })withr::with_envvar(list(ANTHROPIC_API_KEY = "example"), { btw_task_create_skill(mode = "tool", client = "anthropic") })
A generic function used to describe an object for use by LLM.
btw_this(x, ...)btw_this(x, ...)
x |
The thing to describe. |
... |
Additional arguments passed down to underlying methods. Unused arguments are silently ignored. |
A character vector of lines describing the object.
Other btw formatting methods:
btw_this.character(),
btw_this.data.frame(),
btw_this.environment()
btw_this(mtcars) # describe the mtcars dataset btw_this(dplyr::mutate) # include function sourcebtw_this(mtcars) # describe the mtcars dataset btw_this(dplyr::mutate) # include function source
Character strings in btw_this() are used as shortcuts to many underlying
methods. btw_this() detects specific formats in the input string to
determine which method to call, or by default it will try to evaluate the
character string as R code and return the appropriate object description.
btw_this() knows about the following special character string formats:
"./path"
Any string starting with ./ is treated as a relative path.
If the path is a file, we call btw_tool_files_read() and if the path
is a directory we call btw_tool_files_list() on the path.
btw_this("./data") lists the files in data/.
btw_this("./R/load_data.R") reads the source of the R/load_data.R
file.
"{pkgName}" or "@pkg pkgName"
A package name wrapped in braces, or using the @pkg command. Returns the
list of help topics (btw_tool_docs_package_help_topics()) and, if it
exists, the introductory vignette for the package (btw_tool_docs_vignette()).
btw_this("{dplyr}") or btw_this("@pkg dplyr") includes dplyr's introductory vignette.
btw_this("{btw}") returns only the package help index (because btw
doesn't have an intro vignette, yet).
"?help_topic" or "@help topic"
When the string starts with ? or @help, btw searches R's help
topics using btw_tool_docs_help_page(). Supports multiple formats:
btw_this("?dplyr::across") or btw_this("@help dplyr::across")
btw_this("@help dplyr across") - space-separated format
btw_this("@help across") - searches all packages
"@news {{package_name}} {{search_term}}"
Include the release notes (NEWS) from the latest package release, e.g.
"@news dplyr", or that match a search term, e.g. "@news dplyr join_by".
"@url {{url}}"
Include the contents of a web page at the specified URL as markdown, e.g.
"@url https://cran.r-project.org/doc/FAQ/R-FAQ.html". Requires the
chromote package to be installed.
"@git status", "@git diff", "@git log"
Git commands for viewing repository status, diffs, and commit history.
Requires gert package and a git repository.
btw_this("@git status") - show working directory status
btw_this("@git status staged") - show only staged files
btw_this("@git diff") - show unstaged changes
btw_this("@git diff HEAD") - show staged changes
btw_this("@git log") - show recent commits (default 10)
btw_this("@git log main 20") - show 20 commits from main branch
"@issue #number" or "@pr #number"
Fetch a GitHub issue or pull request. Automatically detects the current
repository, or you can specify owner/repo#number or owner/repo number.
Requires gh package and GitHub authentication.
btw_this("@issue #65") - issue from current repo
btw_this("@pr posit-dev/btw#64") - PR from specific repo
btw_this("@issue tidyverse/dplyr 1234") - space-separated format
"@current_file" or "@current_selection"
When used in RStudio or Positron, or anywhere else that the
rstudioapi is supported, btw("@current_file") includes the contents
of the file currently open in the editor using
rstudioapi::getSourceEditorContext().
"@clipboard"
Includes the contents currently stored in your clipboard.
"@platform_info"
Includes information about the current platform, such as the R version,
operating system, IDE or UI being used, as well as language, locale,
timezone and current date.
"@attached_packages", "@loaded_packages", "@installed_packages"
Includes information about the attached, loaded, or installed packages in
your R session, using sessioninfo::package_info().
"@last_error"
Includes the message from the last error that occurred in your session.
To reliably capture the last error, you need to enable
rlang::global_entrace() in your session.
"@last_value"
Includes the .Last.value, i.e. the result of the last expression
evaluated in your R console.
## S3 method for class 'character' btw_this(x, ..., caller_env = parent.frame())## S3 method for class 'character' btw_this(x, ..., caller_env = parent.frame())
x |
A character string |
... |
Ignored. |
caller_env |
The caller environment. |
A character vector of lines describing the object.
Other btw formatting methods:
btw_this(),
btw_this.data.frame(),
btw_this.environment()
mtcars[1:3, 1:4] cat(btw_this("@last_value"))mtcars[1:3, 1:4] cat(btw_this("@last_value"))
Describe a data frame in plain text
## S3 method for class 'data.frame' btw_this( x, ..., format = c("skim", "glimpse", "print", "json"), max_rows = 5, max_cols = 100, package = NULL ) ## S3 method for class 'tbl' btw_this( x, ..., format = c("skim", "glimpse", "print", "json"), max_rows = 5, max_cols = 100, package = NULL )## S3 method for class 'data.frame' btw_this( x, ..., format = c("skim", "glimpse", "print", "json"), max_rows = 5, max_cols = 100, package = NULL ) ## S3 method for class 'tbl' btw_this( x, ..., format = c("skim", "glimpse", "print", "json"), max_rows = 5, max_cols = 100, package = NULL )
x |
A data frame or tibble. |
... |
Additional arguments are silently ignored. |
format |
One of
|
max_rows |
The maximum number of rows to show in the data frame. Only
applies when |
max_cols |
The maximum number of columns to show in the data frame. Only
applies when |
package |
The name of the package that provides the data set. If not
provided, |
A character vector containing a representation of the data frame. Will error if the named data frame is not found in the environment.
btw_this(data.frame): Summarize a data frame.
btw_this(tbl): Summarize a tbl.
btw_tool_env_describe_data_frame()
Other btw formatting methods:
btw_this(),
btw_this.character(),
btw_this.environment()
btw_this(mtcars) btw_this(mtcars, format = "print") btw_this(mtcars, format = "json")btw_this(mtcars) btw_this(mtcars, format = "print") btw_this(mtcars, format = "json")
Describe the contents of an environment
## S3 method for class 'environment' btw_this(x, ..., items = NULL)## S3 method for class 'environment' btw_this(x, ..., items = NULL)
x |
An environment. |
... |
Additional arguments are silently ignored. |
items |
Optional. A character vector of objects in the environment to describe. |
A string describing the environment contents with #> prefixing
each object's printed representation.
btw_tool_env_describe_environment()
Other btw formatting methods:
btw_this(),
btw_this.character(),
btw_this.data.frame()
env <- new.env() env$cyl_6 <- mtcars[mtcars$cyl == 6, ] env$gear_5 <- mtcars[mtcars$gear == 5, ] btw_this(env)env <- new.env() env$cyl_6 <- mtcars[mtcars$cyl == 6, ] env$gear_5 <- mtcars[mtcars$gear == 5, ] btw_this(env)
btw_tool_agent_subagent() is a btw tool that enables hierarchical agent
workflows. When used by an LLM assistant (like btw_app(), btw_client(),
or third-party tools like Claude Code), this tool allows the orchestrating
agent to delegate complex tasks to specialized subagents, each with their own
isolated conversation thread and tool access.
This function is primarily intended to be called by LLM assistants via tool use, not directly by end users.
When an LLM calls this tool:
A new chat session is created (or an existing one is resumed)
The subagent receives the prompt and begins working with only the tools
specified in the tools parameter
The subagent works independently, making tool calls until it completes the task
The function returns the subagent's final message text and a session_id
The orchestrating agent can resume the session later by providing the
session_id
Each subagent maintains its own conversation context, separate from the orchestrating agent's context. Subagent sessions persist for the duration of the R session.
The orchestrating agent must specify which tools the subagent can use via
the tools parameter. The subagent is restricted to only these tools - it
cannot access tools from the parent session. Tools can be specified by:
Specific tool names: c("btw_tool_files_read_text_file", "btw_tool_files_write_text_file")
Tool groups: "files" includes all file-related tools
NULL (default): Uses the default tool set from options or
btw_tools()
Subagent behavior can be configured via R options:
btw.subagent.client: The ellmer::Chat client or provider/model string
to use for subagents. If not set, falls back to btw.client, then to the
default Anthropic client.
btw.subagent.tools_default: Default tools to provide to subagents when
the orchestrating agent doesn't specify tools via the tools parameter.
If not set, falls back to btw.tools, then all btw tools from
btw_tools(). This is a convenience option for setting reasonable
defaults.
btw.subagent.tools_allowed: An allowlist of tools that subagents are
allowed to use at all. When set, any tools requested (either explicitly via
the tools parameter or from defaults) will be filtered against this list.
If disallowed tools are requested, an error is thrown. This provides a
security boundary to restrict subagent capabilities. If not set, all
btw_tools() are allowed.
These options follow the precedence: function argument > btw.subagent.*
option > btw.* option > default value. The tools_allowed option acts as a
filter on top of the resolved tools, regardless of their source.
btw_tool_agent_subagent( prompt, tools = NULL, session_id = NULL, `_intent` = "" )btw_tool_agent_subagent( prompt, tools = NULL, session_id = NULL, `_intent` = "" )
prompt |
Character string with the task description for the subagent.
The subagent will work on this task using only the tools specified in
|
tools |
Optional character vector of tool names or tool groups that the
subagent is allowed to use. Can be specific tool names (e.g.,
|
session_id |
Optional character string with a session ID from a previous call. When provided, resumes the existing subagent conversation instead of starting a new one. Session IDs are returned in the result and have the format "adjective_noun" (e.g., "swift_falcon"). |
_intent |
Optional string describing the intent of the tool call. Added automatically by the ellmer framework when tools are called by LLMs. |
A BtwSubagentResult object (inherits from BtwToolResult) with:
value: The final message text from the subagent
session_id: The session identifier for resuming this conversation
btw_tools() for available tools and tool groups
# This tool is typically called by LLMs via tool use, not directly. # The examples below show how to configure subagent behavior. # Configure the client and default tools for subagents withr::with_options( list( btw.subagent.client = "anthropic/claude-sonnet-4-20250514", btw.subagent.tools_default = "files" ), { getOption("btw.subagent.client") } ) # Restrict subagents to only certain tools withr::with_options( list( btw.subagent.tools_allowed = c("files", "docs"), btw.subagent.tools_default = "files" ), { getOption("btw.subagent.tools_allowed") } )# This tool is typically called by LLMs via tool use, not directly. # The examples below show how to configure subagent behavior. # Configure the client and default tools for subagents withr::with_options( list( btw.subagent.client = "anthropic/claude-sonnet-4-20250514", btw.subagent.tools_default = "files" ), { getOption("btw.subagent.client") } ) # Restrict subagents to only certain tools withr::with_options( list( btw.subagent.tools_allowed = c("files", "docs"), btw.subagent.tools_default = "files" ), { getOption("btw.subagent.tools_allowed") } )
Describes a CRAN package using pkgsearch::cran_package().
btw_tool_cran_package(package_name, `_intent` = "")btw_tool_cran_package(package_name, `_intent` = "")
package_name |
The name of a package on CRAN. |
_intent |
An optional string describing the intent of the tool use. When the tool is used by an LLM, the model will use this argument to explain why it called the tool. |
An info sheet about the package.
Other cran tools:
btw_tool_cran_search()
cli::cat_line( btw_this(pkgsearch::cran_package("anyflights")) )cli::cat_line( btw_this(pkgsearch::cran_package("anyflights")) )
Uses pkgsearch::pkg_search() to search for R packages on CRAN.
btw_tool_cran_search( query, format = c("short", "long"), n_results = NULL, `_intent` = "" )btw_tool_cran_search( query, format = c("short", "long"), n_results = NULL, `_intent` = "" )
query |
Search query string. If this argument is missing or
|
format |
Default formatting of the results. short only outputs the name and title of the packages, long also prints the author, last version, full description and URLs. Note that this only affects the default printing, and you can still inspect the full results, even if you specify short here. |
n_results |
Number of search results to include. Defaults to 10 for 'short' format and 5 for 'long' format. |
_intent |
An optional string describing the intent of the tool use. When the tool is used by an LLM, the model will use this argument to explain why it called the tool. |
A listing of packages matching the search term.
Other cran tools:
btw_tool_cran_package()
# Copy pkgsearch results to the clipboard for use in any LLM app btw( pkgsearch::pkg_search("network visualization", size = 1), clipboard = FALSE ) btw( pkgsearch::pkg_search("network visualization", format = "long", size = 1), clipboard = FALSE )# Copy pkgsearch results to the clipboard for use in any LLM app btw( pkgsearch::pkg_search("network visualization", size = 1), clipboard = FALSE ) btw( pkgsearch::pkg_search("network visualization", format = "long", size = 1), clipboard = FALSE )
Include release notes for a package, either the release notes for the most recent package release or release notes matching a search term.
btw_tool_docs_package_news(package_name, search_term = "", `_intent` = "")btw_tool_docs_package_news(package_name, search_term = "", `_intent` = "")
package_name |
The name of the package as a string, e.g. |
search_term |
A regular expression to search for in the NEWS entries. If empty, the release notes of the current installed version is included. |
_intent |
An optional string describing the intent of the tool use. When the tool is used by an LLM, the model will use this argument to explain why it called the tool. |
Returns the release notes for the currently installed version of the package, or the release notes matching the search term.
Other docs tools:
btw_tool_package_docs
# Copy release notes to the clipboard for use in any AI app btw("@news dplyr", clipboard = FALSE) btw("@news dplyr join_by", clipboard = FALSE) if (interactive()) { # can be slow if (R.version$major == 4 && R.version$minor > "2.0") { # Search through R's release notes. # This should find a NEWS entry from R 4.2 btw("@news R dynamic rd content", clipboard = FALSE) } } # Tool use by LLMs via ellmer or MCP ---- btw_tool_docs_package_news("dplyr") btw_tool_docs_package_news("dplyr", "join_by")# Copy release notes to the clipboard for use in any AI app btw("@news dplyr", clipboard = FALSE) btw("@news dplyr join_by", clipboard = FALSE) if (interactive()) { # can be slow if (R.version$major == 4 && R.version$minor > "2.0") { # Search through R's release notes. # This should find a NEWS entry from R 4.2 btw("@news R dynamic rd content", clipboard = FALSE) } } # Tool use by LLMs via ellmer or MCP ---- btw_tool_docs_package_news("dplyr") btw_tool_docs_package_news("dplyr", "join_by")
Tool: Describe data frame
btw_tool_env_describe_data_frame( data_frame, format = c("skim", "glimpse", "print", "json"), max_rows = 5, max_cols = 100, package = NULL, `_intent` = "" )btw_tool_env_describe_data_frame( data_frame, format = c("skim", "glimpse", "print", "json"), max_rows = 5, max_cols = 100, package = NULL, `_intent` = "" )
data_frame |
The data frame to describe |
format |
One of
|
max_rows |
The maximum number of rows to show in the data frame. Only
applies when |
max_cols |
The maximum number of columns to show in the data frame. Only
applies when |
package |
The name of the package that provides the data set. If not
provided, |
_intent |
An optional string describing the intent of the tool use. When the tool is used by an LLM, the model will use this argument to explain why it called the tool. |
A character vector containing a representation of the data frame. Will error if the named data frame is not found in the environment.
btw_this.data.frame(), btw_tools()
Other env tools:
btw_tool_env_describe_environment()
btw_tool_env_describe_data_frame(mtcars)btw_tool_env_describe_data_frame(mtcars)
This tool can be used by the LLM to describe the contents of an R session, i.e. the data frames and other objects loaded into the global environment. This tool will only see variables that you've named and created in the global environment, it cannot reach into package namespaces, see which packages you have loaded, or access files on your computer.
btw_tool_env_describe_environment(items = NULL, `_intent` = "")btw_tool_env_describe_environment(items = NULL, `_intent` = "")
items |
Optional. A character vector of objects in the environment to describe. |
_intent |
An optional string describing the intent of the tool use. When the tool is used by an LLM, the model will use this argument to explain why it called the tool. |
A string describing the environment contents with #> prefixing
each object's printed representation.
btw_this.environment(), btw_tools()
Other env tools:
btw_tool_env_describe_data_frame()
my_cars <- mtcars[mtcars$mpg > 25, ] btw_tool_env_describe_environment("my_cars")my_cars <- mtcars[mtcars$mpg > 25, ] btw_tool_env_describe_environment("my_cars")
This tool makes targeted, validated edits to a file using hashline references
from btw_tool_files_read(). This approach is based on the technique
described in "The Harness Problem" by Can Duruk, with additional
customizations to improve the performance of the technique, in agentic coding
session.
The core idea is that each line is annotated with a short content hash ("hashline") serving as a stable reference. When submitting an edit, the model includes hashline references for the target lines. The tool validates these hashes against the current file before applying changes, ensuring edits are applied to the intended lines. If a hash mismatch occurs, the edit is rejected and the model must re-read the file for fresh references.
btw_tool_files_read() annotates each line of the file
with a short content hash in the format line_number:hash|content, e.g.
2:d6a|library(btw). The 3-character hash is derived from
rlang::hash() over the line content (trimmed of leading/trailing
whitespace and truncated to 80 characters).
When the model submits an edit, it references specific lines by their
hashline, e.g. "2:d6a", which ensures that the edit is applied precisely to
the intended line. If the file has changed since the last read, the hashline
references will not match the current file state, and the edit will be
rejected with a hash mismatch error, prompting the model to re-read the file.
btw_tool_files_edit() supports three types of edit actions, each using
hashline references for validation:
"replace": Replace a single line. The model provides a line with a
single hashline reference, e.g. "2:d6a", and content to replace the
line. The model can also remove the line by providing empty content.
"insert_after": Insert new lines after a reference line. The model
provides a line with a hashline reference and content with the lines to
insert after it. The model can also insert at the start of the file using
line = "0:000".
"replace_range": Replace a range of consecutive lines. The model provides
a line with two hashline references indicating the start and end of the
range, e.g. "10:a3f,15:b2c", and content with the replacement lines.
Multiple edits in a single call are allowed and are applied together: all succeed or all fail. Edits must not have overlapping line ranges.
After a successful edit, the response includes updated hashline references for the edited regions (plus 1 line of surrounding context). When edits change the total line count, the response includes shift hints that tell the model how to adjust any cached line numbers without re-reading the entire file (e.g. "update line numbers by +2").
The hashline approach provides strong validation for targeted edits, and for
a single round of edits, it's generally more token efficient than the
find-and-replace approach of btw_tool_files_replace() (which is also the
approach used by many file-editing tools, e.g. Edit in Claude Code).
With the hashline approach, the model can make very specific edits without
needing to include large amounts of unchanged context around the edit, which
is often required for find-and-replace to avoid unintended matches.
However, when repeatedly editing the same file, the hashline approach can
cause the model to repeatedly re-read the file to get fresh hashline
references. I've attempted to mitigate this by including updated references
and shift hints (e.g. "update line numbers by +2") in the edit response,
which allows the model to adjust the hashline references of previously read
lines without re-reading the entire file. Models can also choose to re-read
only specific sections of the file using the line_start and line_end
parameters of btw_tool_files_read() to minimize token usage while
refreshing references for the relevant lines.
However, not all models will make use of these features, and in practice, over longer editing sessions, the hashline approach may lead to more token usage due to the model repeatedly re-reading the file to get fresh references.
btw_tool_files_edit(path, edits, `_intent` = "")btw_tool_files_edit(path, edits, `_intent` = "")
path |
Path to the file to edit. The |
edits |
A list of edit operations. Each edit is a named list with
|
_intent |
An optional string describing the intent of the tool use. When the tool is used by an LLM, the model will use this argument to explain why it called the tool. |
Returns a message confirming the edits were applied, including updated hashline references for the edited regions and shift hints when line numbers have changed.
btw_tool_files_read() for reading files with hashline
annotations, btw_tool_files_replace() for find-and-replace edits that
don't require hashline references.
Other files tools:
btw_tool_files_list(),
btw_tool_files_patch(),
btw_tool_files_read(),
btw_tool_files_replace(),
btw_tool_files_search(),
btw_tool_files_write()
Tool: List files
btw_tool_files_list( path = NULL, type = c("any", "file", "directory"), regexp = "", `_intent` = "" )btw_tool_files_list( path = NULL, type = c("any", "file", "directory"), regexp = "", `_intent` = "" )
path |
Path to a directory or file for which to get information. The
|
type |
File type(s) to return, one of |
regexp |
A regular expression (e.g. |
_intent |
An optional string describing the intent of the tool use. When the tool is used by an LLM, the model will use this argument to explain why it called the tool. |
Returns a character table of file information.
Other files tools:
btw_tool_files_edit(),
btw_tool_files_patch(),
btw_tool_files_read(),
btw_tool_files_replace(),
btw_tool_files_search(),
btw_tool_files_write()
withr::with_tempdir({ write.csv(mtcars, "mtcars.csv") btw_tool_files_list(type = "file") })withr::with_tempdir({ write.csv(mtcars, "mtcars.csv") btw_tool_files_list(type = "file") })
Applies a structured diff-like patch envelope to one or more files. Unlike
btw_tool_files_edit() (which requires hashline references from a prior
read) or btw_tool_files_replace() (which requires exact strings), the
patch tool uses context-matching hunks so models can produce coordinated
edits across multiple files in a single tool call. A single patch envelope
can add, update, delete, and move files atomically: either all operations
succeed or none are applied.
A patch is a text envelope that begins with *** Begin Patch and ends with
*** End Patch. Inside the envelope, each operation starts with a header:
** Begin Patch ** Add File: docs/example.md Hello World ** Update File: src/main.py @@ context line old line new line ** Delete File: old.txt ** Update File: src/old.ts ** Move to: src/new.ts @@ context line export const oldName = 1 export const newName = 1 ** End Patch
*** Add File: <path> – create a new file (must not exist).
*** Update File: <path> – modify an existing file.
*** Delete File: <path> – remove an existing file.
*** Move to: <path> – sub-header inside an Update File block; renames
the file to <path> after applying any hunks. Destination must not exist.
Update File)@ – hunk boundary; any trailing text on this line is informational and
ignored.
<text> (space prefix) – context line that must match the file exactly.
-<text> – line to delete; must match the file exactly at this position.
+<text> – line to insert.
Every hunk must include at least one context or delete line to anchor the
edit; pure-insert hunks are rejected. Use *** Add File for new files.
All body lines under *** Add File must start with +; the file content is
the text after each +.
btw_tool_files_patch(patch, `_intent` = "")btw_tool_files_patch(patch, `_intent` = "")
patch |
The full patch text in the wire format described below. Must
begin with |
_intent |
An optional string describing the intent of the tool use. When the tool is used by an LLM, the model will use this argument to explain why it called the tool. |
Returns a summary of the operations applied.
btw_tool_files_edit() for hashline-based targeted edits,
btw_tool_files_replace() for exact find-and-replace edits.
Other files tools:
btw_tool_files_edit(),
btw_tool_files_list(),
btw_tool_files_read(),
btw_tool_files_replace(),
btw_tool_files_search(),
btw_tool_files_write()
Reads the contents of a text file, optionally restricted to a line range.
Each line is annotated with a hashline prefix (line_number:hash|content)
that enables validated editing via btw_tool_files_edit().
The hashline format prefixes each line with line_number:hash|, e.g.
2:f1a| return("world"). The 3-character hash is a truncated
rlang::hash() of the line content after trimming whitespace and
truncating to 80 characters. These hashes are used by
btw_tool_files_edit() to validate that the file hasn't changed between
reading and editing. See btw_tool_files_edit() for details on the
hashline approach and its benefits and limitations.
Hashline annotations are only included in the model-facing tool output. The
display shown to users in btw_app() or shinychat::chat_ui() is always a
clean code block.
btw_tool_files_read(path, line_start = 1, line_end = 1000, `_intent` = "")btw_tool_files_read(path, line_start = 1, line_end = 1000, `_intent` = "")
path |
Path to a file for which to get information. The |
line_start |
Starting line to read, defaults to 1 (starting from the first line). |
line_end |
Ending line to read, defaults to 1000. Change only this value
if you want to read more or fewer lines. Use in combination with
|
_intent |
An optional string describing the intent of the tool use. When the tool is used by an LLM, the model will use this argument to explain why it called the tool. |
Returns lines with hashline annotations (see Hashline annotations).
btw_tool_files_edit() for making validated edits using hashline
references, btw_tool_files_replace() for exact string find-and-replace,
btw_tool_files_write() for writing entire files.
Other files tools:
btw_tool_files_edit(),
btw_tool_files_list(),
btw_tool_files_patch(),
btw_tool_files_replace(),
btw_tool_files_search(),
btw_tool_files_write()
withr::with_tempdir({ write.csv(mtcars, "mtcars.csv") btw_tool_files_read("mtcars.csv", line_end = 5) })withr::with_tempdir({ write.csv(mtcars, "mtcars.csv") btw_tool_files_read("mtcars.csv", line_end = 5) })
Finds and replaces exact string occurrences in a file. Because this tool operates on exact string matches, it's suited for simple renames, value updates, or repetitive text changes where the target string is unambiguous.
btw's two file-editing tools serve different use cases:
btw_tool_files_replace() is best for exact text substitutions:
renaming a variable, updating a URL, or changing a value. It does not
require a prior btw_tool_files_read() call. By default, it requires the
match to be unique to prevent unintended changes.
btw_tool_files_edit() is best for structural, line-based edits: inserting
new lines, deleting lines, replacing a range of lines, or making several
edits at once. It requires hashline references from a prior
btw_tool_files_read() call and validates them against the current file
state.
btw_tool_files_replace( path, old_string, new_string, replace_all = FALSE, `_intent` = "" )btw_tool_files_replace( path, old_string, new_string, replace_all = FALSE, `_intent` = "" )
path |
Path to the file to edit. The |
old_string |
The exact string to find in the file. Must match
character-for-character, including whitespace and indentation. Must be
unique unless |
new_string |
The replacement string. Must differ from |
replace_all |
If |
_intent |
An optional string describing the intent of the tool use. When the tool is used by an LLM, the model will use this argument to explain why it called the tool. |
Returns a message confirming the replacement was applied, including the number of occurrences replaced.
btw_tool_files_edit() for line-based structural edits using
hashline references, btw_tool_files_read() for reading files.
Other files tools:
btw_tool_files_edit(),
btw_tool_files_list(),
btw_tool_files_patch(),
btw_tool_files_read(),
btw_tool_files_search(),
btw_tool_files_write()
Search through code files in the project directory for specific terms.
btw_tool_files_search( term, limit = 100, case_sensitive = TRUE, use_regex = FALSE, show_lines = FALSE, `_intent` = "" )btw_tool_files_search( term, limit = 100, case_sensitive = TRUE, use_regex = FALSE, show_lines = FALSE, `_intent` = "" )
term |
The term to search for in the code files. |
limit |
Maximum number of matching lines to return (between 1 and 1000, default 100). |
case_sensitive |
Whether the search should be case-sensitive (default is
|
use_regex |
Whether to interpret the search term as a regular expression
(default is |
show_lines |
Whether to show the matching lines in the results. Defaults
to |
_intent |
An optional string describing the intent of the tool use. When the tool is used by an LLM, the model will use this argument to explain why it called the tool. |
You can configure which file extensions are included and which paths are excluded from code search by using two options:
btw.files_search.extensions: A character vector of file extensions
to search in (default includes R, Python, JavaScript, TypeScript, Markdown,
SCSS, and CSS files).
btw.files_search.exclusions: A character vector of gitignore-style
patterns to exclude paths and directories from the search. The default
value includes a set of common version control, IDE, and cache folders.
Alternatively, you can also set these options in your btw.md file under the
options section, like this:
---
client:
provider: anthropic
tools: [files_search]
options:
files_search:
extensions: ["R", "Rmd", "py", "qmd"]
exclusions: ["DEFAULT", ".quarto/"]
---
Include "DEFAULT" in the exclusions option to use btw's default
exclusions, which cover common directories like .git/, .vscode/.
If the gert package is installed and the project is a Git repository,
the tool will also respect the .gitignore file and exclude any ignored
paths, regardless of the btw.files_search.exclusions option.
Returns a tool result with a data frame of search results, with
columns for filename, size, last_modified, content and line.
Other files tools:
btw_tool_files_edit(),
btw_tool_files_list(),
btw_tool_files_patch(),
btw_tool_files_read(),
btw_tool_files_replace(),
btw_tool_files_write()
withr::with_tempdir({ writeLines(state.name[1:25], "state_names_1.md") writeLines(state.name[26:50], "state_names_2.md") tools <- btw_tools("files_search") tools$btw_tool_files_search( term = "kentucky", case_sensitive = FALSE, show_lines = TRUE ) })withr::with_tempdir({ writeLines(state.name[1:25], "state_names_1.md") writeLines(state.name[26:50], "state_names_2.md") tools <- btw_tools("files_search") tools$btw_tool_files_search( term = "kentucky", case_sensitive = FALSE, show_lines = TRUE ) })
Tool: Write a text file
btw_tool_files_write(path, content, `_intent` = "")btw_tool_files_write(path, content, `_intent` = "")
path |
Path to the file to write. The |
content |
The text content to write to the file. This should be the complete content as the file will be overwritten. |
_intent |
An optional string describing the intent of the tool use. When the tool is used by an LLM, the model will use this argument to explain why it called the tool. |
Returns a message confirming the file was written.
Other files tools:
btw_tool_files_edit(),
btw_tool_files_list(),
btw_tool_files_patch(),
btw_tool_files_read(),
btw_tool_files_replace(),
btw_tool_files_search()
withr::with_tempdir({ btw_tool_files_write("example.txt", "Hello\nWorld!") readLines("example.txt") })withr::with_tempdir({ btw_tool_files_write("example.txt", "Hello\nWorld!") readLines("example.txt") })
Allows an LLM to switch to a different git branch using
gert::git_branch_checkout(), equivalent to git checkout <branch> in
the terminal.
btw_tool_git_branch_checkout(branch, force = FALSE, `_intent` = "")btw_tool_git_branch_checkout(branch, force = FALSE, `_intent` = "")
branch |
Name of branch to check out. |
force |
Whether to force checkout even with uncommitted changes.
Defaults to |
_intent |
An optional string describing the intent of the tool use. When the tool is used by an LLM, the model will use this argument to explain why it called the tool. |
Returns a confirmation message.
Other git tools:
btw_tool_git_branch_create(),
btw_tool_git_branch_list(),
btw_tool_git_commit(),
btw_tool_git_diff(),
btw_tool_git_log(),
btw_tool_git_status()
withr::with_tempdir({ gert::git_init() gert::git_config_set("user.name", "R Example") gert::git_config_set("user.email", "[email protected]") fs::file_touch("hello.md") gert::git_add("hello.md") gert::git_commit("Initial commit") gert::git_branch_create("feature-1") # LLM checks out an existing branch res <- btw_tool_git_branch_checkout(branch = "feature-1") # What the LLM sees cat(res@value) })withr::with_tempdir({ gert::git_init() gert::git_config_set("user.name", "R Example") gert::git_config_set("user.email", "[email protected]") fs::file_touch("hello.md") gert::git_add("hello.md") gert::git_commit("Initial commit") gert::git_branch_create("feature-1") # LLM checks out an existing branch res <- btw_tool_git_branch_checkout(branch = "feature-1") # What the LLM sees cat(res@value) })
Allows an LLM to create a new git branch using gert::git_branch_create(),
equivalent to git branch <branch> in the terminal.
btw_tool_git_branch_create( branch, ref = "HEAD", checkout = TRUE, `_intent` = "" )btw_tool_git_branch_create( branch, ref = "HEAD", checkout = TRUE, `_intent` = "" )
branch |
Name of the new branch to create. |
ref |
Optional reference point for the new branch. Defaults to |
checkout |
Whether to check out the new branch after creation. Defaults
to |
_intent |
An optional string describing the intent of the tool use. When the tool is used by an LLM, the model will use this argument to explain why it called the tool. |
Returns a confirmation message.
Other git tools:
btw_tool_git_branch_checkout(),
btw_tool_git_branch_list(),
btw_tool_git_commit(),
btw_tool_git_diff(),
btw_tool_git_log(),
btw_tool_git_status()
withr::with_tempdir({ gert::git_init() gert::git_config_set("user.name", "R Example") gert::git_config_set("user.email", "[email protected]") fs::file_touch("hello.md") gert::git_add("hello.md") gert::git_commit("Initial commit") # LLM creates a new branch res <- btw_tool_git_branch_create(branch = "feature/new-analysis") # What the LLM sees cat(res@value) })withr::with_tempdir({ gert::git_init() gert::git_config_set("user.name", "R Example") gert::git_config_set("user.email", "[email protected]") fs::file_touch("hello.md") gert::git_add("hello.md") gert::git_commit("Initial commit") # LLM creates a new branch res <- btw_tool_git_branch_create(branch = "feature/new-analysis") # What the LLM sees cat(res@value) })
This tool allows an LLM to list git branches in the repository using
gert::git_branch_list(), equivalent to git branch in the terminal.
btw_tool_git_branch_list(include = c("local", "remote", "all"), `_intent` = "")btw_tool_git_branch_list(include = c("local", "remote", "all"), `_intent` = "")
include |
Once of |
_intent |
An optional string describing the intent of the tool use. When the tool is used by an LLM, the model will use this argument to explain why it called the tool. |
Returns a character table of branches.
Other git tools:
btw_tool_git_branch_checkout(),
btw_tool_git_branch_create(),
btw_tool_git_commit(),
btw_tool_git_diff(),
btw_tool_git_log(),
btw_tool_git_status()
withr::with_tempdir({ gert::git_init() gert::git_config_set("user.name", "R Example") gert::git_config_set("user.email", "[email protected]") fs::file_touch("hello.md") gert::git_add("hello.md") gert::git_commit("Initial commit") gert::git_branch_create("feature-1") gert::git_branch_create("feature-2") # What the LLM sees cat(btw_tool_git_branch_list()@value) })withr::with_tempdir({ gert::git_init() gert::git_config_set("user.name", "R Example") gert::git_config_set("user.email", "[email protected]") fs::file_touch("hello.md") gert::git_add("hello.md") gert::git_commit("Initial commit") gert::git_branch_create("feature-1") gert::git_branch_create("feature-2") # What the LLM sees cat(btw_tool_git_branch_list()@value) })
This tool allows an LLM stage files and create a git commit. This tool uses a
combination of gert::git_add() to stage files and gert::git_commit() to
commit them, which is equivalent to git add and git commit in the
terminal, respectively.
btw_tool_git_commit(message, files = NULL, `_intent` = "")btw_tool_git_commit(message, files = NULL, `_intent` = "")
message |
A commit message describing the changes. |
files |
Optional character vector of file paths to stage and commit.
Use |
_intent |
An optional string describing the intent of the tool use. When the tool is used by an LLM, the model will use this argument to explain why it called the tool. |
Returns the commit SHA.
Other git tools:
btw_tool_git_branch_checkout(),
btw_tool_git_branch_create(),
btw_tool_git_branch_list(),
btw_tool_git_diff(),
btw_tool_git_log(),
btw_tool_git_status()
withr::with_tempdir({ gert::git_init() gert::git_config_set("user.name", "R Example") gert::git_config_set("user.email", "[email protected]") writeLines("hello, world", "hello.md") res <- btw_tool_git_commit("Initial commit", files = "hello.md") # What the LLM sees cat(res@value) })withr::with_tempdir({ gert::git_init() gert::git_config_set("user.name", "R Example") gert::git_config_set("user.email", "[email protected]") writeLines("hello, world", "hello.md") res <- btw_tool_git_commit("Initial commit", files = "hello.md") # What the LLM sees cat(res@value) })
This tool allows an LLM to run gert::git_diff_patch(), equivalent to
git diff in the terminal, and to see the detailed changes made in a commit.
btw_tool_git_diff(ref = NULL, `_intent` = "")btw_tool_git_diff(ref = NULL, `_intent` = "")
ref |
a reference such as |
_intent |
An optional string describing the intent of the tool use. When the tool is used by an LLM, the model will use this argument to explain why it called the tool. |
Returns a diff patch as a formatted string.
Other git tools:
btw_tool_git_branch_checkout(),
btw_tool_git_branch_create(),
btw_tool_git_branch_list(),
btw_tool_git_commit(),
btw_tool_git_log(),
btw_tool_git_status()
withr::with_tempdir({ gert::git_init() gert::git_config_set("user.name", "R Example") gert::git_config_set("user.email", "[email protected]") writeLines("hello, world", "hello.md") gert::git_add("hello.md") gert::git_commit("Initial commit") writeLines("hello, universe", "hello.md") # What the LLM sees cat(btw_tool_git_diff()@value) })withr::with_tempdir({ gert::git_init() gert::git_config_set("user.name", "R Example") gert::git_config_set("user.email", "[email protected]") writeLines("hello, world", "hello.md") gert::git_add("hello.md") gert::git_commit("Initial commit") writeLines("hello, universe", "hello.md") # What the LLM sees cat(btw_tool_git_diff()@value) })
This tool allows an LLM to run gert::git_log(), equivalent to git log in
the terminal, and to see the commit history of a repository.
btw_tool_git_log(ref = "HEAD", max = 10, after = NULL, `_intent` = "")btw_tool_git_log(ref = "HEAD", max = 10, after = NULL, `_intent` = "")
ref |
Revision string with a branch/tag/commit value. Defaults to
|
max |
Maximum number of commits to retrieve. Defaults to 10. |
after |
Optional date or timestamp: only include commits after this date. |
_intent |
An optional string describing the intent of the tool use. When the tool is used by an LLM, the model will use this argument to explain why it called the tool. |
Returns a character table of commit history.
Other git tools:
btw_tool_git_branch_checkout(),
btw_tool_git_branch_create(),
btw_tool_git_branch_list(),
btw_tool_git_commit(),
btw_tool_git_diff(),
btw_tool_git_status()
withr::with_tempdir({ gert::git_init() gert::git_config_set("user.name", "R Example") gert::git_config_set("user.email", "[email protected]") writeLines("hello, world", "hello.md") gert::git_add("hello.md") gert::git_commit("Initial commit") writeLines("hello, universe", "hello.md") gert::git_add("hello.md") gert::git_commit("Update hello.md") # What the LLM sees cat(btw_tool_git_log()@value) })withr::with_tempdir({ gert::git_init() gert::git_config_set("user.name", "R Example") gert::git_config_set("user.email", "[email protected]") writeLines("hello, world", "hello.md") gert::git_add("hello.md") gert::git_commit("Initial commit") writeLines("hello, universe", "hello.md") gert::git_add("hello.md") gert::git_commit("Update hello.md") # What the LLM sees cat(btw_tool_git_log()@value) })
This tool allows the LLM to run gert::git_status(), equivalent to git status in the terminal, and to see the current status of the working
directory.
btw_tool_git_status( include = c("both", "staged", "unstaged"), pathspec = NULL, `_intent` = "" )btw_tool_git_status( include = c("both", "staged", "unstaged"), pathspec = NULL, `_intent` = "" )
include |
One of |
pathspec |
Optional character vector with paths to match. |
_intent |
An optional string describing the intent of the tool use. When the tool is used by an LLM, the model will use this argument to explain why it called the tool. |
Returns a character table of file statuses.
Other git tools:
btw_tool_git_branch_checkout(),
btw_tool_git_branch_create(),
btw_tool_git_branch_list(),
btw_tool_git_commit(),
btw_tool_git_diff(),
btw_tool_git_log()
withr::with_tempdir({ gert::git_init() gert::git_config_set("user.name", "R Example") gert::git_config_set("user.email", "[email protected]") writeLines("hello, world", "hello.md") # What the LLM sees cat(btw_tool_git_status()@value) })withr::with_tempdir({ gert::git_init() gert::git_config_set("user.name", "R Example") gert::git_config_set("user.email", "[email protected]") writeLines("hello, world", "hello.md") # What the LLM sees cat(btw_tool_git_status()@value) })
Execute R code that calls the GitHub API using gh::gh().
This tool is
designed such that models can write very limited R code to call gh::gh()
and protections are inserted to prevent the model from calling unsafe or
destructive actions via the API. The Endpoint Validation section below
describes how API endpoints are validated to ensure safety.
While this tool can execute R code, the code is evaluated in an environment
where only a limited set of functions and variables are available. In
particular, only the gh() and gh_whoami() functions from the gh package
are available, along with owner and repo variables that are pre-defined
to point to the current repository (if detected). This allows models to focus
on writing GitHub API calls without needing to load packages or manage
authentication.
This tool uses endpoint validation to ensure only safe GitHub API operations are performed. By default, most read operations and low-risk write operations (like creating issues or PRs) are allowed, while dangerous operations (like merging PRs or deleting repositories) are blocked.
To customize which endpoints are allowed or blocked, use the
btw.github.allow and btw.github.block options:
# Allow a specific endpoint
options(btw.github.allow = c(
getOption("btw.github.allow"),
"GET /repos/*/*/topics"
))
# Block a specific endpoint
options(btw.github.block = c(
getOption("btw.github.block"),
"GET /repos/*/*/branches"
))
You can also set these options in your btw.md file under the
options field:
tools: github
options:
github:
allow:
- "PATCH /repos/*/*/pulls/*" # Allow converting PRs to/from draft
- "POST /repos/*/*/git/refs" # Allow creating branches
block:
- "DELETE /repos/**" # Block any delete action under /repos
The precedence order for rules is:
User block rules (checked first, highest priority)
User allow rules
Built-in block rules
Built-in allow rules
Default: reject (if no rules match)
# Get an issue
btw_tool_github(
code = 'gh("/repos/{owner}/{repo}/issues/123", owner = owner, repo = repo)'
)
# Create an issue
btw_tool_github(code = r"(
gh(
"POST /repos/{owner}/{repo}/issues",
title = \"Bug report\",
body = \"Description of bug\",
owner = owner,
repo = repo
)
)")
# Target a different repository
btw_tool_github(code = 'gh("/repos/tidyverse/dplyr/issues/123")')
btw_tool_github(code, fields = "default", `_intent` = "")btw_tool_github(code, fields = "default", `_intent` = "")
code |
R code that calls |
fields |
Optional character vector of GitHub API response fields to retain. If provided, only these fields will be included in the result. Defaults to a curated set of commonly used fields. |
_intent |
An optional string describing the intent of the tool use. When the tool is used by an LLM, the model will use this argument to explain why it called the tool. |
A btw_tool_result containing the result of the GitHub API call.
# This tool requires the gh package and authentication to GitHub. # See additional examples in the documentation above.# This tool requires the gh package and authentication to GitHub. # See additional examples in the documentation above.
Reads the current file using the rstudioapi, which works in RStudio, Positron and VS Code (with the vscode-r extension).
btw_tool_ide_read_current_editor( selection = TRUE, consent = FALSE, `_intent` = "" )btw_tool_ide_read_current_editor( selection = TRUE, consent = FALSE, `_intent` = "" )
selection |
Should only the selected text be included? If no text is selected, the full file contents are returned. |
consent |
Boolean indicating whether the user has consented to reading
the current file. The tool definition includes language to induce LLMs to
confirm with the user before calling the tool. Not all models will follow
these instructions. Users can also include the string |
_intent |
An optional string describing the intent of the tool use. When the tool is used by an LLM, the model will use this argument to explain why it called the tool. |
Returns the contents of the current editor.
btw_tool_ide_read_current_editor(consent = TRUE)btw_tool_ide_read_current_editor(consent = TRUE)
These functions describe package documentation in plain text.
Show a list of available vignettes in the dplyr package:
btw_tool_docs_available_vignettes("dplyr")
Get the introductory vignette for the dplyr package:
btw_tool_docs_vignette("dplyr")
Get a specific vignette, such as the programming vignette for the dplyr
package:
btw_tool_docs_vignette("dplyr", "programming")
btw_tool_docs_package_help_topics(package_name, `_intent` = "") btw_tool_docs_help_page(topic, package_name = "", `_intent` = "") btw_tool_docs_available_vignettes(package_name, `_intent` = "") btw_tool_docs_vignette(package_name, vignette = package_name, `_intent` = "")btw_tool_docs_package_help_topics(package_name, `_intent` = "") btw_tool_docs_help_page(topic, package_name = "", `_intent` = "") btw_tool_docs_available_vignettes(package_name, `_intent` = "") btw_tool_docs_vignette(package_name, vignette = package_name, `_intent` = "")
package_name |
The name of the package as a string, e.g. |
_intent |
An optional string describing the intent of the tool use. When the tool is used by an LLM, the model will use this argument to explain why it called the tool. |
topic |
The |
vignette |
The name (or index) of the vignette to retrieve. Defaults to the "intro" vignette to the package (by the same rules as pkgdown.) |
btw_tool_docs_package_help_topics() returns the topic_id, title, and
aliases fields for every topic in a package's documentation as a
json-formatted string.
btw_tool_docs_help_page() returns the help-page for a package topic as a
string.
Other docs tools:
btw_tool_docs_package_news()
btw_tool_docs_package_help_topics("btw") btw_tool_docs_help_page("btw", "btw")btw_tool_docs_package_help_topics("btw") btw_tool_docs_help_page("btw", "btw")
Run R CMD check on a package using devtools::check(). This performs
comprehensive checks on the package structure, code, and documentation.
btw_tool_pkg_check(pkg = ".", `_intent` = "")btw_tool_pkg_check(pkg = ".", `_intent` = "")
pkg |
Path to package directory. Defaults to '.'. Must be within current working directory. |
_intent |
An optional string describing the intent of the tool use. When the tool is used by an LLM, the model will use this argument to explain why it called the tool. |
The check runs with remote = TRUE, cran = TRUE, manual = FALSE, and
error_on = "never" to provide comprehensive feedback without failing.
The output from devtools::check().
Other pkg tools:
btw_tool_pkg_coverage(),
btw_tool_pkg_document(),
btw_tool_pkg_load_all(),
btw_tool_pkg_test()
Compute test coverage for an R package using covr::package_coverage().
Returns either a file-level summary for the entire package or line-level
details for a specific file.
btw_tool_pkg_coverage(pkg = ".", filename = NULL, `_intent` = "")btw_tool_pkg_coverage(pkg = ".", filename = NULL, `_intent` = "")
pkg |
Path to package directory. Defaults to |
filename |
Optional filename to filter coverage results. If |
_intent |
An optional string describing the intent of the tool use. When the tool is used by an LLM, the model will use this argument to explain why it called the tool. |
A data frame with different structures depending on filename:
When filename = NULL: Returns file-level summary with columns
filename and coverage (percentage).
When filename is specified: Returns line-level details with columns
filename, functions, line_start, line_end, is_covered, and
med_hits.
Other pkg tools:
btw_tool_pkg_check(),
btw_tool_pkg_document(),
btw_tool_pkg_load_all(),
btw_tool_pkg_test()
Generate package documentation using devtools::document(). This runs
roxygen2 on the package to create/update man pages and NAMESPACE.
btw_tool_pkg_document(pkg = ".", `_intent` = "")btw_tool_pkg_document(pkg = ".", `_intent` = "")
pkg |
Path to package directory. Defaults to |
_intent |
An optional string describing the intent of the tool use. When the tool is used by an LLM, the model will use this argument to explain why it called the tool. |
The output from devtools::document().
Other pkg tools:
btw_tool_pkg_check(),
btw_tool_pkg_coverage(),
btw_tool_pkg_load_all(),
btw_tool_pkg_test()
Load package code using pkgload::load_all() in a separate R process via
callr::r(). This verifies that the package code loads without syntax errors
and triggers recompilation of any compiled code (C, C++, etc.).
btw_tool_pkg_load_all(pkg = ".", `_intent` = "")btw_tool_pkg_load_all(pkg = ".", `_intent` = "")
pkg |
Path to package directory. Defaults to '.'. Must be within current working directory. |
_intent |
An optional string describing the intent of the tool use. When the tool is used by an LLM, the model will use this argument to explain why it called the tool. |
Important: This tool runs load_all() in an isolated R process and does
NOT load the package code into your current R session. If you need to load
the package code in your current session for interactive use, use the run R
code tool to call pkgload::load_all() directly.
The output from pkgload::load_all().
Other pkg tools:
btw_tool_pkg_check(),
btw_tool_pkg_coverage(),
btw_tool_pkg_document(),
btw_tool_pkg_test()
Run package tests using devtools::test(). Optionally filter tests by name
pattern.
btw_tool_pkg_test(pkg = ".", filter = NULL, `_intent` = "")btw_tool_pkg_test(pkg = ".", filter = NULL, `_intent` = "")
pkg |
Path to package directory. Defaults to '.'. Must be within current working directory. |
filter |
Optional regex to filter test files. Example: 'helper' matches 'test-helper.R'. |
_intent |
An optional string describing the intent of the tool use. When the tool is used by an LLM, the model will use this argument to explain why it called the tool. |
The output from devtools::test().
Other pkg tools:
btw_tool_pkg_check(),
btw_tool_pkg_coverage(),
btw_tool_pkg_document(),
btw_tool_pkg_load_all()
This tool runs R code and returns results as a list of
ellmer::Content()
objects. It captures text output, plots, messages, warnings, and errors. Code
execution stops on the first error, returning all results up to that point.
btw_tool_run_r(code, `_intent` = "")btw_tool_run_r(code, `_intent` = "")
code |
A character string containing R code to run. |
_intent |
An optional string describing the intent of the tool use. When the tool is used by an LLM, the model will use this argument to explain why it called the tool. |
The behavior of the btw_tool_run_r tool can be customized using the
following R options:
btw.run_r.graphics_device: A function that creates a graphics device used
for rendering plots. By default, it uses ragg::agg_png() if the ragg
package is installed, otherwise it falls back to grDevices::png().
btw.run_r.plot_aspect_ratio: Aspect ratio for plots created during code
execution. Can be a character string of the form "w:h" (e.g., "16:9")
or a numeric value representing width/height (e.g., 16/9). Default is
"3:2".
btw.run_r.plot_size: Integer pixel size for the longest side of plots.
Default is 768L. This image size was selected to match OpenAI's image resizing rules,
where images are resized such that the largest size is 768px. Another
common choice is 512px. Larger images may be used but will result in
increased token sizes.
btw.run_r.enabled: Logical flag to enable or disable the tool globally.
These values can be set using options() in your R session or .Rprofile or
in a btw.md file under the options section.
--- options: run_r: enabled: true plot_aspect_ratio: "16:9" plot_size: 512 ---
A list of ellmer Content objects:
ContentText: visible return values and text output
ContentMessage: messages from message()
ContentWarning: warnings from warning()
ContentError: errors from stop()
ContentImageInline: plots created during execution
Executing arbitrary R code can pose significant security risks, especially in shared or multi-user environments. Furthermore, neither shinychat (as of v0.4.0) or nor ellmer (as of v0.4.0) provide a mechanism to review and reject the code before execution. Even more, the code is executed in the global environment and does not have any sandboxing or R code limitations applied.
It is your responsibility to ensure that you are taking appropriate measures to reduce the risk of the LLM writing arbitrary code. Most often, this means not prompting the model to take large or potentially destructive actions. At this time, we do not recommend that you enable this tool in a publicly- available environment without strong safeguards in place.
That said, this tool is very powerful and can greatly enhance the capabilities of your btw chatbots. Please use it responsibly! If you'd like to enable the tool, please read the instructions below.
This tool is not enabled by default in btw_tools(), btw_app() or
btw_client(). To enable the function, you have a few options:
Set the btw.run_r.enabled option to TRUE in your R session, or in your
.Rprofile file to enable it globally.
Set the BTW_RUN_R_ENABLED environment variable to true in your
.Renviron file or your system environment.
Explicitly include the tool when calling btw_tools("run") (unless the
above options disable it).
In your btw.md file, you can explicitly enable the tool by naming it in the tools option
--- tools: - run_r ---
or you can enable the tool by setting the btw.run_r.enabled option from the
options list in btw.md (this approach is useful if you've globally
disabled the tool but want to enable it for a specific btw chat):
---
options:
run_r:
enabled: true
---
## Not run: # Simple calculation btw_tool_run_r("2 + 2") # Code with plot btw_tool_run_r("hist(rnorm(100))") # Code with warning btw_tool_run_r("mean(c(1, 2, NA))") ## End(Not run)## Not run: # Simple calculation btw_tool_run_r("2 + 2") # Code with plot btw_tool_run_r("hist(rnorm(100))") # Code with warning btw_tool_run_r("mean(c(1, 2, NA))") ## End(Not run)
Checks if a package is installed in the current session. If the package is installed, it returns the version number. If not, it suggests packages with similar names to help the LLM resolve typos.
btw_tool_sessioninfo_is_package_installed(package_name, `_intent` = "")btw_tool_sessioninfo_is_package_installed(package_name, `_intent` = "")
package_name |
The name of the package. |
_intent |
An optional string describing the intent of the tool use. When the tool is used by an LLM, the model will use this argument to explain why it called the tool. |
A message indicating whether the package is installed and its version, or an error indicating that the package is not installed.
Other sessioninfo tools:
btw_tool_sessioninfo_package(),
btw_tool_sessioninfo_platform()
btw_tool_sessioninfo_is_package_installed("dplyr")@value tryCatch( btw_tool_sessioninfo_is_package_installed("dplry"), error = function(err) { cat(conditionMessage(err)) } )btw_tool_sessioninfo_is_package_installed("dplyr")@value tryCatch( btw_tool_sessioninfo_is_package_installed("dplry"), error = function(err) { cat(conditionMessage(err)) } )
Uses sessioninfo::package_info() to provide information about the loaded,
attached, or installed packages. The primary use case is to verify that a
package is installed; check the version number of a specific packages; or
determine which packages are already in use in a session.
btw_tool_sessioninfo_package( packages = "attached", dependencies = "", `_intent` = "" )btw_tool_sessioninfo_package( packages = "attached", dependencies = "", `_intent` = "" )
packages |
Which packages to show, or |
dependencies |
Whether to include the dependencies when listing package information. |
_intent |
An optional string describing the intent of the tool use. When the tool is used by an LLM, the model will use this argument to explain why it called the tool. |
Returns a string describing the selected packages.
btw_tools(), btw_tool_sessioninfo_platform()
Other sessioninfo tools:
btw_tool_sessioninfo_is_package_installed(),
btw_tool_sessioninfo_platform()
btw_tool_sessioninfo_package("btw")btw_tool_sessioninfo_package("btw")
Describes the R version, operating system, and language and locale settings
for the user's system. When using btw_client() or btw_app(), this
information is automatically included in the system prompt.
btw_tool_sessioninfo_platform(`_intent` = "")btw_tool_sessioninfo_platform(`_intent` = "")
_intent |
An optional string describing the intent of the tool use. When the tool is used by an LLM, the model will use this argument to explain why it called the tool. |
Returns a string describing the user's platform.
Other sessioninfo tools:
btw_tool_sessioninfo_is_package_installed(),
btw_tool_sessioninfo_package()
btw_tool_sessioninfo_platform()btw_tool_sessioninfo_platform()
Load a skill's specialized instructions and list its bundled resources.
Skills are modular capabilities that extend Claude's functionality with
specialized knowledge, workflows, and tools. Each skill is a directory
containing a SKILL.md file with instructions and optional bundled
resources (scripts, references, assets).
When btw_tool_skill is included in the chat client's tools, btw
automatically injects information about available skills into the system
prompt so the model knows which skills are available. If the skill tool is
added after client creation, the model can call btw_tool_skill("") (empty
name) to get the current skill listing.
Skills are discovered from the following locations, in increasing order of priority (later sources override earlier ones when skill names conflict):
Skills bundled with the btw package itself
Skills from currently attached R packages — any package with an
inst/skills/ directory that is loaded via library() or require()
User-level skills (~/.btw/skills, ~/.config/btw/skills,
tools::R_user_dir("btw")/skills). For backwards compatibility, the
legacy tools::R_user_dir("btw", "config")/skills path used by briefly
by btw 1.2.0 is also included at lower priority.
Project-level skills (.btw/skills/ or .agents/skills/)
The default user-level and project-level directories can be replaced by
setting the btw.skills.paths R option or the BTW_SKILLS_PATHS environment
variable. When set, the value entirely replaces all user-level and project-level
directories (items 3 and 4 above). Package-bundled skills and skills from
attached packages (items 1 and 2) are always included regardless of this
setting. The R option takes precedence over the environment variable.
Multiple paths can be provided as a character vector (e.g.
options(btw.skills.paths = c("/path/a", "/path/b"))) or as a single
path-separator-delimited string (: on Unix/Mac, ; on Windows, which is
the only form supported by environment variables). Non-existent paths are
silently skipped.
Resolution timing: options and environment variables are read at
tool-registration time (i.e. when btw_tools() or btw_client() is
called). The resolved paths are captured in the tool's closure so that they
remain correct even if the options are later modified or go out of scope
(for example, when btw_client() restores options after returning). If you
need different directories for a new session, create a new client.
btw_tool_skill(name, `_intent` = "")btw_tool_skill(name, `_intent` = "")
name |
The name of the skill to load, or |
_intent |
An optional string describing the intent of the tool use. When the tool is used by an LLM, the model will use this argument to explain why it called the tool. |
A btw_tool_result containing the skill instructions and a listing
of bundled resources with their paths.
Other skills:
btw_skill_install_github(),
btw_skill_install_package(),
btw_skill_install_project()
Tool: Read a Web Page as Markdown
btw_tool_web_read_url(url, `_intent` = "")btw_tool_web_read_url(url, `_intent` = "")
url |
The URL of the web page to read. |
_intent |
An optional string describing the intent of the tool use. When the tool is used by an LLM, the model will use this argument to explain why it called the tool. |
You can control the maximum time to wait for the page to load by setting
the btw.max_wait_for_page_load_s option globally in your R session.
Returns a BtwWebPageResult object that inherits from
ellmer::ContentToolResult containing the markdown content of the web
page.
btw_tool_web_read_url("https://www.r-project.org/") btw_tool_web_read_url( "https://posit.co/blog/easy-tool-calls-with-ellmer-and-chatlas/" )btw_tool_web_read_url("https://www.r-project.org/") btw_tool_web_read_url( "https://posit.co/blog/easy-tool-calls-with-ellmer-and-chatlas/" )
The btw_tools() function provides a list of tools that can be registered
with an ellmer chat via chat$register_tools() that allow the chat to
interface with your computational environment. Chats returned by
this function have access to the tools:
| Name | Description |
btw_tool_agent_subagent() |
|
| Delegate a task to a specialized assistant that can work independently with its own conversation thread. |
| Name | Description |
btw_tool_cran_package() |
Describe a CRAN package. |
btw_tool_cran_search() |
Search for an R package on CRAN. |
| Name | Description |
btw_tool_docs_available_vignettes() |
List available vignettes for an R package. |
btw_tool_docs_help_page() |
Get help page from package. |
btw_tool_docs_package_help_topics() |
Get available help topics for an R package. |
btw_tool_docs_package_news() |
Read the release notes (NEWS) for a package. |
btw_tool_docs_vignette() |
Get a package vignette in plain text. |
| Name | Description |
btw_tool_env_describe_data_frame() |
Show the data frame or table or get information about the structure of a data frame or table. |
btw_tool_env_describe_environment() |
List and describe items in the R session's global environment. |
| Name | Description |
btw_tool_files_edit() |
Edit a text file using hashline references for precise, targeted modifications. |
btw_tool_files_list() |
List files or directories in the project. |
btw_tool_files_patch() |
Apply a patch envelope that adds, updates, deletes, or moves files atomically. |
btw_tool_files_read() |
Read the contents of a text file. |
btw_tool_files_replace() |
Find and replace exact string occurrences in a text file. |
btw_tool_files_search() |
Search code files in the project. |
btw_tool_files_write() |
Write content to a text file. |
| Name | Description |
btw_tool_git_branch_checkout() |
Switch to a different git branch. |
btw_tool_git_branch_create() |
Create a new git branch. |
btw_tool_git_branch_list() |
List git branches in the repository. |
btw_tool_git_commit() |
Stage files and create a git commit. |
btw_tool_git_diff() |
View changes in the working directory or a commit. |
btw_tool_git_log() |
Show the commit history for a repository. |
btw_tool_git_status() |
Show the status of the git working directory. |
| Name | Description |
btw_tool_github() |
Execute R code that calls the GitHub API using gh(). |
| Name | Description |
btw_tool_ide_read_current_editor() |
Read the contents of the editor that is currently open in the user's IDE. |
| Name | Description |
btw_tool_pkg_check() |
Run comprehensive package checks. |
btw_tool_pkg_coverage() |
Compute test coverage for an R package. |
btw_tool_pkg_document() |
Generate package documentation. |
btw_tool_pkg_load_all() |
Load package code to verify it loads correctly. |
btw_tool_pkg_test() |
Run testthat tests for an R package. |
| Name | Description |
btw_tool_run_r() |
Run R code. |
| Name | Description |
btw_tool_sessioninfo_is_package_installed() |
Check if a package is installed in the current session. |
btw_tool_sessioninfo_package() |
Verify that a specific package is installed, or find out which packages are in use in the current session. |
btw_tool_sessioninfo_platform() |
Describes the R version, operating system, language and locale settings for the user's system. |
| Name | Description |
btw_tool_skill() |
Load a skill's specialized instructions and list its bundled resources. |
| Name | Description |
btw_tool_web_read_url() |
Read a web page and convert it to Markdown format. |
btw_tools(...)btw_tools(...)
... |
Optional names of tools or tool groups to include when registering
tools. By default all btw tools are included. For example, use The names provided can be:
|
Registers the tools with chat, updating the chat object in
place. The chat input is returned invisibly.
# requires an ANTHROPIC_API_KEY ch <- ellmer::chat_anthropic() # register all of the available tools ch1 <- ch$clone() ch1$register_tools(btw_tools()) # or register only the tools related to fetching documentation ch2 <- ch$clone() ch2$register_tools(btw_tools("docs")) # ensure that the current tools persist ch3 <- ch$clone() ch3$register_tools(c(ch3$get_tools(), btw_tools()))# requires an ANTHROPIC_API_KEY ch <- ellmer::chat_anthropic() # register all of the available tools ch1 <- ch$clone() ch1$register_tools(btw_tools()) # or register only the tools related to fetching documentation ch2 <- ch$clone() ch2$register_tools(btw_tools("docs")) # ensure that the current tools persist ch3 <- ch$clone() ch3$register_tools(c(ch3$get_tools(), btw_tools()))
Installs the btw CLI launcher using Rapp::install_pkg_cli_apps().
Rapp is required to build and install the
CLI. See Rapp::install_pkg_cli_apps() for details on where the launcher is
installed and how to manage it.
install_btw_cli(destdir = NULL, ...)install_btw_cli(destdir = NULL, ...)
destdir |
Directory where the CLI launcher will be installed. If |
... |
Arguments passed on to
|
After installing the CLI, you will be offered the option to install the
r-btw-cli skill, which helps AI coding assistants discover and use the
btw CLI. If you decline or are in a non-interactive session, the skill
instructions are copied to the clipboard (or printed) so you can add them
to your CLAUDE.md, AGENTS.md, or other context file manually.
The result of Rapp::install_pkg_cli_apps(), invisibly.
btw_mcp_server() starts an MCP server with tools from btw_tools(), which
can provide MCP clients like Claude Desktop or Claude Code with additional
context. The function will block the R process it's called in and isn't
intended for interactive use.
To give the MCP server access to a specific R session, run
btw_mcp_session() in that session. If there are no sessions configured, the
server will run the tools in its own session, meaning that e.g. the
btw_tools(tools = "env") tools will describe R objects in that R
environment.
btw_mcp_server(tools = NULL) btw_mcp_session()btw_mcp_server(tools = NULL) btw_mcp_session()
tools |
A list of |
Returns the result of mcptools::mcp_server() or
mcptools::mcp_session().
When using btw with a coding agent that already has built-in tools for file operations, code execution, or other tasks, you may want to select a subset of btw's tools to avoid overlap. A recommended lightweight configuration for R package development is:
btw_mcp_server(btw_tools("docs", "pkg"))
This gives the agent access to R documentation (help pages, vignettes, news) and package development tools (testing, checking, documenting) without duplicating file or code execution capabilities the agent may already have.
Depending on your workflow, you may also want to include:
"env": Tools to inspect R objects and data frames in the session
"sessioninfo": Tools to check installed packages and platform details
"cran": Tools to search for and describe CRAN packages
btw_mcp_server(list("docs", "pkg", "env", "sessioninfo", "cran"))
See btw_tools() for a complete list of available tool groups and their
contents.
To configure this server with MCP clients, use the command Rscript and the
args -e "btw::btw_mcp_server()". We recommend customizing the tool set as
described above to avoid overlap with your client's built-in capabilities and
to choose the tools that make the most sense for your workflow.
For Claude Desktop's configuration format:
{
"mcpServers": {
"r-btw": {
"command": "Rscript",
"args": ["-e", "btw::btw_mcp_server(list('docs', 'pkg', 'env', 'sessioninfo', 'cran'))"]
}
}
}
For Claude Code:
claude mcp add -s "user" r-btw -- Rscript -e "btw::btw_mcp_server(list('docs', 'pkg', 'env', 'sessioninfo', 'cran'))"
For Positron or VS Code, add the
following to .vscode/mcp.json (for workspace configuration) or to your
user profile's mcp.json (for global configuration, accessible via Command
Palette > MCP: Open User Configuration):
{
"servers": {
"r-btw": {
"type": "stdio",
"command": "Rscript",
"args": ["-e", "btw::btw_mcp_server(list('docs', 'pkg', 'env', 'sessioninfo', 'cran'))"]
}
}
}
Alternatively, run the MCP: Add Server command from the Command Palette, choose stdio, then choose Workspace or Global to add the server configuration interactively.
For Continue, include the following in your config file:
"experimental": {
"modelContextProtocolServers": [
{
"transport": {
"name": "r-btw",
"type": "stdio",
"command": "Rscript",
"args": [
"-e",
"btw::btw_mcp_server(list('docs', 'pkg', 'env', 'sessioninfo', 'cran'))"
]
}
}
]
}
btw_mcp_server() should only be run non-interactively, as it will block the
current R process once called.
To start a server with btw tools:
btw_mcp_server()
Or to only do so with a subset of btw's tools, e.g. those that fetch package documentation:
btw_mcp_server(btw_tools("docs"))
# alternatively a bare list
btw_mcp_server(list("docs"))
# or a list of btw tools and custom tools
btw_mcp_server(list("docs", my_custom_tool))
To allow the server to access variables in specific sessions, call
btw_mcp_session() in that session:
btw_mcp_session()
These functions use mcptools::mcp_server() and mcptools::mcp_session()
under the hood. To configure arbitrary tools with an MCP client, see the
documentation of those functions.
# btw_mcp_server() and btw_mcp_session() are only intended to be run in # non-interactive R sessions, e.g. when started by an MCP client like # Claude Desktop or Claude Code. Therefore, we don't run these functions # in examples. # See above for more details and examples.# btw_mcp_server() and btw_mcp_session() are only intended to be run in # non-interactive R sessions, e.g. when started by an MCP client like # Claude Desktop or Claude Code. Therefore, we don't run these functions # in examples. # See above for more details and examples.
Create or edit a btw.md or AGENTS.md context file for your project or
user-level configuration. These functions help you set up the context files
that btw_client() and btw_app() use to configure chat clients.
use_btw_md() creates a new context file with a default template. If the
file already exists, it will not overwrite it, but will still ensure the file
is added to .Rbuildignore if you're in an R package.
edit_btw_md() opens an existing context file for editing. Without
arguments, it opens the same file that btw_client() would use by default.
use_btw_md(scope = "project") edit_btw_md(scope = NULL)use_btw_md(scope = "project") edit_btw_md(scope = NULL)
scope |
The scope of the context file. Can be:
For |
use_btw_md() returns the path to the context file, invisibly.
edit_btw_md() is called for its side effect of opening the file.
use_btw_md(): Create a new btw.md or AGENTS.md context file in
the current directory, the project directory or your home directory.
edit_btw_md(): Open an existing btw.md or AGENTS.md context file
for editing.
# Create a project-level btw.md
use_btw_md()
# Create a user-level btw.md
use_btw_md("user")
# Create an AGENTS.md file
use_btw_md("AGENTS.md")
# Edit the context file that btw_client() would use
edit_btw_md()
# Edit a specific context file
edit_btw_md("user")
You can use a btw.md or AGENTS.md file to keep
track of project-specific rules, guidance and context in your project. Either
file name will work, so we'll refer primarily to btw.md. These files are
used automatically by btw_client() and btw_app(): they look first for
btw.md and then for AGENTS.md. If both files are present, only the
btw.md file will be used.
Any time you start a chat client with btw_client() or launch a chat session
with btw_app(), btw will automatically find and include the contents of the
btw.md or AGENTS.md file in the system prompt of your chat. This helps
maintain context and consistency across chat sessions.
Use btw.md to inform the LLM of your preferred code style, to provide
domain-specific terminology or definitions, to establish project
documentation, goals and constraints, to include reference materials such or
technical specifications, or more. Storing this kind of information in
btw.md may help you avoid repeating yourself and can be used to maintain
coherence across many chat sessions.
Write in markdown and structure the file in any way you wish, or use
btw_task_create_btw_md() to help you create a project context file for an
existing project with the help of an AI agent.
You can also use the btw.md file to choose default chat settings for your
project in a YAML front matter block at the top of the file. In this YAML
block you can choose settings for the default ellmer chat client, e.g.
provider, model, as well as choose which btw_tools() to use in
btw_client() or btw_app().
Chat client settings
Use the client field to set options for the chat client. This can be a
single string in provider or provider/model format – as used by
ellmer::chat() – or a list of client options with provider and
model fields, as well as any other options supported by the underlying
ellmer::chat_*() function you choose. Note that provider maps to the
ellmer::chat_*() function, while model maps to the model argument of
that function.
Using ellmer's default model for a provider:
--- client: openai ---
--- client: provider: openai ---
Using a specific model:
--- client: anthropic/claude-4-5-sonnet-latest ---
--- client: provider: anthropic model: claude-4-5-sonnet-latest ---
Using additional client options:
--- client: provider: ollama model: "gpt-oss:20b" echo: output base_url: "http://my-company.example.com:11434" ---
Tool Settings
The top-level tools field is used to specify which btw tools
are included in the chat. This should be a list of tool groups or tool names
(with or without the btw_tool_ prefix). See btw_tools() for a list of
available tools and tool groups.
Here's an example btw.md file:
---
client: claude/claude-4-5-sonnet-latest
tools: [docs, env, files, git, ide, search, session, web]
---
Follow these important style rules when writing R code:
* Prefer solutions that use {tidyverse}
* Always use `<-` for assignment
* Always use the native base-R pipe `|>` for piped expressions
One use-case for btw.md is to provide stable context for an on-going task
that might span multiple chat sessions. In this case, you can use btw.md to
hold the complete project plan, with background information, requirements,
and specific tasks to be completed. This can help maintain continuity across
chat sessions, especially if you update the btw.md file as the project
progresses.
In this use case, however, you might want to hide parts of the project plan from the system prompt, for example to hide completed or future tasks when their description would distract the LLM from the current task.
You can hide parts of the btw.md file from the system prompt by wrapping
them in HTML <!-- HIDE --> and <!-- /HIDE --> comment tags. A single
<!-- HIDE --> comment tag will hide all content after it until the next
<!-- /HIDE --> tag, or the end of the file. This is particularly useful
when your system prompt contains notes to yourself or future tasks that you
do not want to be included in the system prompt.
For project-specific configuration, store your btw.md file in the root of
your project directory. You can even have multiple btw.md files in your
project, in which case the one closest to your current working directory
will be used. This makes it easy to have different btw.md files for
different sub-projects or sub-directories within a larger project.
For global configuration, you can maintain a btw.md file in your home
directory (at btw.md or .config/btw/btw.md in your home directory, using
fs::path_home()). This file will be used by default when a project-specific
btw.md file is not found. Note that btw only looks for btw.md in
your home directory if no project-specific btw.md or AGENTS.md file is
present. It also does not look for AGENTS.md in your home directory.
For an interactive guided setup, consider using btw_task_create_btw_md() to use
an LLM to help you create a btw.md file for your project.
Project context files are discovered automatically and included in
the system prompt by btw_client(). See btw_tools() for a list of
available tools.
# See additional examples in the sections above withr::with_tempdir({ withr::with_tempfile("btw_md_tmp", fileext = ".md", { use_btw_md(btw_md_tmp) }) })# See additional examples in the sections above withr::with_tempdir({ withr::with_tempfile("btw_md_tmp", fileext = ".md", { use_btw_md(btw_md_tmp) }) })