Almost what you need
Mia, a lab technician, had an AI assistant write a small script last spring. It turns the plate reader's export into the weekly summary: blank-corrected means, a check on how much the triplicates spread, one table for the lab meeting. Then she went on holiday. Jonas found the script, double-clicked it and got a wall of red text. The next week he got it running, but on an export saved with German settings: every value with a decimal comma was read as text and silently skipped. The table looked fine. Three samples were missing.
In a company it's the quality team's monthly returns report. A colleague automated it with a script that works on his laptop only: it needs an add-on nobody else has installed, and it writes over last month's file, so a failed run destroys the only copy.
The script was never the problem. Only its author could run it and check it. In this book you have OpenCode write such a script, check it against an answer you worked out by hand, and hand it over so a colleague can rerun it and trust it without you. You are at Level 2 Power user: the table goes to your team, so a silent error spreads into their work.
After this you can
- Describe a script by its input, steps, output, what it must refuse and a known answer, before any code exists.
- Point OpenCode at your files with
@, get a plan in Plan mode, and answer its questions instead of letting it guess. - Run the script yourself in OpenCode's terminal, check it against your answer, and break it on purpose.
- Give the project an
AGENTS.mdfor the assistant and aREADME.mdfor people, and push it to your group's Gitea. - Keep your sessions findable, and watch a colleague rerun the script from the README alone.
Before you start
- Books: T08-L01 · Start With OpenCode: Set It Up, Change One Line, and Undo It: OpenCode Desktop with the workbench folder, Plan and Build, and the Review panel. For step 17: T19-L02 · Work on a Shared Gitea Repository From Your Computer With OpenCode, which sets up the SSH key that lets OpenCode push to Gitea.
- Python 3 on your computer and your colleague's; step 1 checks it.
- One real export your team processes by hand every week or month, and one colleague who'll rerun the script without you.
- An empty repository on your group's Gitea (or GitHub) for step 17.
- About 110 minutes: 18 to read, 90 to do.
Last verified 25 September 2026. OpenCode Desktop and its model Space Bunny are free. Space Bunny keeps none of your prompts but runs in the US: anything you send or point at with
@goes there. Python is free. Details for experts at the end of this book.
The idea in one page
- Describe the job before the code. Five lines: input (the file and one real row), steps, output, what to refuse, and a known answer.
- The known answer is the whole trick. Take six to eight rows, work out the result by hand, and save both as files. A script that gives confident wrong numbers looks exactly like one that gives right ones. Your hand-worked answer is the only difference, and it lets a colleague check the script in thirty seconds.
- Plan first, then build. In Plan, OpenCode reads your files, asks about anything unclear and describes what it will write, without changing anything. You correct the plan; then Build writes it.
- Three rules make a script safe to share. Standard library only (the tools that come with Python), so nothing needs installing. Refuse, don't skip: a bad row stops the run with its line number. Never overwrite: each run writes a new dated folder.
- Run it yourself. OpenCode's terminal panel is a window for typed commands, inside the app. You run the script there, the way your colleague will.
- Two short files make it handover-ready.
AGENTS.mdtells the next OpenCode session what the project is and which rules must hold.README.mdtells a person how to run and check it.
Watch it once (72 seconds)
No sound. A yellow dot points at each part while the caption explains it. Read the tour as text (opens in a new tab).
Set up (step 1, once per computer)
Step 1: Check that Python is there. In OpenCode, press Ctrl+** (**Cmd+ on a Mac) to open the terminal panel. If that key isn't on your keyboard (on German keyboards it's ^), type /terminal in the message box and press Enter. Type python --version and press Enter (Mac: python3 --version).
You should see: a number starting with 3. If you see not found instead: on Windows, go to python.org/downloads, click Download Python install manager, run it and choose Install (no administrator rights needed); on a Mac, download the installer from the same page. Quit OpenCode completely (on Windows also its icon next to the clock, if there is one), start it again and retry. Close the panel the same way you opened it. Your colleague checks the same on their computer without OpenCode: in File Explorer, right-click an empty area of any folder, choose Open in Terminal, and type the same command.
Worked example: the weekly plate-reader summary
The method is the one from T01-L01 · From Idea to Working Result: The Four-Quadrant Method.
Structure it
Step 2: Write the five lines. Mia writes them before she opens anything:
Input: the plate reader export as it comes: semicolons, decimal comma, columns well;sample;od
Steps: subtract the mean of the blanks; per sample: mean and CV (spread in % of the mean); flag CV above 15 %
Output: a new folder results-<date> with summary.csv; never overwrite
Refuse: a value that isn't a number, a missing column, no blank: stop with the line number
Answer: a small test file and the result worked out by hand
Understand it
Step 3: Work out the answer by hand. Inside your OpenCode workbench folder, create a folder platereader-summary. In Notepad or TextEdit, save these three files there. In Notepad, choose All files so it doesn't add .txt; in TextEdit, first choose Format → Make Plain Text. Press Enter after the last line of each file.
test_input.csv, six sample wells and two blanks, exactly as the plate reader writes them:
well;sample;od
A1;blank;0,050
A2;blank;0,054
B1;A;0,512
B2;A;0,498
B3;A;0,505
C1;B;0,310
C2;B;0,420
C3;B;0,300
expected_output.csv, the answer Mia worked out in a spreadsheet, with CV = STDEV.S / AVERAGE × 100 (German Excel: STABW.S / MITTELWERT): blank mean 0,052; sample A 0,460, 0,446, 0,453, mean 0,453, CV 1,5 %; sample B 0,258, 0,368, 0,248, mean 0,291, CV 22,9 %, flagged:
sample;mean;cv_percent;flag
A;0,453;1,5;no
B;0,291;22,9;yes
broken_input.csv, the same as test_input.csv but with n.d. instead of 0,420 in line 8. The script must refuse it.
For your own export, take six to eight real rows and replace any names or numbers you may not share (see T12-L01 · Decide What You May Paste Into AI at Work). These test files are what OpenCode sees; your real exports stay out of the chat and are only ever read by the script on your computer.
Step 4: Set up Git from the workbench. In your OpenCode workbench session, in Build, send:
Set up Git in the folder platereader-summary so changes there can be tracked and undone.
Create a Git repository inside platereader-summary and keep line endings exactly as they are.
Use the name Mia and the email mia@example.org for commits.
Save the three CSV files as the first version with the message "Test files and hand-worked answer".
Do not change any file, and work only inside platereader-summary.
Use your own name and email. Work only inside platereader-summary matters: without it, in one of our runs OpenCode asked to reach the whole drive for an extra check, and we clicked Deny.

You should see: the three file names and nothing changed. The technical lines can pass. The test and its answer now exist in the history before any code does.
Step 5: Open the folder as its own project. Add platereader-summary with the folder-and-plus icon next to Projects, click it, then New session.

You should see: the branch label main. That means the Review panel and Undo will work here.
Step 6: Point OpenCode at the file with @. Switch to Plan. Type Look at @test_in and pick test_input.csv from the list that appears. Then finish the sentence and send:
Look at @test_input.csv and tell me which character separates the columns and which character is the decimal mark. Show me one row exactly as it is in the file. Do not change anything.


You should see: semicolon and comma. This is the check that would have saved Jonas: it tells you what the file really contains, not what a spreadsheet shows you.
Choose tools
- OpenCode in Plan, then Build, with Space Bunny Free and made-up or public numbers in the chat; for real exports, the model your organisation has set up.
- Python's standard library only, because Jonas has no administrator rights and can't install anything.
- Your group's Gitea for the handover, so Jonas downloads the same version you checked.
Build it: the script
Step 7: Ask for a plan. Still in Plan, send:
Write summarise.py, using only the Python standard library.
Input: a plate reader CSV like test_input.csv: semicolon-separated, decimal comma, columns well;sample;od. Blank wells have the sample name blank.
Steps: subtract the mean of the blanks from every other value; group by sample; mean and coefficient of variation (sample standard deviation divided by the mean, in percent); flag yes if the CV is above 15%, otherwise no.
Output: a new folder results-YYYY-MM-DD next to the input, with summary.csv (sample;mean;cv_percent;flag), mean with 3 decimals, CV with 1, decimal comma. If that folder exists, stop with a message. Never overwrite.
Refuse: a value that isn't a number, a missing column or no blank: stop with the line number and the reason. Never skip a row.
Usage: python summarise.py export.csv
Check: on test_input.csv the result must equal expected_output.csv.
Show me your plan first. Don't create any other files.
Step 8: Answer its questions. After a first draft, OpenCode may stop and ask about anything your description leaves open. Ours asked two things; the last question has Submit instead of Next.

Our sentence "the sample name blank" could mean an empty name. We clicked Type your own answer: Only the word blank in the sample column. An empty sample name is an error: stop with the line number. Then Next.

We chose Stop with an error: refuse, don't skip. The recommended option isn't always yours.

You should see: a plan that uses only standard Python and ends with Nothing has been written. Read the line One default I'm choosing without asking: ours wrote an empty table for a file with blanks but no samples. We wanted an error there too.
Step 9: Let Build write it. Switch to Build (Ctrl+.) and send:
Go ahead: write summarise.py as planned, but if a file has blanks and no samples, stop with an error too. Do not run it: I will run it myself.
You should see: a short summary of what it wrote, including a table of every reason the script stops. If you forget to switch, Plan answers Switch agents and say go; switch and send Go.
Step 10: Read the Review panel. Press Ctrl+Shift+R (or click the rightmost icon at the top right of the session).

You should see: one changed file, summarise.py, and imports that are all part of standard Python. Five files, or a name you don't recognise under import, means it widened the job: ask why.
Step 11: Ask where the three rules live. Close the panel and send:
In summarise.py, show me three places: where the file is read, where a value that is not a number stops the run, and where the output folder is created without overwriting. Give the line numbers and one sentence each. Do not change anything.

You don't need to understand every line of Python. You need to know where your three rules are, so you can point a colleague to them.
Build it: check it yourself
Step 12: Run the three checks in the terminal. Open the terminal panel as in step 1. It opens in the project folder. Running the script here sends nothing to the model; only the chat does. Type each line and press Enter:
python summarise.py broken_input.csv
python summarise.py test_input.csv
cat results-2026-09-25/summary.csv
cat expected_output.csv
Use today's date in the third line; on a Mac, type python3.

You should see: the refusal naming line 8, and two identical tables. Compare them value by value. If one number differs, check your hand calculation first: rounding too early is the usual culprit. In our pictures the terminal is Git Bash; on Windows yours may be PowerShell. These commands work in both; in the old Command Prompt, use type instead of cat.
Step 13: Run it again. Type python summarise.py test_input.csv once more.

You should see: already exists; refusing to overwrite. Today's result is safe from a second, failed run. To check again on the same day, delete that folder first, in File Explorer. Close the terminal panel.
Build it: hand it over
Step 14: Give the next session a project description. Type / in the message box.

Choose /init and press Enter. OpenCode reads the project and writes AGENTS.md, which every later session reads first. It may run the script itself to see what it does; that's fine. Ours asked two questions. The first: should the dated results folders be kept out of Git? The second:

We chose Gitignore results-*/ for the first (the results folders stay out of Git) and Golden, never edit to match for the second: your hand-worked answer is the contract. If a later change breaks the check, the code is wrong, not the answer.

You should see: AGENTS.md and .gitignore in the Review panel, next to summarise.py, which step 15 commits. Read AGENTS.md once: it's written for the assistant, so it's technical, but every rule in it should be one you agreed to.
Step 15: Write the README for people. Send:
Write README.md for a colleague who is not a programmer, in under 15 lines:
how to run it (python summarise.py and the raw export, exactly as the plate reader saves it);
how to check it first (delete today's results folder, run it on test_input.csv, compare with expected_output.csv: they must match);
what makes it stop (and that it then writes nothing); and who to ask: Mia, deputy Jonas.
Update AGENTS.md where it says there is no README.
Then commit everything with the message "Summary script, README and AGENTS.md".

You should see: the commit, and a README that warns against re-saving the export in Excel. OpenCode added that warning itself; it's exactly Jonas's mistake.
Step 16: Name the session. Click ⋯ next to the session title, choose Rename, type Plate summary script and press Enter. OpenCode names sessions after your first message, which is rarely what you'll search for next month.

Step 17: Push it to your group's Gitea. Create an empty repository on Gitea (as in T19-L01 · Keep Your Files in Gitea and Get Any Version Back, but without a README), copy its SSH address, and send:
Our group's Gitea has an empty repository for this: ssh://git@localhost:2222/rna-lab/platereader-summary.git
Add it as origin, update AGENTS.md where it says there is no remote, commit that, and push main.
If Git reports a conflict, stop: don't resolve it yourself. Show me both versions of the lines and who wrote each.
Use your repository's address.

Step 18: Read the README as Jonas will. Open README.md in the Review panel or on Gitea and follow it in your head, line by line. Ours only checked the good file: nothing told Jonas to try broken_input.csv, and nothing kept real exports out of the repository. So we sent:
Jonas will follow the README alone, so add two things to README.md.
Under "Check it first": first run python summarise.py broken_input.csv; it must stop on line 8 and write nothing.
And: keep your real exports outside this folder, so they never end up in Git.
Commit with the message "README: check the refusal too, keep exports outside" and push.
If Git reports a conflict, stop: don't resolve it yourself. Show me both versions of the lines and who wrote each.

You should see: the push, and both additions. OpenCode added on its own that stopping there is a pass, not a fault, so Jonas won't think he broke something.
Step 19: Watch your colleague rerun it. (Jonas's screen.) Jonas is in the group's team on Gitea, so he can open the private repository. He clicks Code → Download ZIP, right-clicks the file in File Explorer and chooses Extract All. Windows often puts the files in a second folder of the same name inside; he opens the folder that contains README.md, right-clicks an empty area and chooses Open in Terminal. Then he follows the README: broken_input.csv, test_input.csv, the comparison.

You should see (on Jonas's computer): the refusal on line 8, then a summary identical to expected_output.csv. We did exactly this from the ZIP in a separate folder: both checks passed. Then Jonas runs this week's real export, kept outside the folder: he types python summarise.py and drags the export file into the terminal window, which inserts its full path. If it stops, the message names the line, and nothing is lost.
Company: the monthly returns report
- Steps 2 and 3: input is the ERP returns export; output a table of returns per product and reason code, flagging products with more than five returns. The test file has seven rows with made-up customer numbers, including one empty reason code.
- Steps 6 to 8: in Plan, "explain the old script; don't change anything" shows it drops rows with an empty reason code, nine returns last month. The new description: an empty code counts as not coded, on its own line.
- Steps 12 and 13: a malformed date stops the run with its line number; the output folder is
returns-YYYY-MM. - Steps 14 to 19: the README names the quality team's deputy; the repository lives on the company's GitHub; a colleague's first real run shows 14 not coded returns, which starts a talk with customer service.
Working with OpenCode day to day
- One session per task, named so you find it again (step 16). Search sessions on the home screen finds old ones by title.
@points at a file; + attaches a picture of an error message./compactshortens a long session so the model stays sharp;/newstarts a fresh one. A new session still knows the project throughAGENTS.md.- The terminal (Ctrl+`) is where you run things. Let OpenCode write and explain; run the checks yourself.
- Commit after every check that passes. Undo helps inside a session; Git helps after it.
What goes wrong
It works on your computer only. Symptom: a colleague gets No module named …. Fix: standard library only, and look at the imports in the Review panel (step 10). Have your colleague run the README check before anyone relies on it.
Rows quietly disappear. Symptom: the summary has fewer samples than the export. Fix: refuse, don't skip. The check with broken_input.csv proves it.
One word, two meanings. Symptom: the plan treats "blank" as an empty name, or your date as a different format. Fix: answer OpenCode's questions (step 8), and when it recommends an option, check it's yours.
The format changed under you. Symptom: decimal commas read as text, or the export was re-saved in Excel. Fix: ask OpenCode about the test file with @ (step 6); open a real export only in Notepad, never save it from Excel, and run the script on it exactly as the device writes it.
The assistant widens the job. Symptom: extra packages, extra files or a rewritten test file. Fix: Plan first, "don't create any other files", one file in the Review panel, and expected_output.csv marked golden in AGENTS.md.
A real export ends up in Git. Symptom: git status or the Review panel lists a file with real data. Fix: keep real exports outside the repository folder (step 18). If one was already pushed, tell whoever runs Gitea; deleting it in a new commit leaves it in the history.
Nothing happens after "go". Symptom: OpenCode answers Switch agents and say go and writes nothing. Fix: you're still in Plan. Press Ctrl+. and send Go.
Do it yourself (90 minutes)
- Set up (5 min): step 1 on your computer and your colleague's.
- Structure it (10 min): your five lines, with one real row as the example (step 2).
- Understand it (25 min): six to eight rows, the answer by hand, and a broken copy (step 3); Git and the project (steps 4 and 5); ask about the raw file with
@(step 6). - Choose tools (5 min): which model; where the repository lives.
- Build it (45 min): steps 7 to 18. Then sit next to your colleague for step 19 and say nothing.
Exit check
A repository on your group's server with the script (standard library only), test_input.csv, expected_output.csv, broken_input.csv, AGENTS.md and a README with how to run it, how to check it, what makes it stop and whom to ask; the history shows the test files before the script. It passes when your colleague, on their own computer and using only the README, gets exactly the expected output and a refusal naming the line of the broken row.
Rule to remember
A script is ready for the team when someone else can check it without you.
Details for experts
Checked on 25 September 2026. You don't need this to follow the book; it's for setting things up or answering a colleague.
| What | Details | What it means for you |
|---|---|---|
| Versions | OpenCode Desktop 2.0.16, Python 3.13 on Windows 11, Gitea 1.27.2. | The current Python is 3.14; anything from 3.10 runs this script. |
| Questions | In Plan (and during /init), OpenCode can stop and ask with options, one marked Recommended, plus Type your own answer. | Its recommendation is a guess about your lab; you decide. |
| Terminal panel | **Ctrl+** or /terminal`; opens in the project folder with your system's shell. OpenCode's own commands run in the background, not in this panel. | What you type here is not seen by the assistant unless you paste it. |
AGENTS.md | Written by /init, read at the start of every session in that project. Keep it short and true; commit it. | It's how a colleague's OpenCode learns your rules. |
| Slash commands | /init, /terminal, /new, /btw (a side question outside the conversation), /export (the session as a file), /compact. | /export makes a record of how the script was built. |
| Sessions | Rename, export or delete under ⋯. Sessions stay on your computer with OpenCode's data. | Name them; delete ones that contain data you shouldn't keep. |
| Line endings | Windows Git converts line endings by default. Step 4 keeps them as they are, so the byte-for-byte check works on every computer. | If the comparison fails only on Windows, this is why. |
| Python rounding | Plain Python rounding can round a half down (1,45 becomes 1,4); the script uses Decimal with half-up, like a spreadsheet. | If you change the script, keep that, or a result can differ from your spreadsheet in the last digit. |
More on the tool in a team: T08-L04 · Use OpenCode Desktop on Your Organisation's Real Repositories.
Further reading and tools
- T08-L01 · Start With OpenCode: Set It Up, Change One Line, and Undo It: the app, Plan and Build, the Review panel and Undo.
- T08-L03 · Write the Spec First, So an AI Assistant Can Change Code Your Team Depends On: when the script grows into code others depend on.
- T19-L02 · Work on a Shared Gitea Repository From Your Computer With OpenCode: SSH key, pull, push and conflicts.
- T10-L02 · Clean a Messy Export Once, So Your Team Can Refresh It: the same kind of export, handled as data work.
- T12-L01 · Decide What You May Paste Into AI at Work: what may go into the chat.
- OpenCode: Taught.
@, Plan, questions, Build, the Review panel, the terminal,/initand sessions. - Git: Taught. The first version before any code, and commits after each check.
- Gitea: Taught. The shared repository and Download ZIP.
- GitHub: Catalogued. The same handover for the company variant.
Latest news
Agentic autofix for code scanning alerts general availability
Agentic autofix for code scanning alerts is now generally available on GitHub. It remediates alerts by working across the codebase the way a developer would: exploring relevant files and proposing a fix.
Email notifications for repository push events have been retired
As of October 15, 2026, GitHub has retired email notifications for repository push events, which are no longer sent. GitHub shut down the feature to help prevent spam and abuse.
HydraFusion updates and new Max option
GitHub announced updates to HydraFusion, including an expanded model pool and improved orchestration workflows, and introduced a new option called HydraFusion Max. Both HydraFusion and HydraFusion Max are available across VS Code, the GitHub Copilot app, and GitHub Copilot.
The FBI just arrested an OpenAI engineer for spying...
Fireship reports that the FBI arrested Abdul Raman Alphazan, a 35-year-old Saudi national and OpenAI engineering lead on the Agents platform, for allegedly bugging the company's executive conference room. According to the criminal complaint, Alphazan used an internal agent to research meeting rooms and capacities, then between September 24 and 30 used his wife's ChatGPT account to learn how to build a Wi-Fi-enabled audio recording device with an encrypted SD card from a $23 Seed Studio microcontroller. He concealed it in toilet paper and plugged it into a USB port behind the TV in the conference room on September 28. OpenAI's technical surveillance countermeasures team found it after about 48 hours; OpenAI says it used its own models to analyze the device, and investigators matched a MAC address to the wife's ChatGPT history and used security footage showing him near the room. He was fired and arrested on October 9 and charged with one count of federal wiretapping. The complaint does not allege espionage or name a principal, but his bio lists him as an investor at a Riyadh VC firm next to a prince whose father is a senior Saudi intelligence official.