PsyCloud

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.

Pre-release install

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:

hello-rt.R
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 verbsfactors(), cross(), repeat_rows(), shuffle(), derive(), filter_rows(), sample_rows(), constrain(), or load rows with trials() / trial_table().
  • screen(id) — open the trial template, then present(stimulus, duration_ms), ask(stimulus, response), feedback(...), and record(...).
  • 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:

PronounMeans
trial$colorthe current trial's value (inside screen())
row$wordthe current design row (inside the pipeline)
outcome$correctresponse correctness/RT/timeout (after a response)
state$streaka phase-scoped counter
const$thresholda 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)
)
See what an expression compiles to

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.

Next