Nothing
#' Sync AI Assistant Context Files
#'
#' Copies content from the canonical AI assistant file to all other AI files,
#' adding a warning header to non-canonical files.
#'
#' @param config_file Path to configuration file (default: auto-detect settings.yml/settings.yml)
#' @param force Logical; if TRUE, overwrite even if target is newer (default: FALSE)
#' @param verbose Logical; if TRUE (default), show sync messages
#'
#' @return Invisible list with sync results
#'
#' @details
#' This function reads the `ai.canonical_file` setting from settings.yml and
#' copies its content to all other AI assistant instruction files that exist
#' in the project.
#'
#' The canonical file is copied as-is. Non-canonical files receive a warning
#' header indicating they are auto-synced and should not be edited directly.
#'
#' Supported files:
#' \itemize{
#' \item **AGENTS.md** - Cross-platform AI assistants
#' \item **CLAUDE.md** - Claude Code
#' \item **.github/copilot-instructions.md** - GitHub Copilot
#' }
#'
#' @examples
#' \donttest{
#' if (FALSE) {
#' # Sync AI context files
#' ai_sync_context()
#'
#' # Force sync even if targets are newer
#' ai_sync_context(force = TRUE)
#'
#' # Silent sync (for git hooks)
#' ai_sync_context(verbose = FALSE)
#' }
#' }
#'
#' @export
ai_sync_context <- function(config_file = NULL,
force = FALSE,
verbose = TRUE) {
# Validate arguments
checkmate::assert_string(config_file, min.chars = 1, null.ok = TRUE)
checkmate::assert_logical(force, len = 1)
checkmate::assert_logical(verbose, len = 1)
if (is.null(config_file)) {
config_file <- .get_settings_file()
if (is.null(config_file)) {
config_file <- "settings.yml"
}
}
# Check if config exists
if (!file.exists(config_file)) {
if (verbose) {
message("[x] Config file not found: ", config_file)
}
return(invisible(list(success = FALSE, reason = "config_not_found")))
}
# Read configuration
canonical_file <- config("ai.canonical_file", config_file = config_file, default = "")
if (canonical_file == "" || is.null(canonical_file)) {
if (verbose) {
message("Note: No canonical AI file configured")
message(" Set ai.canonical_file in settings.yml to enable sync")
}
return(invisible(list(success = FALSE, reason = "not_configured")))
}
# Check if canonical file exists
if (!file.exists(canonical_file)) {
if (verbose) {
message("[x] Canonical file not found: ", canonical_file)
}
return(invisible(list(success = FALSE, reason = "canonical_not_found")))
}
# Read canonical content
canonical_content <- readLines(canonical_file, warn = FALSE)
# Define all possible AI files
ai_files <- c(
"AGENTS.md",
"CLAUDE.md",
".github/copilot-instructions.md"
)
# Filter to existing files that aren't the canonical
target_files <- ai_files[ai_files != canonical_file & file.exists(ai_files)]
if (length(target_files) == 0) {
if (verbose) {
message("Note: No other AI files to sync")
}
return(invisible(list(success = TRUE, synced = 0)))
}
# Sync each target file
synced_count <- 0
sync_results <- list()
for (target_file in target_files) {
# Check if update needed (unless force = TRUE)
if (!force) {
canonical_mtime <- file.info(canonical_file)$mtime
target_mtime <- file.info(target_file)$mtime
if (!is.na(target_mtime) && target_mtime >= canonical_mtime) {
if (verbose) {
message(" [ok] ", target_file, " (already up to date)")
}
sync_results[[target_file]] <- "up_to_date"
next
}
}
# Create warning header
header <- c(
"<!-- DO NOT EDIT THIS FILE DIRECTLY -->",
"<!-- This file is auto-synced from the canonical source -->",
sprintf("<!-- Canonical file: %s -->", canonical_file),
"<!-- Edit the canonical file and run: framework sync:ai-context -->",
"<!-- Or enable git hooks for automatic sync -->",
""
)
# Combine header + canonical content
new_content <- c(header, canonical_content)
# Write to target
tryCatch({
writeLines(new_content, target_file)
synced_count <- synced_count + 1
sync_results[[target_file]] <- "synced"
if (verbose) {
message(" [ok] Synced to ", target_file)
}
}, error = function(e) {
sync_results[[target_file]] <- paste0("error: ", e$message)
if (verbose) {
message(" [x] Failed to sync ", target_file, ": ", e$message)
}
})
}
if (verbose && synced_count > 0) {
message("\n[ok] Synced ", synced_count, " file(s) from ", canonical_file)
}
invisible(list(
success = TRUE,
canonical = canonical_file,
synced = synced_count,
results = sync_results
))
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.