Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 63 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,69 @@ jobs:
path: ~/.bun/install/cache
key: bun-${{ runner.os }}-${{ hashFiles('bun.lock') }}
- run: bun install --frozen-lockfile
- run: bun dev/screenshots.ts ${{ matrix.wallpaper }}
- if: failure()
# Compares fresh renders with the published ones on the assets branch. A changed scene only warns: its renders
# are uploaded for review, and the publish job below puts them on the assets branch once the change is on main.
- id: compare
continue-on-error: true
run: bun dev/screenshots.ts ${{ matrix.wallpaper }}
- if: steps.compare.outcome == 'failure'
run: echo "::warning title=Screenshots changed::${{ matrix.wallpaper }} renders differently from the README; they publish automatically once on main. See the fresh-screenshots-${{ matrix.wallpaper }} artifact."
- if: steps.compare.outcome == 'failure'
uses: actions/upload-artifact@v7
with:
name: fresh-screenshots-${{ matrix.wallpaper }}
path: dev/out/${{ matrix.wallpaper }}-*-45s.png
path: dev/out/screenshots/

# Commits the changed screenshots to the assets branch, which the README's images point at.
publish:
needs: screenshots
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v7
with:
ref: assets
- uses: actions/download-artifact@v8
with:
pattern: fresh-screenshots-*
merge-multiple: true
- run: |
git add -A
git diff --cached --quiet && exit 0
git -c user.name="github-actions[bot]" -c user.email="41898273+github-actions[bot]@users.noreply.github.com" commit -m "Update screenshots for ${GITHUB_SHA::7}"
git push

# Updates the release branch that `opencode plugin add vaprdev/opencode-wallpapers#release` installs: the built plugin
# with a package.json that has no build scripts, so installing doesn't build it, and no sources, dev tools or images.
release:
needs: [build, check]
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v7
with:
ref: release
path: release
- uses: oven-sh/setup-bun@v2
with:
bun-version: 1.3.14
- uses: actions/cache@v6
with:
path: ~/.bun/install/cache
key: bun-${{ runner.os }}-${{ hashFiles('bun.lock') }}
- run: bun install --frozen-lockfile
- run: bun run build
- working-directory: release
run: |
git rm -rq --ignore-unmatch .
cp -R ../dist ../README.md ../LICENSE ../CHANGELOG.md .
jq 'del(.scripts, .devDependencies)' ../package.json > package.json
git add -A
git diff --cached --quiet && exit 0
git -c user.name="github-actions[bot]" -c user.email="41898273+github-actions[bot]@users.noreply.github.com" commit -m "Release ${GITHUB_SHA::7}"
git push
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
node_modules
dev/out
dist
# The assets branch, checked out by dev/assets.ts
screenshots/
36 changes: 31 additions & 5 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -347,9 +347,9 @@ bun dev/pixel-check.ts [id] [activity] [time] # real-pixel mode against a mo
bun dev/poke.ts <id> [activity] [time] <fx> <fy> [seconds...] # click at a point (fractions of the screen)
bun dev/fade.ts <id>:day <id>:night 50 # a frame halfway through a crossfade, and its cost
bun dev/gif.ts <id> [activity] [time] # a looping GIF at 3x speed in dev/out
bun run screenshots # fails if the README gallery is out of date
bun run screenshots:update # re-renders it (teeming at 45 s)
bun dev/gif.ts all # re-renders the README's GIFs
bun run screenshots # fails if the README gallery differs from the published one
bun run screenshots:update # re-renders it into screenshots/ (teeming at 45 s)
bun dev/gif.ts all # re-renders the README's GIFs into screenshots/
```

- `check.ts` runs the real engine on a mock 160x45 screen. "cells change per frame" is flicker: lower is calmer.
Expand Down Expand Up @@ -379,8 +379,34 @@ bun dev/gif.ts all # re-renders the README's GIFs
1. Put it in `wallpapers/<id>.ts` as a named export, and add it to `wallpapers/index.ts`.
2. Run `bun run typecheck` and `bun dev/check.ts <id>`, and look at `dev/snap.ts` and `dev/preview.ts` output at every
time of day.
3. Add it to the README's wallpaper list, gallery and GIF grid. Add its best-looking time of day to `BEST` in `dev/gif.ts`, then run `bun run screenshots:update` and
`bun dev/gif.ts all`.
3. Add it to the README's wallpaper list, gallery and GIF grid. Add its best-looking time of day to `BEST` in
`dev/gif.ts`. CI publishes its screenshots once it's merged; a maintainer adds its GIF (see below).

## README images

The README's images live on the orphan `assets` branch and are linked by URL, so installing the plugin doesn't
download them. Don't commit images to `main`. The dev tools check out that branch at `screenshots/` (a git worktree,
ignored on `main`) the first time they need it.

- **Screenshots** update themselves: CI renders every wallpaper, and when a pull request changes one it warns and
attaches the fresh renders as an artifact for review. Once the change is on `main`, CI commits them to `assets`.
- **GIFs and the rest** (`hero.gif`, `menu.png`, the farm's seasons and rain) are updated by hand, by anyone who can
push to `assets`:

```sh
git -C screenshots pull origin assets
bun dev/gif.ts all # or copy the new image into screenshots/
git -C screenshots commit -am "Update GIFs" && git -C screenshots push origin assets
```

Push after the change they show is on `main`. A new file needs `git -C screenshots add` first.

## Releases

`opencode plugin add vaprdev/opencode-wallpapers#release` installs the `release` branch, which CI rebuilds from every
push to `main` once the checks pass: `dist/`, the README, the license, the changelog and a `package.json` without
scripts, so installing doesn't build anything. Users get it with `opencode plugin update`. To run your checkout in
OpenCode instead, put its absolute path in `plugins` in `~/.config/opencode/cli.json`.

## Your own package

Expand Down
63 changes: 32 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,26 @@

Animated wallpapers for the OpenCode terminal UI: slow, quiet scenes behind everything, kept readable behind text.

![Beach, tundra, jungle, desert and space wallpapers in motion](screenshots/hero.gif)
![Beach, tundra, jungle, desert and space wallpapers in motion](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/hero.gif)

> This project is not affiliated with, endorsed by, or sponsored by OpenCode or its maintainers.

## Install

Requires OpenCode 2. Clone into OpenCode's plugin directory and restart OpenCode:
Requires OpenCode 2:

```sh
git clone https://github.com/vaprdev/opencode-wallpapers.git ~/.config/opencode/plugins/wallpapers
opencode plugin add vaprdev/opencode-wallpapers#release
```

Update with `git pull`.
Update with `opencode plugin update`. Restart OpenCode after either. If you installed it with `git clone` before, delete
`~/.config/opencode/plugins/wallpapers`.

## Use

Type `/wallpaper` to open the menu. ↑/↓ picks a setting, Enter or ←/→ changes it, Escape closes it.
Type `/wallpaper` to open the menu and pick a wallpaper; none shows until you do. ↑/↓ picks a setting, Enter or ←/→ changes it, Escape closes it.

![The wallpaper menu](screenshots/menu.png)
![The wallpaper menu](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/menu.png)

- **Activity:** calm, lively or teeming: how much moves behind your work.
- **Time:** day, sunset or night, or auto to follow your clock.
Expand All @@ -38,9 +39,9 @@ an error. With mouse support, clicking empty background nudges the scene, and ea

| Spring | Summer | Autumn | Winter |
| --- | --- | --- | --- |
| ![Farm in spring](screenshots/farm-spring.png) | ![Farm in summer](screenshots/farm-summer.png) | ![Farm in autumn](screenshots/farm-autumn.png) | ![Farm in winter](screenshots/farm-winter.png) |
| ![Farm in spring](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/farm-spring.png) | ![Farm in summer](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/farm-summer.png) | ![Farm in autumn](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/farm-autumn.png) | ![Farm in winter](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/farm-winter.png) |

![Farm in the rain](screenshots/farm-rain.png)
![Farm in the rain](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/farm-rain.png)

## Terminals

Expand All @@ -64,32 +65,32 @@ At teeming, played back at 3x speed:

| | |
| --- | --- |
| ![Ocean in motion](screenshots/ocean.gif) | ![Desert in motion](screenshots/desert.gif) |
| ![Jungle in motion](screenshots/jungle.gif) | ![Space in motion](screenshots/space.gif) |
| ![Farm in motion](screenshots/farm.gif) | ![Tundra in motion](screenshots/tundra.gif) |
| ![Beach in motion](screenshots/beach.gif) | ![City in motion](screenshots/city.gif) |
| ![Zen garden in motion](screenshots/zen.gif) | ![Prehistoric in motion](screenshots/prehistoric.gif) |
| ![Rider in motion](screenshots/rider.gif) | ![Megacity in motion](screenshots/megacity.gif) |
| ![Dome in motion](screenshots/dome.gif) | ![Haunted house in motion](screenshots/haunted-house.gif) |
| ![Flower Box in motion](screenshots/flowerbox.gif) | |
| ![Ocean in motion](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/ocean.gif) | ![Desert in motion](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/desert.gif) |
| ![Jungle in motion](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/jungle.gif) | ![Space in motion](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/space.gif) |
| ![Farm in motion](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/farm.gif) | ![Tundra in motion](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/tundra.gif) |
| ![Beach in motion](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/beach.gif) | ![City in motion](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/city.gif) |
| ![Zen garden in motion](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/zen.gif) | ![Prehistoric in motion](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/prehistoric.gif) |
| ![Rider in motion](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/rider.gif) | ![Megacity in motion](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/megacity.gif) |
| ![Dome in motion](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/dome.gif) | ![Haunted house in motion](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/haunted-house.gif) |
| ![Flower Box in motion](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/flowerbox.gif) | |

| | Day | Sunset | Night |
| --- | --- | --- | --- |
| Ocean | ![Ocean by day](screenshots/ocean.png) | ![Ocean at sunset](screenshots/ocean-sunset.png) | ![Ocean at night](screenshots/ocean-night.png) |
| Desert | ![Desert by day](screenshots/desert.png) | ![Desert at sunset](screenshots/desert-sunset.png) | ![Desert at night](screenshots/desert-night.png) |
| Jungle | ![Jungle by day](screenshots/jungle.png) | ![Jungle at sunset](screenshots/jungle-sunset.png) | ![Jungle at night](screenshots/jungle-night.png) |
| Space | ![Space by day](screenshots/space.png) | ![Space at sunset](screenshots/space-sunset.png) | ![Space at night](screenshots/space-night.png) |
| Farm | ![Farm by day](screenshots/farm.png) | ![Farm at sunset](screenshots/farm-sunset.png) | ![Farm at night](screenshots/farm-night.png) |
| Tundra | ![Tundra by day](screenshots/tundra.png) | ![Tundra at sunset](screenshots/tundra-sunset.png) | ![Tundra at night](screenshots/tundra-night.png) |
| Beach | ![Beach by day](screenshots/beach.png) | ![Beach at sunset](screenshots/beach-sunset.png) | ![Beach at night](screenshots/beach-night.png) |
| City | ![City by day](screenshots/city.png) | ![City at sunset](screenshots/city-sunset.png) | ![City at night](screenshots/city-night.png) |
| Zen garden | ![Zen garden by day](screenshots/zen.png) | ![Zen garden at sunset](screenshots/zen-sunset.png) | ![Zen garden at night](screenshots/zen-night.png) |
| Prehistoric | ![Prehistoric by day](screenshots/prehistoric.png) | ![Prehistoric at sunset](screenshots/prehistoric-sunset.png) | ![Prehistoric at night](screenshots/prehistoric-night.png) |
| Rider | ![Rider by day](screenshots/rider.png) | ![Rider at sunset](screenshots/rider-sunset.png) | ![Rider at night](screenshots/rider-night.png) |
| Megacity | ![Megacity by day](screenshots/megacity.png) | ![Megacity at sunset](screenshots/megacity-sunset.png) | ![Megacity at night](screenshots/megacity-night.png) |
| Dome | ![Dome by day](screenshots/dome.png) | ![Dome at sunset](screenshots/dome-sunset.png) | ![Dome at night](screenshots/dome-night.png) |
| Haunted house | ![Haunted house by day](screenshots/haunted-house.png) | ![Haunted house at sunset](screenshots/haunted-house-sunset.png) | ![Haunted house at night](screenshots/haunted-house-night.png) |
| Flower Box | ![Flower Box by day](screenshots/flowerbox.png) | ![Flower Box at sunset](screenshots/flowerbox-sunset.png) | ![Flower Box at night](screenshots/flowerbox-night.png) |
| Ocean | ![Ocean by day](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/ocean.png) | ![Ocean at sunset](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/ocean-sunset.png) | ![Ocean at night](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/ocean-night.png) |
| Desert | ![Desert by day](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/desert.png) | ![Desert at sunset](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/desert-sunset.png) | ![Desert at night](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/desert-night.png) |
| Jungle | ![Jungle by day](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/jungle.png) | ![Jungle at sunset](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/jungle-sunset.png) | ![Jungle at night](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/jungle-night.png) |
| Space | ![Space by day](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/space.png) | ![Space at sunset](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/space-sunset.png) | ![Space at night](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/space-night.png) |
| Farm | ![Farm by day](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/farm.png) | ![Farm at sunset](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/farm-sunset.png) | ![Farm at night](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/farm-night.png) |
| Tundra | ![Tundra by day](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/tundra.png) | ![Tundra at sunset](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/tundra-sunset.png) | ![Tundra at night](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/tundra-night.png) |
| Beach | ![Beach by day](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/beach.png) | ![Beach at sunset](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/beach-sunset.png) | ![Beach at night](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/beach-night.png) |
| City | ![City by day](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/city.png) | ![City at sunset](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/city-sunset.png) | ![City at night](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/city-night.png) |
| Zen garden | ![Zen garden by day](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/zen.png) | ![Zen garden at sunset](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/zen-sunset.png) | ![Zen garden at night](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/zen-night.png) |
| Prehistoric | ![Prehistoric by day](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/prehistoric.png) | ![Prehistoric at sunset](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/prehistoric-sunset.png) | ![Prehistoric at night](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/prehistoric-night.png) |
| Rider | ![Rider by day](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/rider.png) | ![Rider at sunset](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/rider-sunset.png) | ![Rider at night](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/rider-night.png) |
| Megacity | ![Megacity by day](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/megacity.png) | ![Megacity at sunset](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/megacity-sunset.png) | ![Megacity at night](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/megacity-night.png) |
| Dome | ![Dome by day](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/dome.png) | ![Dome at sunset](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/dome-sunset.png) | ![Dome at night](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/dome-night.png) |
| Haunted house | ![Haunted house by day](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/haunted-house.png) | ![Haunted house at sunset](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/haunted-house-sunset.png) | ![Haunted house at night](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/haunted-house-night.png) |
| Flower Box | ![Flower Box by day](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/flowerbox.png) | ![Flower Box at sunset](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/flowerbox-sunset.png) | ![Flower Box at night](https://raw.githubusercontent.com/vaprdev/opencode-wallpapers/assets/flowerbox-night.png) |

## License

Expand Down
14 changes: 14 additions & 0 deletions dev/assets.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// The README's images live on the orphan assets branch, so installing the plugin doesn't download them. The dev tools
// read and write them in screenshots/, a worktree of that branch, created here on first use.
import { existsSync } from "node:fs"

export function assets() {
if (existsSync("screenshots/.git")) return
if (existsSync("screenshots")) throw new Error("screenshots/ isn't a checkout of the assets branch: move it away and rerun")
if (Bun.spawnSync(["git", "rev-parse", "--verify", "--quiet", "refs/heads/assets"]).exitCode) git("fetch", "--depth=1", "origin", "assets:assets")
git("worktree", "add", "screenshots", "assets")
}

function git(...args: string[]) {
if (Bun.spawnSync(["git", ...args], { stdout: "ignore", stderr: "inherit" }).exitCode) throw new Error(`git ${args.join(" ")} failed`)
}
Loading
Loading