SLOPSHOPPER

open-science

Onboarding for the open-science framework: asks which components you want, checks your machine, and sets up tokens safely. Install this first. Also dispatch…

newprocesstimer
★ 6v0.3.4MITupdated 2026-10-07mhycheung/open-science/plugins/open-science
A shopper browsing a rack in a slop shop
README

open-science

The way we do science is changing rapidly, but it is more important than ever to keep science open.

open-science is a framework for doing research in the open (see this blog post for the philosophy behind this):

  • A complete research record. How the methods were developed, the results, the approaches that failed, and the source code, in a public repository and on a project website, with the data archived on Zenodo with a DOI.
  • You decide what goes public, and when. You work in a private repository and can mark any task, file or dataset as private. Nothing is released until you choose to publish. Each release contains only the files you allow, is checked for private material and secrets, and needs your approval.
  • Context management for agentic work. Agents keep a short context file for the project and for each task, so any new session, a collaborator or another researcher can pick up an ongoing project straight away. Optionally, agents also clear their conversation on their own and resume from that file ("session jumps"), so a long session is not resent in full on every turn or after the prompt cache expires, which reduces usage.
  • Work your way. Use plain files and the opsci command yourself, or use the optional Claude Code and Codex plugins. The research record and publication checks are shared.

How a project is organised and published

Start with the tutorial. The documentation covers each part in full, one page per component.

Install

If you use Claude Code, install the plugin and start Claude Code:

claude plugin marketplace add mhycheung/open-science
claude plugin install open-science@open-science
claude

Then type /open-science:onboard. The tutorial says what onboarding does and gives the prompts for the next steps: starting a project, brainstorming, starting a task and using Notion.

For Codex:

codex plugin marketplace add mhycheung/open-science
codex plugin add open-science@open-science
codex

Ask Codex to use open-science:onboard. Restart after installing components and review their hooks with /hooks. See Claude Code and Codex for setup, shared workflows, and the differences in session controls.

If you are not using agents, install the opsci command (pip install "git+https://github.com/mhycheung/open-science#subdirectory=tools", see The opsci command) and follow the pages of the components you want (Components).

Components

The framework has three components. Use any combination; each works without the others, except context management, which needs project management. Project management and publishing are used through opsci and plain files; their Claude Code and Codex plugins are optional. One more plugin, open-science, holds the onboarding skill and the dispatch skill.

#componentwhat it doesneedspages
1project management: the project template and the open-science-project pluginthe layout every project is copied from (description, tasks, map, rules, citations, context files, publish settings), and skills to create a project, start tasks, keep context files under their caps, migrate an old project, take template updates and record side investigations (new-project, new-task, context-files, migrate-project, update-from-template, private-investigation)git, opsciProject template and layout, Project skills
2context management: the open-science-context plugin, for agentsagents keep the context files current and take over a task from them; optionally, they clear their own conversation and resume from those files ("session jumps") (context-management, continue-context, advise-with-context)project management (installed with it), opsci; on Claude Code, a version that runs mods (2.1.287 or later), else Claude Code inside tmux; Codex needs tmux only for session jumpsContext management and session jumps, Working in tmux
3publishing: opsci publish and the open-science-publish plugina private and a public copy of each project; the checked, user-approved export to the public repository; the project website; Zenodo data releases (publish, zenodo-release)git, opsci, a GitHub account; any git repositoryPublishing and the filter, Zenodo releases

On Claude Code, context management does its session jumps through a Claude Code mod, from inside Claude Code, so it needs no tmux. Mods need Claude Code 2.1.287 or later (claude update) and are being switched on for accounts step by step; onboarding checks. Without them, the plugin falls back to typing into the agent's tmux pane, which needs Claude Code to run inside tmux; Working in tmux shows how to set it up, including on a cluster's compute node. Codex needs tmux only for session jumps; see Claude Code and Codex.

Also part of the framework:

partwhat it doespages
opsci commandthe command-line tool behind every step, run by you or by the skills: map build, tasks, context caps, publish, site, Zenodo, notifications, NotionThe opsci command, Notifications, Notion mirror and Feed
open-science pluginthe onboarding skill open-science:onboard; open-science:dispatch, which starts an agent in a new tmux window when you askInstall, Dispatching an agent

Optional extras

Both are in extras/ of the repository, and nothing in the three components depends on them.

extrawherewhatneeds
personal projects pageextras/projects-page/ (no plugin)one page on your personal GitHub site listing your projectsa GitHub Pages site; opsci only to check the file
SLURM resurrectionplugin slurm-resurrect, in extras/slurm-resurrect/for development on a compute node of a computing cluster that uses the SLURM scheduler: when the batch job reaches its time limit, rebuild the tmux session in a new job and resume its Claude Code and Codex sessionsa SLURM cluster, with tmux and Claude Code or Codex running inside a batch job; jq, flock, setsid, sbatch, squeue, scancel

How a project is laid out and published

How to read the figure at the top of this page:

  • Private project repository. Everything is committed here, including drafts, private notes and failed routes. Only files listed under include in publish/manifest.yaml can leave it, and a task directory leaves only if its node header says privacy: public. A soft-private task is left out of the release and the public map but may be mentioned by name; a hard-private task may not appear anywhere in the release. See Project template and layout.
  • The filter. opsci publish check exports one commit, runs every check, and writes a report. If you use an agent, it adds a review of tone and claims. Nothing is pushed until you approve that export by its id. See Publishing and the filter.
  • Public outputs. opsci publish push copies the approved export into the public repository as a new commit, so the private history never reaches it. The public repository builds the project website on GitHub Pages. Data in data/ never goes to the public repository; it can be released on Zenodo with a DOI, after you confirm the release. Your personal projects page links to all three.

What is in this repository

pathwhat
template/the project skeleton that a new project is copied from
plugins/optional Claude Code and Codex plugins: open-science (onboarding) and one per component
extras/the optional extras: the projects page and the slurm-resurrect plugin
tools/the opsci Python package and command line (map build, publish, sync, Zenodo, notify, site)
tests/tests/run_all runs every automated test
docs/the documentation website (mkdocs.yml), one page per component
docs/design/the design report, the original request, the build plan, and the verification results
CHANGELOG.mdwhat each release changed, and how to migrate a project to a new layout

Choices recorded here

  • Command-line name: opsci (short for "open science").
  • Environment: pixi. pixi.toml pins Python ≥3.11 and the test dependencies; pixi.lock records the exact versions. pixi run test runs the tests.

The opsci command

commandwhat
opsci template instantiatecopy the project template into a new directory
opsci task newcreate a task directory, optionally with a plan
opsci map buildbuild the project graph and the list of dead ends from the node headers
opsci context checkcheck the context files against their line caps
opsci publishexport, check and push the public part of a project
opsci sitebuild the project site
opsci zenodorelease data to Zenodo (sandbox by default); see Zenodo releases
opsci notifysend a message, and optionally a file, to the user; see Notifications
opsci notionmirror a project into Notion and post to its Feed; see Notion mirror and Feed
opsci projects-pagecheck the personal projects page
opsci migratecheck that a migration lost no file
opsci guide checkcheck that the user guide is short and names only things that exist

opsci <command> --help gives the options; tools/README.md describes each command.

Licences

Code: MIT (LICENSE). Documentation and other text: CC BY 4.0 (LICENSE-docs).

Source 1 files
hooks/dispatch_mod.js 30 lines
1// open-science dispatch inside Claude Code (a Claude Code mod).
2//
3// A session that open-science:dispatch started with a prompt has OPSCI_DISPATCH_PROMPT set
4// to a file in the state directory that holds the prompt. When the session starts, the mod
5// claims the file (scripts/dispatch.sh claim: print it and remove it, once) and submits the
6// prompt as the user's own words. A file already claimed (by dispatch.sh, which types the
7// prompt into the pane when no mod claims it in time, or by an earlier start of this
8// session) sends nothing, so the prompt is sent once.
9
10export function register(on) {
11  on('session.start', async ($, e, next) => {
12    const file = await $.env.get('OPSCI_DISPATCH_PROMPT')
13    if (file) {
14      // Not for the processes this session starts (a nested agent, a dispatch from here).
15      await $.env.set('OPSCI_DISPATCH_PROMPT', undefined)
16      $.clock.after(0, async () => {
17        let r
18        try {
19          r = await $.process.run(['bash', [$.plugin.root, 'scripts', 'dispatch.sh'].join('/'), 'claim', file], { timeoutMs: 10000 })
20        } catch {
21          return
22        }
23        const text = r.exitCode === 0 ? r.stdout.replace(/\n+$/, '') : ''
24        if (text.trim()) await $.prompt.submit({ text, asUser: true })
25      })
26    }
27    return next(e)
28  })
29}
30