Skip to content

Latest commit

 

History

122 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

BerryWiki

A companion authoring, navigation, indexing and synchronisation layer for GitHub.com Wikis that gives them a CherryTree/Zim-style hierarchical notebook experience — while keeping the content as plain, GitHub-compatible Markdown in ordinary Git storage.

Core principle: the wiki must stay fully usable when BerryWiki is not. You can always clone the .wiki.git repo, read/edit the Markdown in any editor, commit, push, and view it through GitHub's normal Wiki UI. BerryWiki enhances the files; it never makes them depend on the app.

What works today

A local wiki folder can be browsed and edited end to end:

berrywiki serve ./my-wiki          # three-pane explorer + editor at :23779
  • Hierarchical notebook over flat files. Tree, sibling ordering, backlinks and a generated _Sidebar.md that GitHub renders natively — all driven by a hidden metadata block that is invisible in the rendered wiki, never by filenames.
  • Zero-JavaScript editor. Source editing with preview, page create and delete, explicit Save and Save-draft. Drafts live outside the clone, survive a killed process, and are visible as a banner, a badge and a marker in the tree. No <script> is served anywhere — a test asserts it on every route.
  • Writes that refuse rather than clobber. If a page changed on disk, or changed since your editor was opened, Save is refused with a 409 — and your text is kept, both in the form and as a draft. Nothing you typed is discarded.
  • Tags with index pages. A tags: list in the metadata block gives /tags (every tag with a page count), /tags/<tag> (the pages carrying it) and /search?tag= (filter alone or beside a query). The tag field is part of the editor and the new-page form. GitHub ignores the key, so a tagged wiki is still an ordinary wiki.
  • Consistency diagnostics. Broken links, missing parents, cycles and duplicate ids, surfaced in the UI and via berrywiki check.
  • Commit-on-save (berrywiki-sync, wired into serve): when the folder is a git working tree, every save, create and delete is one atomic commit with the sidebar in the same commit. Changes made outside BerryWiki are checkpointed as their own commit first, never clobbered. /changes lists unpublished commits and offers fetch + fast-forward + push; if the branch has diverged, /conflicts hands off with the exact git steps. Once you have started the merge yourself, /conflicts classifies each clash from the git index, shows base, ours and theirs, and can conclude a merge whose only clash is the generated _Sidebar.md by regenerating it. Never force-pushes, never starts a merge, never merges two authored sides, never discards local work. serve --no-commit serves the folder without touching git.
  • Move a page or a whole subtree from its page (Move…): pick a new parent and position, Preview the exact list of files renamed and links rewritten without changing anything, then Move to apply it as one commit. Retitling is done in the editor; the filename follows on the next move.
  • Attachments, and history per page. Files attach to a page and are stored in the wiki repo like any other content; each page has a history view reading real git history, so you can see what changed and when without leaving the reader.
  • Accessibility as a gate, not an aspiration. berrywiki-a11y is a dev-only crate of fourteen structural rules that runs over every rendered route in the test suite: heading order, landmarks, a skip link, accessible names, and text alternatives for anything that signals with colour or shape alone. Contrast ratios are recorded by hand in ADR-0012. Writing the gate found an unswept route that two green "every route" tests had both missed.
  • Backup and restore, and CherryTree import. berrywiki backup writes a git bundle of committed history plus drafts and the operation journal; berrywiki restore rebuilds from it. berrywiki import reads a CherryTree .ctd notebook and reports what it would become before writing anything.

What does not work yet

Being explicit, because the difference matters:

  • Merging two authored sides. BerryWiki never starts a merge and never merges page bodies or metadata. It classifies a merge you started, shows all three sides, and can conclude one whose only clash is the generated sidebar; anything else is refused and left for you to settle in git.
  • GitHub serving is read-only. serve --github mirrors a wiki and renders no edit affordances.
  • The accessibility walkthrough has not been run. The structural half is a gate and is enforced on every route (above). The manual half — driving the reader and the editor with a screen reader — is written up in docs/execution/a11y-walkthrough.adoc and has never been executed. It needs a human at a browser with NVDA. No screen-reader claim is made until it has been.
  • Live GitHub behaviour is unverified. Every GitHub Wiki behaviour BerryWiki relies on is recorded in docs/compatibility/github-wiki.adoc and, as of today, none has been tested against a real wiki — those spikes are credential-gated. Treat the compatibility report as a hypothesis list.
  • CherryTree import works; Zim import, packaging and proofs do not yetberrywiki import reads CherryTree XML notebooks, and what it cannot carry across is listed construct by construct in ADR-0014. Zim import and Guix packaging are the rest of Phase 5. The invariants a proof would cover are written down in docs/proofs/invariants.adoc, each with the tests that witness it and a CI gate that keeps the list honest. They are tested, not proved.

Current position: Phases 0–4 are built — all five Phase 4 packages (tags, history, attachments, accessibility, backup/restore) are done, with the accessibility walkthrough the one explicit exception above. Phase 5 is one of four: CherryTree import is done; Zim import, Guix packaging and the SPARK proof work are open. The suite is 429 tests across 42 binaries, green (measured 2026-09-15). See docs/execution/work-packages.adoc for the package-by-package state and docs/execution/debt-register.adoc for known debt.

Install and use

Requires Rust 1.89 or newer. No other runtime.

cargo build --release
./target/release/berrywiki --help
berrywiki check ./my-wiki           # tree + diagnostics; exit 1 on any error
berrywiki sidebar ./my-wiki --write # regenerate _Sidebar.md
berrywiki serve ./my-wiki           # browse and edit at http://127.0.0.1:23779
berrywiki serve ./my-wiki --no-commit           # same, without commit-on-save
berrywiki serve ./my-wiki --author "Ada <ada@example.org>"   # commit identity
berrywiki serve --github owner/repo # mirror a GitHub wiki (read-only)
berrywiki backup ./my-wiki ./backup-2026-09-03  # bundle + drafts + journal
berrywiki restore ./backup-2026-09-03 ./restored-wiki
berrywiki import notes.ctd ./my-wiki            # dry run: what it would bring across
berrywiki import notes.ctd ./my-wiki --apply    # write the pages, in one commit

For a private wiki, supply a token via BERRYWIKI_GITHUB_TOKEN — never as a command-line argument, so it stays out of shell history and process listings.

fixtures/test-wiki/ is a small notebook you can point any of these at.

How a page looks on disk

Ordinary Markdown, preceded by a comment GitHub does not render:

<!-- berrywiki
id: 0195f6ec-36a2-7a42-b519-5f558842e256
parent: 0195f6d0-b787-7c3a-a48f-c1a04fb2ea84
position: 30
kind: page
tags:
  - assessment
-->

# Assessment Plan

Ordinary Markdown from here on.

Delete the comment and the page is still a perfectly good wiki page — it simply stops being part of the tree. That is the point.

Checking a wiki in CI (for teachers, and anyone else)

berrywiki check validates a wiki tree — broken links, missing parents, cycles, duplicate ids — and exits non-zero on error-level diagnostics, so it works as a CI gate over a course wiki. You do not have to install anything: this repository ships a composite Action at its root.

# .github/workflows/wiki.yml in your own course repository
name: wiki
on: [push, pull_request]

jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
      # Pin this to a commit SHA rather than @main. The Action builds the CLI
      # from whatever revision you pinned it at and caches the binary on that
      # commit, so a pinned workflow restores a cached binary while @main
      # rebuilds every time this repository moves.
      - uses: metadatastician/berrywiki@main
        with:
          path: .          # folder holding the wiki pages
          strict: 'false'  # 'true' also fails the build on warnings

The Action writes a summary to the job page and exposes errors, warnings and pages as step outputs. Warnings do not fail the build by default — a missing parent or a broken link is a warning, and a duplicate page id is an error — which is usually what you want on a wiki that is still being written. Set strict: 'true' once your tree is clean and you want it to stay that way.

The point, for a module wiki, is finding out that Week 7 links to a page you deleted before a student does.

The Action currently builds berrywiki from source and caches the binary by commit, because there is no tagged release yet. That is a deliberate hold, not an oversight — see the note in action.yml.

Architecture

Thirteen crates, layered so the parts that must be provably correct have no I/O to be wrong about — see ARCHITECTURE.md.

  • Engine: Rust. No hand-written JavaScript or TypeScript (ADR-0003); the UI is server-rendered and script-free by test. ADR-0007 was ruled on 2026-09-03: generated script may ship, but only from a named toolchain, reproducibly, and listed in a provenance manifest. None exists, so nothing is served.
  • berrywiki-serve has no third-party dependencies at all — a hand-rolled std::net server, no async runtime, no web framework.
  • Docs: AsciiDoc (.adoc) for technical docs and ADRs; Markdown (.md) for wiki content and community-health files.

Layout

crates/berrywiki-core/      deterministic engine (no I/O)
crates/berrywiki-store/     WikiStore trait + LocalFolderStore (atomic writes)
crates/berrywiki-serve/     zero-JS three-pane explorer and editor
crates/berrywiki-git/       closed-set git wrapper · -sync/-github/-git-compat
crates/berrywiki-appstate/  out-of-clone app state · -draft for drafts
crates/berrywiki-cli/       the `berrywiki` command
fixtures/test-wiki/         fixture notebook (Markdown)
docs/architecture/          plan + overview
docs/compatibility/         GitHub Wiki compatibility findings (unverified)
docs/decisions/             architecture decision records
docs/execution/             work packages + debt register
docs/proofs/                invariants ledger INV-1..6 (tested, proof scheduled)
scripts/                    CI gates (invariants-ledger check, AsciiDoc render)

Build & test

cargo test --workspace     # includes the no-<script> and no-data-loss harnesses
cargo fmt --all -- --check
cargo clippy --workspace --all-targets -- -D warnings

cargo test is the safety gate: it carries the script-free SSR assertions and the git conflict / no-data-loss harness.

Contributing

See CONTRIBUTING.md. Security reports: SECURITY.md.

Licence

Code is licensed under MPL-2.0; documentation under CC-BY-SA-4.0. Full texts in LICENSES/; machine-readable mapping in REUSE.toml.

The root LICENSE file is the verbatim, unmodified MPL-2.0 text, and must stay that way. It carried a short dual-licence preamble until 2026-09-15, which read correctly to a human but dropped GitHub's licensee below its match threshold, so the repository reported its licence as "other" and showed no licence in the sidebar. The dual-licence statement lives here and in REUSE.toml instead, which are the normative record; LICENSE is only the copy GitHub reads. Adding anything above the MPL text — even a comment — breaks detection again.

About

CherryTree/Zim-style hierarchical notebook for GitHub Wikis — tree, backlinks and a zero-JavaScript editor over plain Markdown that stays fully usable without it.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Used by

Contributors

Languages