# Les 2 — OpenCode Pro
## Lesstof — Rules, Worktrees & Scroll Animations

**Vak:** AI-Assisted Development
**Opleiding:** NOVI Hogeschool Utrecht
**Onderwerp:** OpenCode Desktop professioneel inzetten met regels, config en parallel worktrees

---

## Inhoudsopgave

1. [OpenCode in 2026](#1-opencode-in-2026)
2. [TUI vs Desktop — welke kies je?](#2-tui-vs-desktop)
3. [Plan/Build/@explore + /init](#3-planbuildexplore--init)
4. [`AGENTS.md` — het officiële regelbestand](#4-agentsmd--het-officiele-regelbestand)
5. [`opencode.json` — config & permissies](#5-opencodejson--config--permissies)
6. [Plugins & `opencode-worktree`](#6-plugins--opencode-worktree)
7. [De scroll-animatie stack (Next.js 16)](#7-de-scroll-animatie-stack)
8. [Project setup van A tot Z](#8-project-setup-van-a-tot-z)
9. [Workflow patterns](#9-workflow-patterns)
10. [Bronnen](#10-bronnen)

---

## 1. OpenCode in 2026

OpenCode is een open-source AI coding-IDE. 60.000+ GitHub stars. Gemaakt door SST. Provider-agnostisch — werkt met OpenAI, Anthropic, Google, Groq, lokale modellen via Ollama, en meer.

Vergelijkbaar concept als Cursor of Claude Code, maar:
- **Open source** — geen vendor lock-in
- **Provider-keuze** — niet vast aan één AI-bedrijf
- **Script-vriendelijk** — perfect voor automation, CI/CD, plugins
- **Twee smaken:** Desktop (UI) en TUI (terminal)

### Desktop App (vandaag onze keuze)

Native app voor macOS, Windows, Linux. Download via https://opencode.ai/download.

Layout (globaal):
- **File tree** links — bestanden + folders, right-click voor acties
- **Diff viewer** midden — visueel groen/rood met klik-accept/reject
- **Chat panel** onder — prompts naar de agent
- **Sessions sidebar** links — meerdere parallelle sessies (voor worktrees!)
- **Ingebouwde terminal** — onderaan, optioneel

### TUI (terminal)

```bash
npm i -g opencode-ai@latest
opencode
```

Zelfde engine, zelfde commando's, zelfde plugins. Goed voor SSH, scripts, CI/CD.

---

## 2. TUI vs Desktop — Welke kies je?

| Aspect | TUI | Desktop |
|--------|-----|---------|
| Leercurve | Steiler — alles via keyboard | Vlakker — visueel |
| Diff review | Plain text inline | Visuele diff-viewer |
| Files browsen | Via @-references | File tree zichtbaar |
| Sessies parallel | Tmux / aparte terminals | Sessions sidebar |
| SSH / headless servers | ✅ | ❌ (X-server nodig) |
| Worktree plugin auto-spawn | ✅ (spawnt terminal) | ❌ (handmatige tab) |
| Snel typen / muscle memory | ✅ | Ok, maar trager |
| Scripted workflows | ✅ | Beperkt |

### Wanneer wel TUI?

- **SSH-only servers** — geen X11 nodig
- **CI/CD pipelines** — scripted invocaties
- **Tmux fans** — past in je tmux setup
- **Worktree power-users** — auto-terminal-spawn van de plugin

### Onze keuze voor deze les en eindopdracht: Desktop

Sneller te leren, visueler, beter voor parallel-werken via Sessions sidebar.

---

## 3. Plan/Build/@explore + /init

### Plan vs Build mode

OpenCode heeft twee modes — Tab om te wisselen.

**Plan mode** is read-only. Tools: `read`, `grep`, `glob`, `webfetch`. Geen edits, geen shell commands. Goed voor brainstorm / verkenning.

**Build mode** is default. Alle tools aan. Schrijft code, voert commands uit.

Best practice: begin **altijd** in plan-mode. Laat het uitleggen wat het van plan is. Geef feedback. Pas dan Tab → build.

### Sub-agents

Drie ingebouwde sub-agents:

| Naam | Wat | Wanneer |
|------|-----|---------|
| `@explore` | Read-only verkenning | "Waar staat X?" "Wat is dit?" |
| `@general` | Brede taak-agent | Default voor de meeste taken |
| `@scout` | Gerichte zoekopdracht | "Vind alle plaatsen waar..." |

Manuele aanroep: `@explore vind alle authenticatie code`. Primaire agent kan ze ook autonoom inschakelen.

### `/init` commando

In de chat: `/init`. OpenCode scant je repo, stelt vragen, en genereert/update je `AGENTS.md`.

Doe dit **als eerste actie** in elk nieuw project. Daarna kun je het bestand uitbreiden met jouw specifieke regels.

### Belangrijke keybinds (Desktop én TUI)

| Shortcut | Actie |
|----------|-------|
| `Tab` | Wissel plan ↔ build |
| `Enter` | Submit |
| `Esc` | Cancel |
| `Ctrl+X h` | Help (alle bindings) |
| `Ctrl+D` | Exit (TUI) |

Leader-key voor commando-specifieke bindings: `Ctrl+X`. Customizen via `~/.config/opencode/tui.json` of in Desktop settings.

---

## 4. `AGENTS.md` — Het officiële regelbestand

`AGENTS.md` is markdown in je project-root die OpenCode automatisch in elke context laadt. Officieel format. Expliciet vergeleken in de docs met Cursor's `.cursorrules`.

### Twee locaties

| Pad | Wanneer |
|-----|---------|
| `./AGENTS.md` | Per project (in repo, geversioneerd) |
| `~/.config/opencode/AGENTS.md` | Globaal voor alle projecten |

### Externe regels referencen

```markdown
# Stack rules
@rules/styling.md
@rules/security.md
```

OpenCode laadt deze lazy via z'n Read-tool — pas wanneer relevant.

### Voorbeeld voor scroll-animatie project

```markdown
# Project Rules

## Why this stack
High-end scroll storytelling site (Awwwards/FWA niveau).
GSAP + Lenis = pro standaard — Apple, Stripe, OpenAI, Active Theory,
Locomotive, Darkroom Engineering. Framer Motion is voor app UI, niet voor
scroll storytelling. Kies GSAP voor timing-precisie + GPU-perf.

## Stack
- Next.js 16 (App Router, TypeScript, Turbopack)
- TailwindCSS voor styling
- GSAP 3.15+ (incl. ScrollTrigger, SplitText) met `@gsap/react`
- Lenis 1.3+ (`lenis/react`) voor smooth scroll

## Hard rules
- Geen Framer Motion, react-spring, AOS
- Animaties altijd in Client Components (`"use client"`)
- ScrollTrigger registratie 1x per file
- Animatie-code altijd binnen `useGSAP(() => {}, { scope: ref })`
- Nooit `useEffect` voor GSAP code
- Lenis sync: `gsap.ticker.add` met `autoRaf: false`
- **Async params (Next 16):** altijd `await params` en `await searchParams`

## Patterns
- Eén `<SmoothScroll>` wrapper in `app/layout.tsx`
- Refs i.p.v. globale selectors; scope animaties
- Tailwind voor layout/typografie; GSAP voor transform/opacity
- Geen `transition-*` Tailwind classes op geanimeerde elementen

## Done = 
- Geen hydration warnings
- Werkt in React Strict Mode
- `ScrollTrigger.refresh()` na dynamische content
```

**De `## Why this stack` sectie is cruciaal.** Hiermee snapt de agent *waarom*
we deze keuzes maken — niet alleen *wat*. Resultaat: hij stelt op eigen
initiatief geen Framer Motion meer voor, want hij begrijpt dat we voor scroll
storytelling werken.

### Tips voor goede AGENTS.md

- **Concreet, niet vaag.** "Gebruik clean code" werkt niet. "useGSAP alleen, geen useEffect" wel.
- **Versie-pinning** voor libraries die snel veranderen.
- **Definitie van klaar** — checkpoints die de agent zelf kan toetsen.
- **Anti-patterns expliciet noemen** — "Geen Framer Motion" voorkomt veel discussie.

---

## 5. `opencode.json` — Config & Permissies

### Locaties

| Pad | Scope |
|-----|-------|
| `./opencode.json` | Per project |
| `~/.config/opencode/opencode.json` | Globaal |

### Basis voorbeeld

```json
{
  "$schema": "https://opencode.ai/config.json",
  "model": "openai/gpt-4o-mini"
}
```

Model formaat: `provider/model-id`. Voorbeelden:
- `openai/gpt-4o-mini`
- `openai/gpt-4o`
- `anthropic/claude-sonnet-4`
- `groq/llama-3.3-70b-versatile`

### Permissies

```json
{
  "$schema": "https://opencode.ai/config.json",
  "permission": {
    "bash": {
      "*": "ask",
      "git *": "allow",
      "rm *": "deny"
    },
    "edit": {
      "*": "deny",
      "app/**/*.tsx": "allow",
      "components/**": "allow"
    }
  }
}
```

Drie levels: `allow`, `ask`, `deny`. Glob patterns voor bash commands en file paths.

### Plugin syntax (npm)

```json
{
  "plugin": [
    "@anthropic/some-plugin@1.0.0"
  ]
}
```

OpenCode installeert plugins automatisch via Bun in `~/.cache/opencode/node_modules/` bij het opstarten.

### MCP servers (optioneel)

```json
{
  "mcp": {
    "context7": {
      "type": "local",
      "command": "npx",
      "args": ["-y", "@upstash/context7-mcp"]
    }
  }
}
```

Voor up-to-date library docs binnen je AI-context. Niet vereist voor deze les.

---

## 6. Plugins & `opencode-worktree`

### Wat is `opencode-worktree`?

Plugin van **kdcokenny** (community maker, ook achter `ocx` en `opencode-workspace`).

**Wat doet het?**
Geeft de agent twee nieuwe tools:
- `worktree_create` — maakt nieuwe branch + worktree-folder
- `worktree_delete` — commit changes + cleanup

**Worktree-locatie:**
`~/.local/share/opencode/worktree/<project-id>/<branch>/`

### Installatie via `ocx`

```bash
# Eenmalig: ocx installeren
curl -fsSL https://kdco.dev/ocx/install.sh | sh

# Plugin toevoegen
ocx add kdco/worktree --from https://registry.kdco.dev
```

Restart OpenCode na install.

### Verschil Desktop vs TUI

| Actie | TUI | Desktop |
|-------|-----|---------|
| `worktree_create` aanroepen | ✅ | ✅ |
| `worktree_delete` aanroepen | ✅ | ✅ |
| **Auto nieuw terminal venster** | ✅ | ❌ |
| Nieuwe context openen | Auto | Handmatig (Sessions sidebar) |

In Desktop maakt de plugin de worktree, daarna open je hem zelf in een nieuwe Sessions tab.

### Workflow in Desktop

1. In je hoofd-Session: `Maak een worktree voor feature-hero.`
2. Plugin maakt worktree-folder
3. Klik **+ New Session** in sidebar
4. **Open Folder** → navigate naar de worktree-folder
5. Nu heb je 2 sessies parallel in sidebar — main + feature-hero
6. Klik tussen sessies om te wisselen

### Handmatig alternatief (zonder plugin)

```bash
git worktree add ../mijn-repo-hero -b feature-hero
```

Dan handmatig nieuwe Session openen op die folder.

### Best practices

- Eén opencode-instance per worktree-directory (gouden regel)
- Niet wisselen tussen sessies van verschillende worktrees binnen één session-context (cwd-bug)
- Branch name = folder name (makkelijker zoeken in `git worktree list`)
- Cleanup na merge — niet stapelen

---

## 7. De scroll-animatie stack

### Next.js 16 (mei 2026)

Uitgekomen oktober 2025. **Breaking changes ten opzichte van 15:**

- **Async API's verplicht:** `cookies()`, `headers()`, `params`, `searchParams` zijn nu allemaal async. Altijd `await`:
  ```tsx
  // app/products/[id]/page.tsx
  export default async function Page({ params }: { params: Promise<{ id: string }> }) {
    const { id } = await params;  // VERPLICHT in 16
    return <div>{id}</div>;
  }
  ```
- **Turbopack is default** voor `dev` en `build`. Webpack alleen via opt-in.
- **`middleware.ts` → `proxy.ts`** met nieuwe Node.js runtime.
- **`revalidateTag` vereist 2e argument** (cacheLife profile).
- **Node.js 20.9+** vereist (18 is dropped).

### Waarom GSAP + Lenis?

Dit is **dé** stack voor scroll storytelling op pro-niveau. Niet "een" optie — de standaard.

**Wie gebruikt dit?**
- **Apple** — product pages met scroll-revealed content
- **Stripe** — homepage en product pages
- **OpenAI** marketing pages
- **Awwwards / FWA winnaars** — vrijwel altijd GSAP
- Pro studios: **Active Theory**, **Locomotive**, **Resn**, **Darkroom Engineering** (makers van Lenis)

**Waarom niet Framer Motion?**
- Framer Motion is uitstekend voor **app UI** — modals, page transitions, micro-interacties
- Maar voor **scroll storytelling** (jouw eindopdracht): GSAP heeft betere timing-precisie en GPU-optimalisaties
- Daarom: Framer Motion voor app-werk, GSAP voor scroll-werk

**Andere voordelen:**
- **GSAP sinds januari 2025: 100% gratis** onder de "no charge" license — incl. ScrollTrigger, SplitText, MorphSVG (vroeger premium)
- **Lenis** integreert naadloos met ScrollTrigger via één RAF sync
- Beide zijn **populair op v0 en Cursor** — AI's kennen de patterns goed

Schrijf dit op in je `AGENTS.md` (sectie `## Why this stack`). Dan kiest je AI agent dezelfde keuzes om dezelfde redenen.

### Packages

```bash
npm install gsap @gsap/react lenis
```

**Belangrijk:**
- Pakket heet **`lenis`** (niet meer `@studio-freight/lenis`)
- `@gsap/react` geeft je de officiele `useGSAP` hook

### De `useGSAP` hook

Drop-in vervanger voor `useEffect`/`useLayoutEffect` voor GSAP code. Doet automatisch cleanup via `gsap.context()`. Werkt veilig met React Strict Mode en SSR.

```tsx
"use client";
import { useRef } from "react";
import gsap from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
import { useGSAP } from "@gsap/react";

gsap.registerPlugin(useGSAP, ScrollTrigger);

export default function FadeIn() {
  const ref = useRef<HTMLDivElement>(null);

  useGSAP(() => {
    gsap.from(".fade-item", {
      opacity: 0,
      y: 60,
      duration: 1,
      stagger: 0.15,
      scrollTrigger: {
        trigger: ref.current,
        start: "top 80%",
      },
    });
  }, { scope: ref });

  return (
    <section ref={ref}>
      <h2 className="fade-item text-5xl font-bold">Hello scroll</h2>
      <p className="fade-item">Ik fade in.</p>
    </section>
  );
}
```

### Lenis sync met ScrollTrigger

Zonder sync lopen GSAP en Lenis hun eigen requestAnimationFrame — animaties haperen. Officieel patroon: `autoRaf: false` op Lenis, GSAP's ticker drijft Lenis aan.

```tsx
// components/SmoothScroll.tsx
"use client";
import { ReactLenis, type LenisRef } from "lenis/react";
import { useEffect, useRef } from "react";
import gsap from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";

gsap.registerPlugin(ScrollTrigger);

export default function SmoothScroll({ children }: { children: React.ReactNode }) {
  const lenisRef = useRef<LenisRef>(null);

  useEffect(() => {
    function update(time: number) {
      lenisRef.current?.lenis?.raf(time * 1000);
    }
    gsap.ticker.add(update);
    gsap.ticker.lagSmoothing(0);
    return () => gsap.ticker.remove(update);
  }, []);

  return (
    <ReactLenis root ref={lenisRef} options={{ autoRaf: false, lerp: 0.1 }}>
      {children}
    </ReactLenis>
  );
}
```

In `app/layout.tsx`:

```tsx
import SmoothScroll from "@/components/SmoothScroll";
import "./globals.css";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="nl">
      <body>
        <SmoothScroll>{children}</SmoothScroll>
      </body>
    </html>
  );
}
```

---

## 8. Project setup van A tot Z

### Stap 1 — Next.js 16 project aanmaken

```bash
npx create-next-app@latest scroll-site \
  --typescript --tailwind --app --eslint --no-src-dir --turbopack
cd scroll-site
```

### Stap 2 — Animation dependencies

```bash
npm install gsap @gsap/react lenis
```

### Stap 3 — Git init + first commit

```bash
git init
git add .
git commit -m "init: next 16 + gsap + lenis"
```

### Stap 4 — `AGENTS.md` toevoegen

Plak het voorbeeld uit sectie 4 in `AGENTS.md` in root. Pas aan op jouw project.

### Stap 5 — `opencode.json` toevoegen

```json
{
  "$schema": "https://opencode.ai/config.json",
  "model": "openai/gpt-4o-mini",
  "permission": {
    "bash": {
      "*": "ask",
      "git *": "allow",
      "npm *": "allow",
      "rm *": "deny"
    }
  }
}
```

### Stap 6 — OpenCode Desktop starten

Open OpenCode Desktop → File → Open Folder → `scroll-site`.

In chat: `/init` om je AGENTS.md te valideren.

### Stap 7 — SmoothScroll wrapper bouwen

Vraag in chat:
> Bouw een SmoothScroll wrapper component volgens onze AGENTS.md. Plaats hem in `components/SmoothScroll.tsx` en wrap children in `app/layout.tsx`.

Plan-mode → review → Tab → Build-mode.

### Stap 8 — Eerste worktree

> Maak een worktree voor feature-hero en bouw daar een hero-sectie met een SplitText-reveal op scroll.

Plugin maakt worktree → open nieuwe Sessions tab op die folder → agent bouwt.

---

## 9. Workflow patterns

### Pattern 1 — Plan eerst, dan Build

Begin altijd in **plan-mode**. Laat de agent uitleggen wat het van plan is. Geef feedback. Pas dan Tab → build.

### Pattern 2 — Eén worktree per feature

Werk niet alles in main. Een feature = een worktree = een branch. Makkelijk parallel + makkelijk reviewen via PR.

### Pattern 3 — `AGENTS.md` evolueert

Loop je tegen iets aan dat steeds verkeerd gaat? Voeg toe aan AGENTS.md. Het is een levend document.

### Pattern 4 — `@explore` voor verkenning

Nieuwe codebase of vergeten waar iets staat? `@explore` eerst, dan pas hoofd-agent inzetten. Spaart tokens en geeft jou betere context.

### Pattern 5 — Permissions matchen je risico

Beginnersproject: `bash.*` op `ask`. Productie-werk: alleen specifieke folders editable. Schrijf permissions naar het werk dat je doet.

### Pattern 6 — Sessions sidebar = jouw parallel werk

Eén Session = orchestrator (in main). Worktrees met aparte Sessions = workers. Orchestrator stuurt, workers bouwen. Klik tussen tabs.

---

## 10. Bronnen

### OpenCode officieel
- Hoofdsite: https://opencode.ai
- Download (Desktop): https://opencode.ai/download
- Docs: https://opencode.ai/docs/
- Rules (`AGENTS.md`): https://opencode.ai/docs/rules/
- Config: https://opencode.ai/docs/config/
- Plugins: https://opencode.ai/docs/plugins/
- Agents (sub-agents): https://opencode.ai/docs/agents/
- Modes: https://opencode.ai/docs/modes/
- Commands: https://opencode.ai/docs/commands/
- Permissions: https://opencode.ai/docs/permissions/
- GitHub: https://github.com/sst/opencode
- DeepWiki Desktop apps: https://deepwiki.com/sst/opencode/6.7-desktop-applications

### Plugin ecosystem
- `opencode-worktree`: https://github.com/kdcokenny/opencode-worktree
- `ocx` extension manager: https://github.com/kdcokenny/ocx
- `opencode-workspace` (uitgebreidere variant): https://github.com/kdcokenny/opencode-workspace

### Next.js 16
- Blog post: https://nextjs.org/blog/next-16
- Upgrade guide: https://nextjs.org/docs/app/guides/upgrading/version-16
- create-next-app CLI: https://nextjs.org/docs/app/api-reference/cli/create-next-app

### GSAP
- Docs v3: https://gsap.com/docs/v3/
- React guide (`useGSAP`): https://gsap.com/resources/React/
- License (sinds 2025 gratis): https://gsap.com/standard-license
- ScrollTrigger: https://gsap.com/docs/v3/Plugins/ScrollTrigger/
- SplitText: https://gsap.com/docs/v3/Plugins/SplitText/

### Lenis
- GitHub: https://github.com/darkroomengineering/lenis
- React README: https://github.com/darkroomengineering/lenis/blob/main/packages/react/README.md
- Homepage: https://lenis.darkroom.engineering/

### Combinaties / patterns
- GSAP forum: Next 15/16 best practices: https://gsap.com/community/forums/topic/43831-what-are-the-best-practices-for-using-gsap-with-next-15-clientserver-components/
- Tutorial: Next.js + Lenis + GSAP: https://devdreaming.com/blogs/nextjs-smooth-scrolling-with-lenis-gsap

### Volgende les preview
Les 3: **Introductie Cursor**. De commerciele tegenhanger van OpenCode. Cursor rules vs AGENTS.md, Composer mode, Tab-completion, @-references. Wanneer kies je welke tool?
