Skip to content

refactor(config): platform-aware, single-source user config locations#203

Merged
gadenbuie merged 12 commits into
mainfrom
refactor/btw-user-config-sources
Jul 17, 2026
Merged

refactor(config): platform-aware, single-source user config locations#203
gadenbuie merged 12 commits into
mainfrom
refactor/btw-user-config-sources

Conversation

@gadenbuie

@gadenbuie gadenbuie commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

Summary

btw_user_dirs() is now the single, platform-aware source of truth for where btw looks for user-level agents, skills, and config. On Windows it now also searches R's home directory (fs::path_home_r(), typically Documents) in addition to the user profile, since the two can differ; macOS/Linux behavior is unchanged.

User-facing changes:

  • New ?btw-config help page documents every user and project configuration location in one place. btw_client(), use_btw_md()/edit_btw_md(), and the skill-install functions link to it and describe their own relevant locations.
  • use_btw_md("user") now creates ~/.btw/btw.md (the recommended location) instead of the old ~/btw.md. If a ~/btw.md already exists, it offers to migrate it instead of creating a second, shadowed file. ~/btw.md still takes precedence as a config file when present — this asymmetry (loose file wins for config, ~/.btw/ trio wins for skills/agents) is intentional and documented in ?btw-config.
  • If more than one user-level btw.md exists, btw picks the highest-priority one and warns once per session, naming the file in use. edit_btw_md("user") shows a menu of all existing user configs when more than one exists, marking the active one.
  • The legacy skills directory (tools::R_user_dir("btw", "config")/skills) is deprecated: btw still reads it but warns once per session when it actually contains skills. Read support will be removed in btw 1.5.0.

For developers extending this code:

  • btw_user_dirs() (R/utils.R) is the ordered list of user-level directories (agents, skills); iterate it and take the first match.
  • user_config_paths(filename) (R/utils.R) is the ordered list of user-level file candidates for a given filename, including the ~/btw.md-style home-root convenience entries that directories don't have. path_find_user() builds on this — use it rather than re-deriving the search set.
  • btw_user_dir_preferred() (R/utils.R) = btw_user_dirs()[[1]], the single source for "the recommended location to create a new file/dir in." Use this instead of hardcoding ~/.btw.
  • path_home_display() / path_display() (R/utils.R) abbreviate paths against fs::path_home_r() (what R's ~ actually expands to), so user-facing messages showing recommended/active paths stay accurate on Windows.
  • existing_user_btw_md() and maybe_migrate_user_btw_md() (R/edit_btw_md.R) are the building blocks for "does a user config already exist, and should we offer to migrate it" — reuse these rather than re-implementing the shadowing checks if you add another user-scoped file type.

gadenbuie added 10 commits July 9, 2026 16:12
Resolve the user-level config trio under both fs::path_home() and
fs::path_home_r() so Windows honors R's home directory for agents and
skills, matching the existing btw.md config-file search. macOS/Linux
entries collapse via unique(), leaving behavior unchanged.
Warn once per session when the btw <= 1.2.0 skills location
(R_user_dir("btw", "config")/skills) actually contains skills, pointing
users to ~/.btw/skills. The legacy directory is still read; read support
will be removed in btw 1.5.0.
Add a user-visible ?btw-config reference documenting all project and
user configuration locations, and update btw_client(), use_btw_md(), and
the skill functions to describe their own locations completely and link
to it. Clarify the discover_agent_md_files() priority comment.
Address review finding on the docs/behavior mismatch for user-level
btw.md. use_btw_md("user") now creates ~/.btw/btw.md and offers to
migrate an existing ~/btw.md rather than creating a shadowed file. A
loose ~/btw.md still takes precedence when loading; path_find_user()
warns once per session when more than one user-level btw.md is found.
Documentation across btw-config, btw_client(), and use_btw_md() updated
to describe this precedence accurately.
Convert the message-content assertions for use_btw_md("user") and the
multiple-config warning to snapshot tests. Add path_home_display() to
render home-relative paths without requiring them to exist, so the
migration advisory and warning show ~/... paths (deterministic in
snapshots and tidier for users).
use_btw_md("user") and edit_btw_md("user") only reasoned about ~/btw.md
and ~/.btw/btw.md, while the loader searches the full ordered set. This
could create a shadowing ~/.btw/btw.md over an active config in
~/.config/btw/, R_user_dir, or (Windows) R's home root, and the
"already exists" hint pointed at edit_btw_md("user") which actually
opened the higher-priority ~/btw.md.

- Add user_config_paths() as the single ordered source; path_find_user()
  builds on it. Add existing_user_btw_md() returning all existing
  user-level btw.md in priority order.
- use_btw_md("user") creates ~/.btw/btw.md only when no user config
  exists anywhere; otherwise offers to migrate/consolidate the active
  file. maybe_migrate_user_btw_md() no longer clobbers an existing
  recommended file.
- edit_btw_md("user") presents a menu of existing configs, marking the
  one read by btw_client()/btw_app() and nudging consolidation.
- Add local_user_home() test isolation plus cases for non-loose
  migration, no-clobber, and the edit menu; update snapshots and docs.
path_home_display()/path_display() abbreviated ~ against fs::path_home()
(user profile), but R expands ~ via fs::path_home_r(). On Windows those
differ, so a recommended path printed as ~/.btw/btw.md pointed at a
different file than the one created/migrated, risking another shadowed
config. Same defect in the legacy-skills warning.

- Add btw_user_dir_preferred() = btw_user_dirs()[[1]] as the single
  source for the recommended user dir; use it in use_btw_md("user"),
  edit_btw_md("user"), warn_multiple_user_config(), and the legacy
  skills warning instead of hardcoding fs::path_home(".btw").
- Abbreviate ~ against fs::path_home_r() so profile-only paths render
  natively rather than as a misleading ~. macOS/Linux unchanged.
- Add unit tests for btw_user_dir_preferred() and path_home_display().
Address test-review findings:

- Route identical-home-root tests through local_user_home() and pin
  R_USER_DATA_DIR in distinct-root tests so tools::R_user_dir() no longer
  resolves to the developer's real user dir (removes contamination risk
  and the implementation-mirror in the btw_user_dirs() expectations).
- Add branch coverage for maybe_migrate_user_btw_md() decline and
  resolve_user_btw_md_for_edit() cancelled-selection paths.
- Consolidate the legacy-skill-dir warning test into a single captured
  warning asserted for both message parts.
@gadenbuie
gadenbuie marked this pull request as ready for review July 9, 2026 23:29
@gadenbuie gadenbuie added this to the v1.3.1 milestone Jul 17, 2026
@gadenbuie
gadenbuie merged commit af88d61 into main Jul 17, 2026
9 checks passed
@gadenbuie
gadenbuie deleted the refactor/btw-user-config-sources branch July 17, 2026 19:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant