Project skills (open-science-project)¶
The open-science-project plugin is the project-structure component. It gives Claude Code and
Codex seven skills, and hooks, that work on a project made from the
template. It needs git and opsci.
claude plugin install open-science-project@open-science
For Codex: codex plugin add open-science-project@open-science, then restart and review
the hooks with /hooks. See Claude Code and Codex.
Always name the skills in full, for example /open-science-project:new-task (in Codex,
ask for open-science-project:new-task). If your own skills directory (~/.claude/skills/,
or ~/.codex/skills/ for Codex) has a skill with the same short name, the model tends
to pick that one instead; open-science:onboard offers to move such skills to an archive
folder.
| skill | use it to |
|---|---|
open-science-project:new-project |
create a new project from the template |
open-science-project:new-task |
start a task, with or without a plan |
open-science-project:context-files |
keep the context files current and under their line caps |
open-science-project:migrate-project |
move an existing project into the layout without losing a file |
open-science-project:update-from-template |
take framework improvements into a project made from an older template |
open-science-project:private-investigation |
record a side question in a private context file |
open-science-project:notion |
keep a project's Notion mirror in sync; see Notion |
open-science-project:new-project¶
Creates an empty project to start working in. It does not invent research goals, methods or
rules: a slot it was not given content for gets a one-line TODO:.
- It asks for the directory, a short slug, a one-line title and the user's name, and always asks what the project is about (the question, why it matters, the approach, what counts as success, the scope, the key sources). A short answer is fine; any part can be left for later.
- It runs
opsci template instantiate(see Project template and layout), with--no-context-managementunless you use session jumps. - It makes the directory a git repository and commits everything.
- It writes your answer into
PROJECT.mdunder the matching headings, a 3 to 8 line summary intoAGENTS.md§1, and the opening paragraph ofREADME.md. If you named a scratch directory, batch account or notification channel, it copiesconfig/site.example.yamltoconfig/site.local.yamland fills those fields only. - It reports the directory, the framework commit recorded, and every
TODO:left.
It does not create a public repository or add the project to your projects page unless you
ask. It never copies the template over an existing project: use
open-science-project:migrate-project or open-science-project:update-from-template.
open-science-project:new-task¶
A task is a directory, tasks/<id>/. The id is short, lower case, and starts with a
sequence number (t07-mode-fit-v2).
- Design. The agent asks you only the decisions that are yours: the goal, what counts as done, constraints, budget, autonomy level. It proposes one approach and names the alternatives.
- Directory. It runs:
opsci task new <id> --title "<title>" --plan [--depends-on <id>...] [--related <id>...] \
[--supersedes <id>...] [--autonomy autonomous|checkpoints|collaborative] [--hold-at S2 ...]
This writes context.md with a validated node header, log.md, subcontext/ and, with
--plan, plan.md from the plan template. It refuses an id that is not lower case
letters, digits and hyphens, an id that exists, an edge to a node that does not exist,
and --hold-at without --autonomy checkpoints. Without --plan the task has no plan,
which suits small work and explorations.
3. Plan. The agent writes plan.md: goal (a "done" that can be shown false), design
with rejected alternatives, constraints, delegation, one section per subtask (output
directory, what it delivers, steps, gate, what is fatal), and budget. There are no
absolute paths and no job-submission lines in the plan.
4. Context. It fills the task's context.md, adds the task to the project
context.md, runs opsci map build and opsci context check, and commits.
5. Stop. It reports the plan to you and stops. Execution starts when you approve it.
The plan header sets how much the agent does without asking:
autonomy |
the main agent |
|---|---|
autonomous (default) |
runs the whole plan and escalates only fatal problems |
checkpoints |
also stops at each point listed in hold_at |
collaborative |
also asks whenever two readings of the plan would lead to materially different work |
Fatal means: a plan assumption shown false, the budget ceiling would be exceeded, an irreversible action the plan does not cover, missing access, or a result that contradicts the goal.
A brainstorm task lives under brainstorm/tasks/ (opsci task new <id> --root brainstorm)
and is soft-private by default. Its node is part of the project graph, and edges may join it
to project tasks.
When an idea is ready to become project work, the agent creates a new project task that
restates it; it never links to the brainstorm task.
open-science-project:context-files¶
The rule behind it: a fresh session given only AGENTS.md, the project context.md and the
task's tasks/<id>/context.md can take the correct next action without asking anything.
Context files hold what is true now; history goes in the logs, detail in subcontext/.
| file | holds | cap |
|---|---|---|
context.md (project) |
goal, task table, in flight, next step, waiting on the user, open questions | 200 lines |
tasks/<id>/context.md |
node header and the task's goal, current state, in flight, next step, pointers | 200 lines |
tasks/<id>/subcontext/*.md |
one subtask or subagent each | none |
tasks/<id>/log.md, log/YYYY-MM.md |
append-only history | none |
map/README.md |
the project's logic, hand-written | 150 lines |
The same caps apply to brainstorm/context.md and brainstorm/tasks/<id>/context.md.
After every finished subtask the agent answers four questions (contracts/main.md §3):
- Did a task's status or edges change, or did a subtask start, finish, fail or branch?
Update its node header and its
map.md. Did a result land, change or fail? Write or update its file intasks/<id>/results/. A result is something later work will rely on, or something that answers part of the task's goal; a debugging finding goes only in the task'smap.md, unless it matters conceptually. The agent setsmilestone: truewhen the result obviously answers part of the project's question, and asks you when unsure. Runopsci map build, and settle every result it reports as resting on failed or superseded work. - Does the next agent need to know? Update
context.md. - Was a source or package used or consulted? Update
citations/. If a result relies on it, its key goes in that result'suses:; an assumption taken from it is a result of its own (kind: assumption). - Append one line to the task log and one to
log/YYYY-MM.md.
open-science-project:private-investigation¶
For a question you ask on the side that needs real work to answer (reading code or papers, a computation, a test run) but does not advance the project. The agent uses it when you invoke it, and on its own when such a question comes up; a question it can answer quickly it just answers.
The investigation gets its own directory, private-docs/investigations/<YYYY-MM-DD>-<slug>/,
with a context.md holding the question, the state of the work and the answer, and the
scripts and plots it needed. private-docs/ is never exported. The investigation is
soft-private by default: the task's public context.md names the file in backticks and says
when to read it, without stating the question or the findings. A hard-private investigation
is listed under hard_private: in publish/manifest.yaml and is named in no exported
file; private-docs/investigations/README.md indexes all of them. If the answer changes the
project, the agent restates what the task needs in the task's own files.
open-science-project:migrate-project¶
Moves an existing project, ongoing or finished, into the layout without losing a file.
- It works in a git worktree on a new branch, so the original is untouched until you
merge, and records every file with its hash first:
opsci migrate inventory <worktree> -o <scratch>/inventory.json. It lists the files git ignores (data, outputs) with their size and asks whether, after the merge, you want them copied to their new paths or moved. - It instantiates the template into a scratch directory and copies over only the files the
project does not have. It then creates the migration task,
tasks/t00-migration/(soft-private), and registers the session for itscontext.md. That file records the worktree, the inventory, your answers and the next step, and itsplan.mdholds the approved mapping, so a large migration can stop and be taken over by another session withopen-science-context:continue-context. - It proposes a mapping (which directories become tasks; what goes to
src/,data/,paper/,citations/,rules/,archive/; where each ignored file goes; the results each task will record) and waits for your approval before moving anything. Files move withgit mv, so history follows them, and references to old paths are fixed. - It writes a node header per task, a result file for each approved result (with what it
rests on, its figures and code, and the external works it uses), each task's
map.md,map/README.md, the projectcontext.md,PROJECT.mdfrom the project's own descriptions, and one log line, then builds the map and the claims graph. - It runs
opsci migrate compare <scratch>/inventory.json <worktree>, which fails if any file's content is found nowhere (a moved file counts as kept), reports, and asks you to approve the merge. - After the merge it offers to copy or move the ignored files, and to mirror the project
to Notion (
opsci notion enable, thenopsci notion init).
open-science-project:update-from-template¶
Takes framework improvements into a project. It is a diff against the framework commit the project was copied from, applied by hand, never a re-copy. See Updating a project.
Hooks¶
The Claude Code plugin installs three hooks. All act only inside a project made from the
template (a directory holding both AGENTS.md and config/framework.yaml). Without jq,
the line-cap hook does nothing; without python3, the human-verified guard falls back to a
stricter text search of the whole request and the push guard does nothing.
| hook | when | what it does |
|---|---|---|
| line cap | after an agent's Edit or Write | when a context.md is over 200 lines or map/README.md over 150, reports it to the agent as an error with the instruction to prune it now; after a task context edit it reminds the agent of the four questions. Needs jq |
| human-verified guard | before an agent's Edit, Write or NotebookEdit | refuses an edit after which the file sets verification: human-verified more often than before, in any YAML spelling (quotes, escapes, tags, block scalars, anchors); paths are resolved through symlinks. Needs python3; PyYAML, if installed, adds a parse of the front matter |
| public push guard | before an agent's Bash command | refuses a direct push to the public repository (see Publishing). Needs python3 |
Both guard against mistakes; they are not security boundaries. Bash commands are not
checked by the human-verified guard. The publish check is the second line: it refuses a
human-verified node whose verification: line was last changed in an agent's commit.
Codex uses separate adapters for apply_patch, including patches touching several files.
They enforce the same human-verification and line-cap rules, and the same public push guard. Trust the definitions using /hooks.
Shell/custom-tool edits can bypass file checks; run opsci context check and publication
checks as well. Every agent commit includes Agent: claude or Agent: codex.