R SDK (psycloudr)
psycloudr brings PsyCloud authoring to R with a |>-friendly builder. Like the Python SDK, it
compiles to the same bundle format Studio uses, so an R-authored study runs on the same
runtime and can be opened in Studio.
psycloudr is under active development (0.0.0.9000) and not yet on CRAN. Install it from the
monorepo:
# install.packages("remotes")
remotes::install_github("bbuchsbaum/psycloud", subdir = "packages/psycloudr")A few workbench helpers (preview, simulate) also expect the psycloud CLI on your PATH. Core
authoring and write_bundle() do not.
A complete example
This builds a minimal reaction-time study — instructions, a colored circle that appears after a fixation cross, an any-key response — and compiles it to a bundle:
library(psycloudr)
bundle <- experiment(id = "hello.rt", name = "Hello, psycloudr") |>
instructions(markdown(
"# Reaction Time\n\nPress any key the moment the circle appears.\n\nPress any key to begin."
)) |>
phase("main", label = "Trials") |>
factors(color = c("tomato", "steelblue")) |>
cross() |>
repeat_rows(3) |>
shuffle(seed = seed_per_participant("hello-rt")) |>
screen("trial") |>
present(fixation_cross(x = "center", y = "center", size = 40), 700) |>
ask(
circle(x = "center", y = "center", radius = 60, fill = trial$color),
anykey()
) |>
record(color) |>
end_screen(markdown("# Done\n\nThanks for playing!")) |>
bundle(with_auto_ids = TRUE)The fluent pipeline
The pipeline reads as a sequence of verbs joined by |>:
experiment(id, name)— start the study.instructions(...)/end_screen(...)— full-screen pages before/after the task.phase(id, label)— open a trial phase.- Design verbs —
factors(),cross(),repeat_rows(),shuffle(),derive(),filter_rows(),sample_rows(),constrain(), or load rows withtrials()/trial_table(). screen(id)— open the trial template, thenpresent(stimulus, duration_ms),ask(stimulus, response),feedback(...), andrecord(...).bundle(with_auto_ids = TRUE)— validate and compile.
Stimulus helpers include text(), markdown(), image(), circle(), fixation_cross(), and
blank(); response helpers include keypress(), anykey(), slider(), and prompt(). There
are also higher-level "design intent" wrappers — hypothesis(), within_subjects(),
between_subjects(), measures() — and low-level pc_* constructors for advanced use.
Dynamic values: the expression DSL
R operators are overloaded so you can write expressions naturally; they compile to PsyCloud's runtime expression format. Reference values through pronouns:
| Pronoun | Means |
|---|---|
trial$color | the current trial's value (inside screen()) |
row$word | the current design row (inside the pipeline) |
outcome$correct | response correctness/RT/timeout (after a response) |
state$streak | a phase-scoped counter |
const$threshold | a study-level constant |
Derived columns and conditionals use case_when() and expr_if(); for anything the DSL doesn't
cover, drop to a raw expression string with expr():
# A derived "correct key" column, computed while building the trial table
derive("correctKey", case_when(
row$word == "red" ~ "r",
row$word == "green" ~ "g",
.default = "b"
))
# Conditional feedback text at run time
feedback(
text(expr('if(outcome.correct, "Correct", "Wrong")'),
font_size = 40, x = "center", y = "center"),
timeout(400)
)expr_source(trial$word) prints the compiled form ("trial.word") — handy when debugging a
binding or constraint.
Inspect, write, and deploy
# Inspect before shipping
psycloud(bundle) # inline preview widget (RStudio viewer)
summary(bundle) # structural summary
preview_trials(bundle) # the materialized trial table
validate_bundle(bundle) # schema validation
lint_bundle(bundle)$counts
# Write the bundle directory to disk
write_bundle(bundle, dir = "hello_rt_bundle", overwrite = TRUE)write_bundle() emits bundle.json, designProgram.json, screenProgram.json, and
bindings.json — the same layout the CLI and Studio
read. To publish to a hosted server, set PSYCLOUD_SERVER_URL / PSYCLOUD_API_KEY, create a
study with pc_create_study(), and push with pc_push().
Worked examples
The package ships runnable studies under packages/psycloudr/inst/examples/high-level/
(including word-stroop, simple-rt, recognition-memory, luck-vogel-1997, and
design-first-memory) plus vignettes — among them a set of jsPsych → psycloudr mappings
(Stroop, SRT, recognition memory, adaptive, and more) that are ideal if you're migrating.