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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

* Added `btw_tool_files_patch()`, a new files tool that applies a structured diff-style patch envelope to make coordinated changes across multiple files in a single call. One patch can add, update, delete, and rename files atomically: all operations are validated before any file is written, so a partial failure leaves the working tree untouched (#190).

* The `btw info` CLI command group has been replaced by three focused top-level commands: `btw system-info` (platform and R session info), `btw check-installed <pkgs>` (check if packages are installed, exits 0 by default with `--fail` for non-zero exit on missing packages), and `btw installed-packages <pkgs>` (show installed package versions). `btw info` is retained as a deprecated stub that prints migration guidance. All three commands support `--json` output with documented field shapes (#195).

* Added two new commands to the `btw` CLI: `btw app` to launch a `btw_app()` session in the current working directory and `btw skills install` to install skills from the terminal.

* Added `btw docs topics <pkg>` to the `btw` CLI for discovering a package's help topics and vignettes. Use `--only help` or `--only vignettes` to limit output to one section, or `--json` for machine-readable output (#195).
Expand Down
145 changes: 100 additions & 45 deletions exec/btw.R
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,16 @@ if (version) {
has_value <- function(x) !is.na(x) && nzchar(x)

btw_json_output <- function(x) {
cat(jsonlite::toJSON(x, auto_unbox = TRUE, pretty = TRUE, na = "null"), "\n")
cat(
jsonlite::toJSON(
x,
auto_unbox = TRUE,
pretty = TRUE,
na = "null",
null = "null"
),
"\n"
)
}

btw_output <- function(x) {
Expand Down Expand Up @@ -227,7 +236,7 @@ btw_pkg_coverage <- function(path, file, json = FALSE) {
}
}

btw_info_platform <- function(json = FALSE) {
btw_system_info <- function(json = FALSE) {
result <- btw:::btw_tool_sessioninfo_platform_impl()
if (json) {
btw_json_output(S7::prop(result, "extra"))
Expand All @@ -236,31 +245,51 @@ btw_info_platform <- function(json = FALSE) {
}
}

btw_info_packages <- function(packages, deps, check, json = FALSE) {
pkgs <- packages
if (check && length(pkgs) > 0) {
if (json) {
results <- lapply(pkgs, function(pkg) {
result <- btw:::btw_tool_sessioninfo_is_package_installed_impl(pkg)
S7::prop(result, "extra")
})
btw_json_output(results)
} else {
for (pkg in pkgs) {
btw_output(btw:::btw_tool_sessioninfo_is_package_installed_impl(pkg))
btw_check_installed <- function(packages, fail = FALSE, json = FALSE) {
results <- lapply(packages, function(pkg) {
tryCatch(
btw:::btw_tool_sessioninfo_is_package_installed_impl(pkg),
error = function(e) e
)
})

errors <- vapply(results, inherits, logical(1), "error")

if (json) {
data <- unname(Map(
function(pkg, r) {
if (inherits(r, "error")) {
list(package = pkg, version = NULL, installed = FALSE)
} else {
extra <- S7::prop(r, "extra")
extra[["installed"]] <- TRUE
extra
}
},
packages,
results
))
btw_json_output(data)
} else {
for (r in results) {
if (inherits(r, "error")) {
cat(cli::ansi_strip(conditionMessage(r)), "\n", file = stderr())
} else {
btw_output(r)
}
}
}

if (fail && any(errors)) quit(status = 1)
}

btw_installed_packages <- function(packages, deps, json = FALSE) {
deps_val <- if (has_value(deps)) deps else ""
result <- btw:::btw_tool_sessioninfo_package_impl(packages, deps_val)
if (json) {
btw_json_output(S7::prop(result, "extra")$data)
} else {
if (length(pkgs) == 0) {
pkgs <- "attached"
}
deps_val <- if (has_value(deps)) deps else ""
result <- btw:::btw_tool_sessioninfo_package_impl(pkgs, deps_val)
if (json) {
btw_json_output(S7::prop(result, "extra")$data)
} else {
btw_output(result)
}
btw_output(result)
}
}

Expand Down Expand Up @@ -420,36 +449,62 @@ switch(
if (pkg_cmd == "") btw_self_help("pkg")
},

#| title: Inspect the R session and environment
#| title: "[Deprecated] Inspect the R session and environment"
info = {
#| description: Output as JSON.
json <- FALSE

switch(
info_cmd <- "",

#| title: Show platform and session info
platform = {
tryCatch(btw_info_platform(json), error = btw_error)
},

#| title: Show installed package information
platform = {},
packages = {
#| description: Package names to query.
`packages...` <- c()
#| description: Dependency types to include.
deps <- ""
#| description: Check if packages are installed.
#| short: 'c'
check <- FALSE

tryCatch(
btw_info_packages(`packages...`, deps, check, json),
error = btw_error
)
}
)
if (info_cmd == "") btw_self_help("info")
cat(
"btw info is deprecated. Use:\n",
" btw system-info (was: btw info platform)\n",
" btw check-installed (was: btw info packages --check)\n",
" btw installed-packages (was: btw info packages)\n",
file = stderr()
)
quit(status = 1)
},

#| title: Show platform and R session info
system_info = {
#| description: "Output as JSON object with fields: r_version, os, system, ui, language, locale, encoding, timezone, date."
json <- FALSE

tryCatch(btw_system_info(json), error = btw_error)
},

#| title: Check if packages are installed
check_installed = {
#| description: Package names to check.
#| required: true
`packages...` <- c()
#| description: Exit with a non-zero status if any package is not installed.
fail <- FALSE
#| description: "Output as JSON array of objects with fields: package (string), version (string or null if not installed), installed (bool)."
json <- FALSE

tryCatch(btw_check_installed(`packages...`, fail, json), error = btw_error)
},

#| title: Show installed package versions
installed_packages = {
#| description: Package names to query.
#| required: true
`packages...` <- c()
#| description: "Dependency types to include. Use TRUE for all types, FALSE for none, or a comma-separated list of types: Depends, Imports, Suggests, LinkingTo, Enhances."
deps <- ""
#| description: "Output as JSON array of objects with fields: package, ondiskversion, loadedversion, path, loadedpath, attached, is_base, date, source, md5ok, library."
json <- FALSE

tryCatch(
btw_installed_packages(`packages...`, deps, json),
error = btw_error
)
},

#| title: Query CRAN package metadata
Expand Down
39 changes: 10 additions & 29 deletions tests/testthat/_snaps/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@
Wraps btw package tools for docs, pkg, info, and cran operations.

Commands:
docs Access R documentation
pkg Work with an R package under development
info Inspect the R session and environment
cran Query CRAN package metadata
skills Manage btw skills
help Show btw CLI usage guide for AI agents
app Run btw_app() in the current directory
docs Access R documentation
pkg Work with an R package under development
info [Deprecated] Inspect the R session and environment
system-info Show platform and R session info
check-installed Check if packages are installed
installed-packages Show installed package information
cran Query CRAN package metadata
skills Manage btw skills
help Show btw CLI usage guide for AI agents
app Run btw_app() in the current directory

Options:
--version / --no-version Print btw version and exit. [default: false]
Expand Down Expand Up @@ -89,28 +92,6 @@

For help with a specific command, run: `btw pkg <command> --help`.

# btw info --help shows info group help

Code
run_btw("info", "--help")
Output
Inspect the R session and environment

Usage: btw info [OPTIONS] <COMMAND>

Commands:
platform Show platform and session info
packages Show installed package information

Options:
--json / --no-json Output as JSON. [default: false] Enable with `--json`.

Global options:
--version / --no-version Print btw version and exit. [default: false]
Enable with `--version`.

For help with a specific command, run: `btw info <command> --help`.

# btw cran --help shows cran group help

Code
Expand Down
Loading
Loading