| Title: | Generate Workflow Diagrams from Code Annotations |
|---|---|
| Description: | Provides tools for extracting and processing structured annotations from source files in 30+ programming languages to facilitate workflow visualization. The package scans source files for special 'PUT' annotations that define nodes, connections, and metadata within a data processing workflow. Supports 'R', 'Python', 'SQL', 'JavaScript', 'TypeScript', 'Go', 'Rust', 'Java', and more with automatic comment syntax detection. These annotations can then be used to generate visual representations of data flows and processing steps across polyglot software environments. Builds on concepts from literate programming Knuth (1984) <doi:10.1093/comjnl/27.2.97> and utilizes directed acyclic graph (DAG) theory for workflow representation Foraita, Spallek, and Zeeb (2014) <doi:10.1007/978-0-387-09834-0_65>. Diagram generation powered by 'Mermaid' Sveidqvist (2014) <https://mermaid.js.org/>. |
| Authors: | Philipp Thoss [aut, cre] (ORCID: <https://orcid.org/0000-0002-4672-2792>) |
| Maintainer: | Philipp Thoss <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.2.0 |
| Built: | 2026-10-14 22:31:53 UTC |
| Source: | https://github.com/pjt222/putior |
Converts a file extension to a standardized language name used internally for detection pattern lookup.
ext_to_language(ext)ext_to_language(ext)
ext |
Character string of the file extension (without dot) |
Character string of the language name, or NULL if not supported
Other language-support:
get_comment_prefix(),
get_detection_patterns(),
get_supported_extensions(),
list_supported_languages()
ext_to_language("r") # Returns "r" ext_to_language("py") # Returns "python" ext_to_language("sql") # Returns "sql" ext_to_language("js") # Returns "javascript" ext_to_language("xyz") # Returns NULLext_to_language("r") # Returns "r" ext_to_language("py") # Returns "python" ext_to_language("sql") # Returns "sql" ext_to_language("js") # Returns "javascript" ext_to_language("xyz") # Returns NULL
Returns the single-line comment prefix for a given file extension.
Falls back to # for unknown extensions.
get_comment_prefix(ext)get_comment_prefix(ext)
ext |
Character string of the file extension (without dot) |
Character string of the comment prefix
Other language-support:
ext_to_language(),
get_detection_patterns(),
get_supported_extensions(),
list_supported_languages()
get_comment_prefix("r") # Returns "#" get_comment_prefix("sql") # Returns "--" get_comment_prefix("js") # Returns "//" get_comment_prefix("tex") # Returns "%" get_comment_prefix("xyz") # Returns "#" (fallback)get_comment_prefix("r") # Returns "#" get_comment_prefix("sql") # Returns "--" get_comment_prefix("js") # Returns "//" get_comment_prefix("tex") # Returns "%" get_comment_prefix("xyz") # Returns "#" (fallback)
Returns the detection patterns for identifying inputs, outputs, and dependencies in source code files for a specific programming language.
get_detection_patterns(language = "r", type = NULL)get_detection_patterns(language = "r", type = NULL)
language |
Character string specifying the language. Options: "r", "python", "sql", "shell", "julia", "javascript", "typescript", "go", "rust", "java", "c", "cpp", "matlab", "ruby", "lua", "wgsl" |
type |
Optional character string to filter by detection type. Options: "input", "output", "dependency". If NULL (default), returns all. |
A list of patterns with the following structure:
input: List of patterns for detecting file inputs
output: List of patterns for detecting file outputs
dependency: List of patterns for detecting script dependencies
Each pattern contains:
regex: Regular expression to match the function call
arg_position: Position of the file path argument (1-indexed)
arg_name: Named argument for file path (alternative to position)
description: Human-readable description
Other language-support:
ext_to_language(),
get_comment_prefix(),
get_supported_extensions(),
list_supported_languages()
# Get all R patterns patterns <- get_detection_patterns("r") # Get only input patterns for Python input_patterns <- get_detection_patterns("python", type = "input") # Get dependency patterns for R dep_patterns <- get_detection_patterns("r", type = "dependency")# Get all R patterns patterns <- get_detection_patterns("r") # Get only input patterns for Python input_patterns <- get_detection_patterns("python", type = "input") # Get dependency patterns for R dep_patterns <- get_detection_patterns("r", type = "dependency")
Returns information about available color themes for workflow diagrams.
get_diagram_themes()get_diagram_themes()
Named list describing available themes
Other utilities:
is_valid_put_annotation(),
split_file_list()
# See available themes get_diagram_themes() ## Not run: # Use a specific theme (requires actual workflow data) workflow <- put("./src") put_diagram(workflow, theme = "github") ## End(Not run)# See available themes get_diagram_themes() ## Not run: # Use a specific theme (requires actual workflow data) workflow <- put("./src") put_diagram(workflow, theme = "github") ## End(Not run)
Returns a character vector of all file extensions supported by putior's annotation parsing system.
get_supported_extensions()get_supported_extensions()
Character vector of supported file extensions (without dots)
Other language-support:
ext_to_language(),
get_comment_prefix(),
get_detection_patterns(),
list_supported_languages()
get_supported_extensions()get_supported_extensions()
Test helper function to validate PUT annotation syntax
is_valid_put_annotation(line)is_valid_put_annotation(line)
line |
Character string containing a PUT annotation |
An annotation is valid when every property in it can be read; one that
put() would partly ignore (and warn about) is not.
Logical indicating if the annotation is valid
Other utilities:
get_diagram_themes(),
split_file_list()
is_valid_put_annotation('# put id:"test", label:"Test"') # TRUE is_valid_put_annotation("# put invalid syntax") # FALSEis_valid_put_annotation('# put id:"test", label:"Test"') # TRUE is_valid_put_annotation("# put invalid syntax") # FALSE
Returns a character vector of all programming languages that can have
PUT annotations parsed by putior. Note that detection patterns (for
put_auto) may only be available for a subset of these languages.
list_supported_languages(detection_only = FALSE)list_supported_languages(detection_only = FALSE)
detection_only |
Logical. If TRUE, only return languages with detection pattern support. Default: FALSE |
Character vector of supported language names
Other language-support:
ext_to_language(),
get_comment_prefix(),
get_detection_patterns(),
get_supported_extensions()
# All languages with annotation parsing support list_supported_languages() # Only languages with auto-detection patterns list_supported_languages(detection_only = TRUE)# All languages with annotation parsing support list_supported_languages() # Only languages with auto-detection patterns list_supported_languages(detection_only = TRUE)
Print a putior_theme Object
## S3 method for class 'putior_theme' print(x, ...)## S3 method for class 'putior_theme' print(x, ...)
x |
A |
... |
Additional arguments (ignored). |
The object, invisibly.
Other core-workflow:
print.putior_workflow(),
put(),
put_diagram(),
put_theme(),
summary.putior_workflow()
Displays a concise summary of a putior workflow data frame.
## S3 method for class 'putior_workflow' print(x, ...)## S3 method for class 'putior_workflow' print(x, ...)
x |
A putior_workflow object |
... |
Additional arguments (ignored) |
Invisibly returns x
Other core-workflow:
print.putior_theme(),
put(),
put_diagram(),
put_theme(),
summary.putior_workflow()
Scans source files in a directory for PUT annotations that define workflow nodes, inputs, outputs, and metadata. Supports multiple programming languages with their native comment syntax, including single-line and multiline formats.
put( path, pattern = NULL, recursive = TRUE, include_line_numbers = FALSE, validate = TRUE, exclude = NULL, log_level = NULL )put( path, pattern = NULL, recursive = TRUE, include_line_numbers = FALSE, validate = TRUE, exclude = NULL, log_level = NULL )
path |
Character string specifying the path to the folder containing files, or path to a single file |
pattern |
Regex pattern for filtering files (e.g., |
recursive |
Logical. Should subdirectories be searched recursively? Default: TRUE |
include_line_numbers |
Logical. Should line numbers be included in output? Default: FALSE |
validate |
Logical. Should annotations be validated for common issues? Default: TRUE |
exclude |
Character vector of regex patterns. Files whose full path
matches any pattern are excluded from scanning. Default: NULL (no exclusion).
Example: |
log_level |
Character string specifying log verbosity for this call.
Overrides the global option |
A data frame containing file names and all properties found in annotations.
Always includes columns: file_name, file_type, and any properties found in
PUT annotations (typically: id, label, node_type, input, output).
Annotations without an id get one: a UUID when the uuid package is
installed, otherwise node_1, node_2, and so on.
Valid node_type values: "input", "process" (default),
"output", "decision", "start", "end".
An additional type "artifact" is used internally by put_diagram()
for data file nodes and should not be set manually.
If include_line_numbers is TRUE, also includes line_number.
Note: If output is not specified in an annotation, it defaults to the file name.
PUT annotations work with any language by using the appropriate comment prefix:
Hash (#): R, Python, Shell, Julia, Ruby, Perl, YAML
Dash (–): SQL, Lua, Haskell
Slash (//): JavaScript, TypeScript, C/C++, Java, Go, Rust, Swift, Kotlin, C#
Percent (%): MATLAB, LaTeX
PUT annotations can be written in single-line or multiline format. The comment prefix is determined automatically by file extension.
Single-line format (various languages):
# put id:"node1", label:"Process" # R/Python --put id:"node1", label:"Query" -- SQL //put id:"node1", label:"Handler" // JavaScript
Multiline format: Use backslash (\) for line continuation
# put id:"node1", label:"Process Data", \ # input:"data.csv", \ # output:"result.csv"
Benefits of multiline format:
Compliance with code style guidelines (styler, lintr)
Improved readability for complex workflows
Easier maintenance of long file lists
Better code organization and documentation
Syntax rules:
End lines with backslash (\) to continue
Each continuation line must start with the appropriate comment marker
Properties are automatically joined with proper comma separation
Works with all PUT formats: prefix+put, prefix + put, prefix+put|, prefix+put:
Other core-workflow:
print.putior_theme(),
print.putior_workflow(),
put_diagram(),
put_theme(),
summary.putior_workflow()
## Not run: # Scan a directory for workflow annotations (recursive by default) workflow <- put("./src/") # Scan top-level only (opt out of recursion) workflow <- put("./project/", recursive = FALSE) # Scan a single file workflow <- put("./script.R") # Include line numbers for debugging workflow <- put("./src/", include_line_numbers = TRUE) # Scan JavaScript/TypeScript files workflow <- put("./frontend/", pattern = "\\.(js|ts|jsx|tsx)$") # Scan SQL files workflow <- put("./sql/", pattern = "\\.sql$") # Single-line PUT annotations (various languages): # R/Python: # put id:"load_data", label:"Load Dataset" # SQL: --put id:"query", label:"Execute Query" # JS/TS: //put id:"handler", label:"API Handler" # MATLAB: %put id:"compute", label:"Compute Results" # # Multiline PUT annotations work the same across languages: # # put id:"complex_process", label:"Complex Processing", \ # # input:"file1.csv,file2.csv", \ # # output:"results.csv" # # --put id:"etl_job", label:"ETL Process", \ # -- input:"source_table", \ # -- output:"target_table" ## End(Not run)## Not run: # Scan a directory for workflow annotations (recursive by default) workflow <- put("./src/") # Scan top-level only (opt out of recursion) workflow <- put("./project/", recursive = FALSE) # Scan a single file workflow <- put("./script.R") # Include line numbers for debugging workflow <- put("./src/", include_line_numbers = TRUE) # Scan JavaScript/TypeScript files workflow <- put("./frontend/", pattern = "\\.(js|ts|jsx|tsx)$") # Scan SQL files workflow <- put("./sql/", pattern = "\\.sql$") # Single-line PUT annotations (various languages): # R/Python: # put id:"load_data", label:"Load Dataset" # SQL: --put id:"query", label:"Execute Query" # JS/TS: //put id:"handler", label:"API Handler" # MATLAB: %put id:"compute", label:"Compute Results" # # Multiline PUT annotations work the same across languages: # # put id:"complex_process", label:"Complex Processing", \ # # input:"file1.csv,file2.csv", \ # # output:"results.csv" # # --put id:"etl_job", label:"ETL Process", \ # -- input:"source_table", \ # -- output:"target_table" ## End(Not run)
Functions for automatically detecting workflow elements from code analysis, generating PUT annotation comments, and merging manual with auto-detected annotations.
Analyzes source code files to automatically detect workflow elements including inputs, outputs, and dependencies without requiring explicit PUT annotations. This is similar to how roxygen2 auto-generates documentation skeletons.
put_auto( path, pattern = NULL, recursive = TRUE, detect_inputs = TRUE, detect_outputs = TRUE, detect_dependencies = TRUE, include_line_numbers = FALSE, exclude = NULL, log_level = NULL )put_auto( path, pattern = NULL, recursive = TRUE, detect_inputs = TRUE, detect_outputs = TRUE, detect_dependencies = TRUE, include_line_numbers = FALSE, exclude = NULL, log_level = NULL )
path |
Character string specifying the path to the folder containing files, or path to a single file |
pattern |
Regex pattern for filtering files (e.g., |
recursive |
Logical. Should subdirectories be searched recursively? Default: TRUE |
detect_inputs |
Logical. Should file inputs be detected? Default: TRUE |
detect_outputs |
Logical. Should file outputs be detected? Default: TRUE |
detect_dependencies |
Logical. Should script dependencies (source calls) be detected? Default: TRUE |
include_line_numbers |
Logical. Should line numbers be included? Default: FALSE |
exclude |
Character vector of regex patterns. Files whose full path matches any pattern are excluded from scanning. Default: NULL (no exclusion). |
log_level |
Character string specifying log verbosity for this call.
Overrides the global option |
A data frame in the same format as put(), containing:
file_name: Name of the source file
file_path: Path to the file, as the scan found it
file_type: File extension (r, py, sql, etc.)
id: Auto-generated node identifier (based on file name)
label: Human-readable label (file name without extension)
input: Comma-separated list of detected input files
output: Comma-separated list of detected output files
node_type: Inferred node type (input/process/output)
This format is directly compatible with put_diagram().
put for manual annotation extraction,
put_generate for generating annotation comments,
put_merge for combining manual and auto-detected annotations
Other auto-annotation:
put_generate(),
put_merge()
## Not run: # Auto-detect workflow from a directory workflow <- put_auto("./src/") put_diagram(workflow) # Auto-detect with line numbers workflow <- put_auto("./scripts/", include_line_numbers = TRUE) # Only detect outputs (useful for finding data products) outputs_only <- put_auto("./analysis/", detect_inputs = FALSE) ## End(Not run)## Not run: # Auto-detect workflow from a directory workflow <- put_auto("./src/") put_diagram(workflow) # Auto-detect with line numbers workflow <- put_auto("./scripts/", include_line_numbers = TRUE) # Only detect outputs (useful for finding data products) outputs_only <- put_auto("./analysis/", detect_inputs = FALSE) ## End(Not run)
Generates a Mermaid flowchart diagram from putior workflow data, showing the flow of data through your analysis pipeline.
put_diagram( workflow, output = "console", file = "workflow_diagram.md", title = NULL, direction = "TD", node_labels = "label", show_files = FALSE, show_artifacts = FALSE, show_workflow_boundaries = TRUE, style_nodes = TRUE, theme = "light", palette = NULL, show_source_info = FALSE, source_info_style = "inline", enable_clicks = FALSE, click_protocol = "vscode", artifact_edges = c("replace", "both"), mermaid_config = "classic", accessibility = TRUE, log_level = NULL )put_diagram( workflow, output = "console", file = "workflow_diagram.md", title = NULL, direction = "TD", node_labels = "label", show_files = FALSE, show_artifacts = FALSE, show_workflow_boundaries = TRUE, style_nodes = TRUE, theme = "light", palette = NULL, show_source_info = FALSE, source_info_style = "inline", enable_clicks = FALSE, click_protocol = "vscode", artifact_edges = c("replace", "both"), mermaid_config = "classic", accessibility = TRUE, log_level = NULL )
workflow |
Data frame returned by |
output |
Character string specifying output format. Options:
|
file |
Character string specifying output file path (used when output = "file") |
title |
Character string for diagram title (optional). The drawn
title shows it as written, except when it contains a |
direction |
Character string specifying diagram direction. Options: "TD" (top-down; "TB" is a synonym), "LR" (left-right), "BT" (bottom-top), "RL" (right-left) |
node_labels |
Character string specifying what to show in nodes: "name" (node IDs), "label" (descriptions), "both" (ID: label) |
show_files |
Logical indicating whether to show file connections |
show_artifacts |
Logical indicating whether to show data files as nodes.
When TRUE, every input and output file that is not itself one of the
workflow's scripts gets a node, and each script connects to the files
it writes and reads ( |
show_workflow_boundaries |
Logical indicating whether to apply special styling to nodes with node_type "start" and "end". When TRUE, these nodes get distinctive workflow boundary styling (icons, colors). When FALSE, they render as regular nodes. |
style_nodes |
Logical indicating whether to apply styling based on node_type |
theme |
Character string specifying color theme. Options:
The viridis family themes are perceptually uniform and tested for accessibility. |
palette |
Optional |
show_source_info |
Logical indicating whether to display source file information in diagram nodes. When TRUE, each node shows its originating file name. Default is FALSE for backward compatibility. |
source_info_style |
Character string specifying how to display source info:
|
enable_clicks |
Logical indicating whether to add click directives to nodes.
When TRUE, nodes become clickable links that open the source file in an
editor. The link uses the path the scan recorded ( |
click_protocol |
Character string specifying the URL protocol for clickable nodes:
RStudio has no URL scheme for opening files, so there is no "rstudio" protocol; "rstudio" gives a warning and file:// links. |
artifact_edges |
With |
mermaid_config |
Mermaid configuration to write into the diagram's frontmatter, next to the title:
|
accessibility |
Logical. When TRUE (default), the diagram carries
accessibility metadata that screen readers announce: |
log_level |
Character string specifying log verbosity for this call.
Overrides the global option |
Character string containing the mermaid diagram code
Labels are quoted, and double quotes, | and a # that Mermaid
would read as a character entity (as in #35;) are escaped. So is
text that Mermaid would read as syntax:
the first % of %%{, which starts a directive
that Mermaid removes from the diagram text;
the space in direction LR (or TB, BT,
RL, TD), which Mermaid takes for a direction statement;
on a line where style or classDef comes before it,
a : followed by an escaped character, which would let Mermaid
cut that entity short.
An edge to an id that ends in direction ends with ;. The
escapes are Mermaid entities such as #quot;. Mermaid shows them as
the character in HTML labels.
Where Mermaid 11.17.2 and later draw SVG text instead
(htmlLabels: false for all labels, or
flowchart.htmlLabels: false for edge labels and subgraph titles),
they show the entity as written; Mermaid 11.12.0 can garble it there.
Mermaid still interprets HTML tags such as <br/> and
$$...$$ (KaTeX math) inside labels. So a < followed by a
letter, /, ! or ? starts a tag, and the text up to
the next > disappears (a<b and c>d shows ad); write
< for a < that should show (in math, \lt).
put_diagram() warns about such a <, unless it starts one
of the tags br, b, i, em, strong,
sub, sup, code or span. Their attribute
values need single quotes: double quotes are escaped, and Mermaid then
keeps them in the value, so the attribute has no effect.
Node ids are reduced to letters, digits and underscores. An id that starts
with a digit or is a Mermaid keyword (such as end or class)
gets a node_ prefix. Ids that only differ in punctuation (a-b
and a_b) are kept apart with a numeric suffix and a warning; an id
that is already valid (a_b) keeps its form. With
source_info_style = "subgraph", each source file becomes a subgraph
with the id file_<name>.
Mermaid draws at most 500 edges and 50,000 characters (not counting the
frontmatter and %% comments) by default, and shows an error or a
placeholder instead. Only the page that renders the diagram can raise
these limits (maxEdges, maxTextSize in
mermaid.initialize()); GitHub, GitLab and Quarto keep the
defaults. put_diagram() warns when its output is over either
limit.
The output uses only classic Mermaid syntax, so that every current
renderer draws it. The frontmatter (title and mermaid_config)
needs Mermaid 9.3.0 or later, accTitle/accDescr 9.1.0 or
later (measured). CI draws every diagram option on Mermaid 11.12.0, 11.17.2, 12.1.0
and 12.2.0; 10.9.8 was checked once. Renderers (2026-10-12): GitHub
12.1.0 (measured), Quarto 1.10 and 1.11 11.12.0, GitLab 11.16.1, VS Code
11.17.0, Positron 11.15.0; the pkgdown site and the sandbox load 12.2.0.
Newer syntax such as @{ shape: ... } needs Mermaid 11.3 or
later and is not used while Quarto ships 11.12.0.
Other core-workflow:
print.putior_theme(),
print.putior_workflow(),
put(),
put_theme(),
summary.putior_workflow()
## Not run: # Basic usage - shows only script connections workflow <- put("./src/") put_diagram(workflow) # Show all data artifacts as nodes (complete data flow) put_diagram(workflow, show_artifacts = TRUE) # Show artifacts with file labels on connections put_diagram(workflow, show_artifacts = TRUE, show_files = TRUE) # Show workflow boundaries with special start/end styling put_diagram(workflow, show_workflow_boundaries = TRUE) # Disable workflow boundaries (start/end nodes render as regular) put_diagram(workflow, show_workflow_boundaries = FALSE) # GitHub-optimized theme for README files put_diagram(workflow, theme = "github") # Save to file with artifacts enabled put_diagram(workflow, show_artifacts = TRUE, output = "file", file = "workflow.md") # For use in knitr/pkgdown - returns raw mermaid code # Use within a code chunk with results='asis' # (sep = "": Mermaid reads the frontmatter only at the very start) cat("```mermaid\n", put_diagram(workflow, output = "raw"), "\n```\n", sep = "") # Show source file info inline in nodes put_diagram(workflow, show_source_info = TRUE) # Group nodes by source file using subgraphs put_diagram(workflow, show_source_info = TRUE, source_info_style = "subgraph") # Enable clickable nodes (opens in VS Code) put_diagram(workflow, enable_clicks = TRUE) # Enable clickable nodes with file:// links put_diagram(workflow, enable_clicks = TRUE, click_protocol = "file") # Use a custom color palette my_theme <- put_theme(base = "dark", input = c(fill = "#1a5276", stroke = "#2e86c1", color = "#ffffff")) put_diagram(workflow, palette = my_theme) ## End(Not run)## Not run: # Basic usage - shows only script connections workflow <- put("./src/") put_diagram(workflow) # Show all data artifacts as nodes (complete data flow) put_diagram(workflow, show_artifacts = TRUE) # Show artifacts with file labels on connections put_diagram(workflow, show_artifacts = TRUE, show_files = TRUE) # Show workflow boundaries with special start/end styling put_diagram(workflow, show_workflow_boundaries = TRUE) # Disable workflow boundaries (start/end nodes render as regular) put_diagram(workflow, show_workflow_boundaries = FALSE) # GitHub-optimized theme for README files put_diagram(workflow, theme = "github") # Save to file with artifacts enabled put_diagram(workflow, show_artifacts = TRUE, output = "file", file = "workflow.md") # For use in knitr/pkgdown - returns raw mermaid code # Use within a code chunk with results='asis' # (sep = "": Mermaid reads the frontmatter only at the very start) cat("```mermaid\n", put_diagram(workflow, output = "raw"), "\n```\n", sep = "") # Show source file info inline in nodes put_diagram(workflow, show_source_info = TRUE) # Group nodes by source file using subgraphs put_diagram(workflow, show_source_info = TRUE, source_info_style = "subgraph") # Enable clickable nodes (opens in VS Code) put_diagram(workflow, enable_clicks = TRUE) # Enable clickable nodes with file:// links put_diagram(workflow, enable_clicks = TRUE, click_protocol = "file") # Use a custom color palette my_theme <- put_theme(base = "dark", input = c(fill = "#1a5276", stroke = "#2e86c1", color = "#ffffff")) put_diagram(workflow, palette = my_theme) ## End(Not run)
Analyzes source code files and generates suggested PUT annotation comments based on detected inputs, outputs, and dependencies. This is similar to how roxygen2 generates documentation skeletons.
put_generate( path, pattern = NULL, recursive = TRUE, output = "console", insert = FALSE, style = "multiline", exclude = NULL, log_level = NULL )put_generate( path, pattern = NULL, recursive = TRUE, output = "console", insert = FALSE, style = "multiline", exclude = NULL, log_level = NULL )
path |
Character string specifying the path to a file or directory |
pattern |
Regex pattern for filtering files (e.g., |
recursive |
Logical. Should subdirectories be searched recursively? Default: TRUE |
output |
Character string specifying output destination:
|
insert |
Logical. If TRUE, insert annotations directly into source files at the top. Use with caution. Default: FALSE |
style |
Character string specifying annotation style:
Default: "multiline" |
exclude |
Character vector of regex patterns. Files whose full path matches any pattern are excluded. Default: NULL (no exclusion). |
log_level |
Character string specifying log verbosity for this call.
Overrides the global option |
Invisibly returns a character vector of generated annotations.
Side effects depend on the output parameter.
put_auto for direct workflow detection,
put for extracting existing annotations
Other auto-annotation:
put_auto(),
put_merge()
## Not run: # Print suggested annotations to console put_generate("./analysis.R") # Copy to clipboard for easy pasting put_generate("./scripts/", output = "clipboard") # Generate multiline style annotations put_generate("./src/", style = "multiline") # Insert annotations directly into files (use with caution) put_generate("./new_script.R", insert = TRUE) ## End(Not run)## Not run: # Print suggested annotations to console put_generate("./analysis.R") # Copy to clipboard for easy pasting put_generate("./scripts/", output = "clipboard") # Generate multiline style annotations put_generate("./src/", style = "multiline") # Insert annotations directly into files (use with caution) put_generate("./new_script.R", insert = TRUE) ## End(Not run)
Combines manually written PUT annotations with auto-detected workflow elements, allowing flexible strategies for handling conflicts and supplementing information.
put_merge( path, pattern = NULL, recursive = TRUE, merge_strategy = "manual_priority", include_line_numbers = FALSE, exclude = NULL, log_level = NULL )put_merge( path, pattern = NULL, recursive = TRUE, merge_strategy = "manual_priority", include_line_numbers = FALSE, exclude = NULL, log_level = NULL )
path |
Character string specifying the path to a file or directory |
pattern |
Regex pattern for filtering files (e.g., |
recursive |
Logical. Should subdirectories be searched recursively? Default: TRUE |
merge_strategy |
Character string specifying how to merge:
|
include_line_numbers |
Logical. Should line numbers be included? Default: FALSE |
exclude |
Character vector of regex patterns. Files whose full path matches any pattern are excluded. Default: NULL (no exclusion). |
log_level |
Character string specifying log verbosity for this call.
Overrides the global option |
A data frame in the same format as put(), containing
merged workflow information from both manual and auto-detected sources.
put for manual annotation extraction,
put_auto for auto-detection
Other auto-annotation:
put_auto(),
put_generate()
## Not run: # Merge with manual annotations taking priority workflow <- put_merge("./src/") put_diagram(workflow) # Supplement manual annotations with auto-detected I/O workflow <- put_merge("./scripts/", merge_strategy = "supplement") # Combine all inputs/outputs from both sources workflow <- put_merge("./analysis/", merge_strategy = "union") ## End(Not run)## Not run: # Merge with manual annotations taking priority workflow <- put_merge("./src/") put_diagram(workflow) # Supplement manual annotations with auto-detected I/O workflow <- put_merge("./scripts/", merge_strategy = "supplement") # Combine all inputs/outputs from both sources workflow <- put_merge("./analysis/", merge_strategy = "union") ## End(Not run)
Constructs a custom color palette for use with put_diagram().
Specify colors for any subset of node types; unspecified types inherit
from the base theme.
put_theme( base = "light", input = NULL, process = NULL, output = NULL, decision = NULL, artifact = NULL, start = NULL, end = NULL )put_theme( base = "light", input = NULL, process = NULL, output = NULL, decision = NULL, artifact = NULL, start = NULL, end = NULL )
base |
Character string naming the base theme to inherit from.
Must be one of the valid themes returned by |
input |
Named character vector |
process |
Named character vector |
output |
Named character vector |
decision |
Named character vector |
artifact |
Named character vector |
start |
Named character vector |
end |
Named character vector |
Each node type accepts a named character vector with keys fill,
stroke, and color (text color). All values must be valid
hex colors (e.g., "#1a5276"). Keys you leave out keep the
base theme's value for that node type, and so does the border
width (3px for start and end nodes, 1px for artifacts in most themes).
If you change how light fill is, set color as well, so
the label stays readable.
An object of class putior_theme (a named list of CSS style
strings, one per node type), suitable for passing to
put_diagram(palette = ...).
Other core-workflow:
print.putior_theme(),
print.putior_workflow(),
put(),
put_diagram(),
summary.putior_workflow()
# Override only input node colors, inherit rest from dark theme my_theme <- put_theme(base = "dark", input = c(fill = "#1a5276", stroke = "#2e86c1", color = "#ffffff")) # Full custom palette custom <- put_theme( input = c(fill = "#264653", stroke = "#2a9d8f", color = "#ffffff"), process = c(fill = "#e9c46a", stroke = "#f4a261", color = "#000000"), output = c(fill = "#e76f51", stroke = "#264653", color = "#ffffff")) ## Not run: workflow <- put("./src/") put_diagram(workflow, palette = my_theme) ## End(Not run)# Override only input node colors, inherit rest from dark theme my_theme <- put_theme(base = "dark", input = c(fill = "#1a5276", stroke = "#2e86c1", color = "#ffffff")) # Full custom palette custom <- put_theme( input = c(fill = "#264653", stroke = "#2a9d8f", color = "#ffffff"), process = c(fill = "#e9c46a", stroke = "#f4a261", color = "#000000"), output = c(fill = "#e76f51", stroke = "#264653", color = "#ffffff")) ## Not run: workflow <- put("./src/") put_diagram(workflow, palette = my_theme) ## End(Not run)
Returns the agent definition for ACP discovery. This manifest describes putior's capabilities to other AI agents.
putior_acp_manifest()putior_acp_manifest()
A list containing the agent manifest with name, description, and metadata about capabilities.
Other integration:
putior_acp_server(),
putior_guide(),
putior_help(),
putior_mcp_server(),
putior_mcp_tools()
# Get the agent manifest manifest <- putior_acp_manifest() print(manifest$name) print(manifest$description)# Get the agent manifest manifest <- putior_acp_manifest() print(manifest$name) print(manifest$description)
Starts an ACP (Agent Communication Protocol) REST server that exposes putior as an agent that other AI agents can discover and call.
putior_acp_server( host = "127.0.0.1", port = 8080L, root = getwd(), token = NULL )putior_acp_server( host = "127.0.0.1", port = 8080L, root = getwd(), token = NULL )
host |
Character string specifying the host address. Default: "127.0.0.1" (localhost only) |
port |
Integer specifying the port number. Default: 8080 |
root |
The folder that requests may scan (default: the working directory). A request's relative path is taken from it, and a path outside it, also through a symbolic link, is rejected; a scan skips files that links inside it lead outside to. A request without a path scans this folder. |
token |
|
The ACP server exposes the following endpoints:
Returns the agent manifest for discovery
Execute a putior operation
Get the status/result of a previous run
This function does not return; it runs the server until terminated.
A request can scan only the root folder and what lies
below it, and it sees the file names and labels found there. A path
outside the root is rejected, also when a symbolic link or junction
leads there; a recursive scan skips the files that links inside the
root lead outside to, and refuses a folder with more than 200 such
links. A path with a .. component, control
characters, or a network or device form (\\server\share,
//server/share) is rejected before the disk is touched.
Messages show the root as <root>.
Without a token, the server runs only on a loopback host
(127.x.x.x, localhost, ::1) and answers only
requests addressed to such a name, so that a web page cannot reach
it through DNS rebinding. With host = "0.0.0.0" or another
address, set token.
POST /runs needs Content-Type: application/json,
which a web page cannot send to another site without the server's
consent. A Content-Length over 1 MB is refused (a body sent
in chunks is not limited); on a server that other machines can
reach, use a proxy that limits the request size.
Run IDs are 128 random bits (from the openssl package, which plumber2 needs), so a client cannot guess the ID of another client's run.
The server does not use TLS: across a network, put it behind a proxy that does, or the token travels in clear text.
POST /runs expects a JSON body with this structure:
{
"input": [
{
"role": "user",
"parts": [
{
"content": "scan ./R/ for workflow annotations",
"content_type": "text/plain"
}
]
}
],
"session_id": "optional-session-id"
}
The agent understands natural language requests for:
scan: "Scan ./R/ for PUT annotations"
diagram: "Generate a diagram for ./R/"
auto: "Auto-detect workflow from ./src/"
generate: "Generate annotation suggestions for ./R/"
merge: "Merge manual and auto annotations in ./R/"
help: "Help with annotation syntax"
guide: "What are your capabilities?"
Test the server with curl:
# Discover agents
curl http://localhost:8080/agents
# Execute a scan
curl -X POST http://localhost:8080/runs \
-H "Content-Type: application/json" \
-d '{"input": [{"role": "user", "parts": [{"content": "scan ./R/"}]}]}'
# With a token
curl -X POST http://localhost:8080/runs \
-H "Authorization: Bearer $PUTIOR_ACP_TOKEN" \
-H "Content-Type: application/json" \
-d '{"input": [{"role": "user", "parts": [{"content": "scan ./R/"}]}]}'
putior_acp_manifest for the agent definition,
putior_mcp_server for MCP (Model-to-tool) integration
Other integration:
putior_acp_manifest(),
putior_guide(),
putior_help(),
putior_mcp_server(),
putior_mcp_tools()
## Not run: # Start ACP server on default port putior_acp_server() # Start on custom host/port # Reachable from other machines: needs a token, sent by clients as # "Authorization: Bearer <token>" putior_acp_server(host = "0.0.0.0", port = 9000, root = "~/projects", token = Sys.getenv("PUTIOR_ACP_TOKEN")) ## End(Not run)## Not run: # Start ACP server on default port putior_acp_server() # Start on custom host/port # Reachable from other machines: needs a token, sent by clients as # "Authorization: Bearer <token>" putior_acp_server(host = "0.0.0.0", port = 9000, root = "~/projects", token = Sys.getenv("PUTIOR_ACP_TOKEN")) ## End(Not run)
Provides structured reference documentation for AI coding assistants (Claude Code, GitHub Copilot, etc.) to help users with putior.
putior_guide(topic = NULL, output = c("console", "raw", "clipboard"))putior_guide(topic = NULL, output = c("console", "raw", "clipboard"))
topic |
Character string specifying section. NULL for full content. Options: "quick-start", "syntax", "languages", "functions", "patterns", "examples", or NULL (all) |
output |
Output format: "console" (default), "raw", or "clipboard" |
For step-by-step procedures, see the agent-almanac repository, which provides 6 skills for the complete putior workflow.
Invisibly returns content as character vector. With output="raw", returns as single string.
Other integration:
putior_acp_manifest(),
putior_acp_server(),
putior_help(),
putior_mcp_server(),
putior_mcp_tools()
# Show full guide putior_guide() # Show specific topic putior_guide("quick-start") # Get raw markdown for AI consumption guide_md <- putior_guide(output = "raw")# Show full guide putior_guide() # Show specific topic putior_guide("quick-start") # Get raw markdown for AI consumption guide_md <- putior_guide(output = "raw")
Provides quick-reference help for common putior tasks and syntax. Call without arguments to see available topics.
putior_help(topic = NULL)putior_help(topic = NULL)
topic |
Character string specifying the help topic. Options:
|
Invisibly returns NULL. Prints help content to the console.
Other integration:
putior_acp_manifest(),
putior_acp_server(),
putior_guide(),
putior_mcp_server(),
putior_mcp_tools()
# Show available topics putior_help() # Show annotation syntax putior_help("annotation") # Show supported languages putior_help("languages") # Show available themes putior_help("themes") # Show node types putior_help("node_types") # Show detection patterns info putior_help("patterns") # Show quick examples putior_help("examples") # Show AI assistant guide reference putior_help("guide")# Show available topics putior_help() # Show annotation syntax putior_help("annotation") # Show supported languages putior_help("languages") # Show available themes putior_help("themes") # Show node types putior_help("node_types") # Show detection patterns info putior_help("patterns") # Show quick examples putior_help("examples") # Show AI assistant guide reference putior_help("guide")
Starts an MCP server that exposes putior functions as tools for AI assistants. This enables AI coding assistants (Claude Code, Claude Desktop) to directly call workflow annotation and diagram generation functions.
putior_mcp_server( type = c("stdio", "http"), host = "127.0.0.1", port = 8080L, root = getwd(), token = NULL )putior_mcp_server( type = c("stdio", "http"), host = "127.0.0.1", port = 8080L, root = getwd(), token = NULL )
type |
Character string specifying the transport type:
|
host |
Character string specifying the host for HTTP transport. Default: "127.0.0.1" |
port |
Integer specifying the port for HTTP transport. Default: 8080 |
root |
For HTTP transport: the folder that the tools may scan (default: the working directory). A relative path is taken from it, a path outside it is an error, and a recursive scan skips the files that links inside it lead outside to. Over stdio the client is the local program that started the server, and paths are not limited. |
token |
For HTTP transport: |
The MCP server exposes the following putior functions as tools:
put - Scan files for PUT annotations
put_diagram - Generate Mermaid diagrams
put_auto - Auto-detect workflow from code
put_generate - Generate annotation suggestions
put_merge - Merge manual + auto annotations
get_comment_prefix - Get comment prefix for extension
get_supported_extensions - List supported extensions
list_supported_languages - List supported languages
get_detection_patterns - Get auto-detection patterns
get_diagram_themes - List available themes
putior_guide - AI assistant documentation
putior_help - Quick reference help
set_putior_log_level - Configure logging
is_valid_put_annotation - Validate annotation syntax
split_file_list - Parse file lists
ext_to_language - Extension to language name
Only these tools are served: mcptools' tools for choosing a running R
session (list_r_sessions, select_r_session) are turned off,
so every call runs in the server's own R process.
Over stdio, R warnings would never reach the client. When R warns while
a tool runs (invalid annotations, a < in a title or label, a
diagram over Mermaid's size limits, ...), the tool returns the warnings
as a second text item after its result, at most 20 of them, each cut to
1,000 characters. For put_diagram they are Mermaid comment lines,
so the diagram still renders when a client joins the two items; the
first item is always exactly the Mermaid code. When a call fails, the warnings raised before
the error follow its message.
This function does not return; it runs the MCP server until terminated.
Claude Code (WSL/Linux/macOS):
claude mcp add putior -- Rscript -e "putior::putior_mcp_server()"
Claude Desktop (Windows):
Add to %APPDATA%\Claude\claude_desktop_config.json:
{
"mcpServers": {
"putior": {
"command": "Rscript",
"args": ["-e", "putior::putior_mcp_server()"]
}
}
}
Over stdio nothing below applies: the client is the program that started the server. Over HTTP:
A tool can scan only the root folder and what lies below
it, and returns the file names, labels and annotations found there,
with the same rules as putior_acp_server: a path
outside the root is an error, also through a symbolic link or
junction; a recursive scan skips the files that links inside the
root lead outside to; a path with a .. component, control
characters or a network or device form is rejected. Results and
messages show the root as <root>, and put_diagram
refuses enable_clicks, whose links name files by their path
on the server.
Without a token, the server runs only on a loopback host
and answers only requests addressed to a loopback name, so that a
web page cannot reach it through DNS rebinding; mcptools also
rejects requests from web pages of other origins.
mcptools checks the token and the Host, through options that putior sets. Before serving, the server tests that mcptools refuses requests without the token or from an untrusted Host; if it does not (a version that reads other settings), the server does not start.
mcptools' own settings stay in force: hosts trusted through the
option mcptools.http_trusted_hosts or the environment
variable MCPTOOLS_HTTP_TRUSTED_HOSTS are answered too, and a
secret set through mcptools.http_shared_secret or
plumber2.sharedSecret is required when token is
NULL.
To serve other machines, set token; mcptools then answers
only requests that send it:
# R
putior_mcp_server(type = "http", host = "0.0.0.0", port = 8080,
root = "path/to/project",
token = Sys.getenv("PUTIOR_MCP_TOKEN"))
# Claude Code
claude mcp add --transport http putior http://<server>:8080/ \
--header "Plumber-Shared-Secret: <token>"
The server does not use TLS and mcptools does not limit the request size: across a network, put it behind a proxy that serves HTTPS and limits the size, or the token travels in clear text.
putior_mcp_tools for accessing the tool definitions
Other integration:
putior_acp_manifest(),
putior_acp_server(),
putior_guide(),
putior_help(),
putior_mcp_tools()
## Not run: # Start MCP server with default stdio transport putior_mcp_server() # Start MCP server with HTTP transport, scanning only the current folder putior_mcp_server(type = "http", port = 8080) ## End(Not run)## Not run: # Start MCP server with default stdio transport putior_mcp_server() # Start MCP server with HTTP transport, scanning only the current folder putior_mcp_server(type = "http", port = 8080) ## End(Not run)
Returns a list of ellmer tool definitions for all putior functions that
can be exposed via MCP. This function is primarily used internally by
putior_mcp_server, but can also be used directly for
inspection or custom MCP server implementations.
putior_mcp_tools(include = NULL, exclude = c("run_sandbox"))putior_mcp_tools(include = NULL, exclude = c("run_sandbox"))
include |
Character vector of tool names to include. If NULL (default), all available tools are included. |
exclude |
Character vector of tool names to exclude. Default excludes "run_sandbox" since Shiny apps cannot run via MCP. |
The tools confine scans to a folder only in a server started by
putior_mcp_server(type = "http") (see its Security section). In
a custom server that other programs can reach, they scan any folder
that the R process can read.
A list of ellmer tool definitions suitable for use with
mcptools::mcp_server(). A tool returns its result as text (JSON,
Mermaid code or Markdown); when R warned, it returns a list of two
ellmer::ContentText objects instead: the result and the
warnings.
putior_mcp_server for starting the MCP server
Other integration:
putior_acp_manifest(),
putior_acp_server(),
putior_guide(),
putior_help(),
putior_mcp_server()
## Not run: # Get all putior MCP tools tools <- putior_mcp_tools() # Get specific tools only tools <- putior_mcp_tools(include = c("put", "put_diagram")) # Exclude specific tools tools <- putior_mcp_tools(exclude = c("run_sandbox", "putior_help")) ## End(Not run)## Not run: # Get all putior MCP tools tools <- putior_mcp_tools() # Get specific tools only tools <- putior_mcp_tools(include = c("put", "put_diagram")) # Exclude specific tools tools <- putior_mcp_tools(exclude = c("run_sandbox", "putior_help")) ## End(Not run)
Opens an interactive Shiny application for experimenting with PUT annotations and workflow diagrams. Users can paste or type annotated code, adjust diagram settings, and see real-time diagram generation without installing the package locally.
run_sandbox()run_sandbox()
The sandbox app allows you to:
Enter annotated code with PUT comments
Simulate multiple files using file markers
Customize diagram appearance (theme, direction, etc.)
View extracted workflow data
Copy or download generated Mermaid code
Launches the Shiny app in the default browser. Returns invisibly.
Other interactive:
set_putior_log_level()
## Not run: # Launch the interactive sandbox run_sandbox() ## End(Not run)## Not run: # Launch the interactive sandbox run_sandbox() ## End(Not run)
Configure the logging verbosity for putior functions. Higher verbosity levels provide more detailed information about internal operations, which is useful for debugging annotation parsing, workflow detection, and diagram generation.
set_putior_log_level(level = "WARN")set_putior_log_level(level = "WARN")
level |
Character string specifying the log level:
|
Invisibly returns the previous log level
Other interactive:
run_sandbox()
# Save current level, change, then restore old_level <- set_putior_log_level("DEBUG") getOption("putior.log_level") set_putior_log_level(old_level)# Save current level, change, then restore old_level <- set_putior_log_level("DEBUG") getOption("putior.log_level") set_putior_log_level(old_level)
Parses a comma-separated string of file names into a character vector, trimming whitespace from each entry.
split_file_list(file_string)split_file_list(file_string)
file_string |
Comma-separated file names |
Character vector of individual file names
Other utilities:
get_diagram_themes(),
is_valid_put_annotation()
split_file_list("data.csv, results.rds, plot.png") split_file_list("")split_file_list("data.csv, results.rds, plot.png") split_file_list("")
Provides a structured summary of a putior workflow data frame.
## S3 method for class 'putior_workflow' summary(object, ...)## S3 method for class 'putior_workflow' summary(object, ...)
object |
A putior_workflow object |
... |
Additional arguments (ignored) |
Invisibly returns a list with summary information
Other core-workflow:
print.putior_theme(),
print.putior_workflow(),
put(),
put_diagram(),
put_theme()