npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

jotbook

v0.0.1

Published

Markdown-based project memory for Claude Code, viewable in your browser.

Readme

Jotbook

Plain-Markdown project memory for Claude Code, viewable in your browser.

jotbook is a tiny Claude Code extension that turns project memory into a folder of plain Markdown files (one per entry) and ships a static HTML viewer so you can read and filter your memory in the browser while you work.

  • Plain Markdown all the way down. Entries are standard .md files with YAML frontmatter — the same shape Claude Code's auto-memory and OpenAI Codex AGENTS.md use. They render correctly on GitHub, in any editor, in any Markdown reader. Drop your own .md files into entries/ and they just work.
  • No bespoke syntax. No custom fence types, no raw-HTML escape hatches, no widget DSL. If a Markdown reader can render it, jotbook can render it.
  • O(1) writes. Each new memory entry is one new file. Claude never has to read the whole memory or re-emit a JSON blob to add an entry.
  • Selective reading. A small generated memory.json index lets Claude filter by type and tags and load only the relevant entry bodies on demand.
  • No build step for users. The viewer ships pre-built — npx jotbook is everything end-users run. (Maintainers run npm run build before publishing to regenerate the React bundle; see viewer-src/ and ADR 0018.)

Quick start

cd your-project
npx jotbook init      # scaffold .claude-memory/, skill, /remember command, hook
npx jotbook serve     # open the viewer at http://localhost:4123

Then use Claude Code in any of these ways:

/remember we use JWT v2 for auth — see src/auth.ts:10-40

or just say it in natural language:

"Remember that we use JWT v2 for auth — see src/auth.ts:10-40."

Either path writes a new file at .claude-memory/entries/<id>.md. Refresh the viewer to see it.

Commands

| Command | What it does | | --- | --- | | npx jotbook init | Scaffold .claude-memory/, install the skill, install the /remember command, register the SessionStart hook. | | npx jotbook build | Rebuild .claude-memory/memory.json from entries/*.md. | | npx jotbook update | Refresh the viewer bundle, schema, skill, and slash command. Your entries and viewer-config.json are preserved (v3 is a clean break — see ADR 0016 — so there's no migration pass; legacy v1 fields on disk surface as _warnings on the Index stub and need a manual cleanup). | | npx jotbook serve | Serve the viewer at http://localhost:4123. Regenerates memory.json on every fetch, so edits to entries show up on refresh. | | npx jotbook record --title "..." [--type ...] [--body ...] | Create a new Entry through the audited write path (id is invented; v2 schema enforced). | | npx jotbook validate | Walk entries/*.md and exit non-zero on any schema error. Designed for CI. | | npx jotbook codex-notify | Codex notify hook surface — validates agent-turn-complete events and exits cleanly. | | npx jotbook --version | Print the installed version. |

What init creates

your-project/
├── .claude-memory/
│   ├── entries/             ← one .md file per entry — your memory lives here
│   ├── assets/              ← images referenced by entries
│   ├── memory.json          ← generated index. DO NOT hand-edit.
│   ├── schema.json          ← JSON Schema for the index (the contract)
│   ├── viewer.html          ← static viewer
│   ├── viewer.js
│   ├── viewer.css
│   ├── entry-format.js      ← shared MD-entry parser (used by CLI + viewer)
│   └── viewer-config.json   ← customize colors, labels, types
└── .claude/
    ├── settings.json        ← SessionStart hook entry
    ├── commands/
    │   └── remember.md      ← /remember slash command
    └── skills/
        └── jotbook-memory/
            └── SKILL.md     ← teaches Claude the MD entry format

The entry format

Every memory entry is a plain Markdown file with YAML frontmatter:

---
id: 2026-05-14-jwt-v2
type: decision
title: Use JWT v2 for auth
tags: [auth, architecture]
created: 2026-05-14T10:00:00Z
updated: 2026-05-14T10:00:00Z
---

We switched to JWT v2 because the v1 library is unmaintained. Tokens are signed
with RS256; rotation is monthly. See `src/auth.ts:10-40`.

That's it. Frontmatter + plain Markdown. Nothing else.

Required frontmatter fields: id (must match the filename), type, title. Everything else is optional.

Common type values: note, decision, todo, convention, code-area, correction. Free-form is fine; the viewer falls back to default styling.

v2 vocabulary (the only allowed frontmatter keys): id, type, title, author, tags, links, evidence, supersedes, resolves, created, updated. The schema validator (bin/schema-validator.js) rejects writes containing anything else — including the v1 fields status, assigned_to, blocks, manual, verified, which were removed in 2.0.

What the Markdown body can contain

Standard Markdown — the same subset that renders correctly on GitHub and in most editors. No special syntax:

  • Headings (#######), paragraphs, bullet lists, bold, italic, inline code, links
  • Blockquotes (> …) for asides, callouts, and warnings
  • Images: ![alt](assets/foo.png) — save the file under .claude-memory/assets/
  • Fenced code blocks with language tags
  • Mermaid diagrams via a standard ```mermaid fence (lazy-loaded)
  • Pipe tables: |col|col| with a |---|---| separator row
  • Horizontal rule: ---

Any other tool that reads Markdown will render the same file the same way. That's the point.

The generated index (memory.json)

memory.json is a build artifact. The CLI regenerates it from entries/*.md on every serve and build. Do not hand-edit it.

{
  "version": "3.0",
  "project": "your-project",
  "entries": [
    {
      "id": "2026-05-14-jwt-v2",
      "type": "decision",
      "title": "Use JWT v2 for auth",
      "tags": ["auth", "architecture"],
      "created": "2026-05-14T10:00:00Z",
      "updated": "2026-05-14T10:00:00Z",
      "file": "entries/2026-05-14-jwt-v2.md"
    }
  ]
}

The index stays small — title and frontmatter only. The full entry body is in the .md file and only loads when someone opens that specific entry in the viewer or when Claude reads it for selective recall.

Customizing the viewer (no forking required)

Edit .claude-memory/viewer-config.json:

{
  "title": "Acme Memory",
  "theme": {
    "primary": "#ff5a5f",
    "background": "#fff",
    "surface": "#f4f4f4",
    "text": "#111",
    "muted": "#666",
    "border": "#e0e0e0"
  },
  "types": {
    "note":     { "label": "Note",     "color": "#5b8def" },
    "decision": { "label": "Decision", "color": "#a371f7" },
    "spike":    { "label": "Spike",    "color": "#f0883e" }
  },
  "defaultSort": "updated-desc"
}

Any new type value you start using just needs an entry here to get a custom label and color. Unknown types still render fine.

Environment

  • JOTBOOK_PORT — port for serve (default 4123).

Why plain Markdown?

  • Portable. Any .md file someone wrote in another tool drops into entries/ and renders. Any jotbook entry opens in GitHub, VS Code, Obsidian, or cat and looks the same as in the viewer.
  • O(1) writes. Adding a memory entry is creating one new file — no read-parse-mutate-write cycle on a growing JSON file.
  • Sticky for the agent. Markdown with YAML frontmatter is the format every major coding agent (Claude Code's auto-memory, Codex AGENTS.md, Cursor) chose for the same reason: agents write it more reliably than JSON.
  • Selective reading still works. The generated memory.json index lets Claude filter by type and tags and load only the bodies it actually needs.
  • No vendor lock-in. Nothing in entries/ is jotbook-specific. If you stop using jotbook tomorrow, you still have a folder of plain Markdown notes.

License

MIT.