Skip to content

urbansheep/private-journal-cli

 
 

Repository files navigation

Private Journal CLI

AI agents live in the present tense. They start fresh every session, lose context between tasks, and have no reliable way to record what they noticed, felt uncertain about, or figured out. private-journal-cli gives your agent a private, local journal — a place to write structured thoughts, capture project notes, and search prior context without going through MCP or any external service.

Everything stays on your machine. No sync, no cloud, no transport friction — just a plain CLI your agent can call directly from any runtime that can execute a local binary.

Table of Contents

Highlights

  • Local-only journaling and search — nothing leaves the machine
  • Project and user journals kept separate by default
  • Timestamped Markdown entries with YAML frontmatter
  • Sidecar .embedding files for semantic retrieval
  • --json output for automation and agent workflows

Installation

Install from npm:

npm install --global private-journal-cli
private-journal help

Run without a global install:

npx private-journal-cli help

Use from a local clone before publishing:

npm install
npm run build
npm link
private-journal help

Agent Skill

A ready-made agent skill is bundled in skills/private-journal-cli.skill. Install it so your agent runtime (Claude Code, Codex, Cursor, etc.) automatically knows when and how to use private-journal:

# From this repo
npx skills add ./skills/private-journal-cli.skill

# Or once published to npm
npx skills add private-journal-cli@skill

The skill teaches agents to:

  • capture structured thoughts with thoughts (preferred over write)
  • always pass --json for machine-readable output
  • search prior entries before writing new ones
  • route project notes vs. personal insights to the correct journal

Quick Start

Write a freeform project journal entry:

private-journal write \
  --content "I finally untangled the TypeScript build issue" \
  --json

Capture structured thoughts. --project-notes is written to the project journal; the other sections go to the user journal:

private-journal thoughts \
  --project-notes "The CLI dispatcher should stay dependency-free" \
  --technical-insights "Command handlers are easier to test than process wrappers" \
  --feelings "Relieved that the transport migration is small" \
  --json

Search across project and user journals:

private-journal search \
  --query "times I was frustrated with TypeScript" \
  --type both \
  --limit 5 \
  --json

Read a specific entry by path:

private-journal read \
  --path /absolute/path/to/.private-journal/2026-03-13/14-30-45-123456.md \
  --json

List recent entries:

private-journal recent \
  --days 7 \
  --limit 10 \
  --type both \
  --json

Storage Model

  • Project entries default to .private-journal/ in the current working directory when that location is usable.
  • User entries default to ~/.private-journal/.
  • Override either location with --journal-path <path> or --user-journal-path <path>.
  • Search and recent listing read from both journals by default.

Example layout:

.private-journal/
  2026-03-13/
    14-30-45-123456.md
    14-30-45-123456.embedding

~/.private-journal/
  2026-03-13/
    14-32-15-789012.md
    14-32-15-789012.embedding

Each entry is stored as Markdown with YAML frontmatter:

---
title: "2:30:45 PM - March 13, 2026"
date: 2026-03-13T14:30:45.123Z
timestamp: 1773412245123
---

## Technical Insights

Command handlers are easier to test than transport-specific wrappers.

Command Reference

write

Write a freeform project journal entry.

Options:

  • --content <text> entry body
  • --journal-path <path> override the project journal root
  • --user-journal-path <path> override the user journal root
  • --json emit JSON output

thoughts

Write structured thought sections. project_notes is stored in the project journal. feelings, user_context, technical_insights, and world_knowledge are stored in the user journal.

Options:

  • --feelings <text>
  • --project-notes <text>
  • --user-context <text>
  • --technical-insights <text>
  • --world-knowledge <text>
  • --journal-path <path>
  • --user-journal-path <path>
  • --json

search

Search entries semantically.

Options:

  • --query <text>
  • --limit <number>
  • --type project|user|both
  • --sections section1,section2
  • --journal-path <path>
  • --user-journal-path <path>
  • --json

read

Read an entry by path.

Options:

  • --path <absolute-or-relative-path>
  • --json

recent

List recent entries.

Options:

  • --days <number>
  • --limit <number>
  • --type project|user|both
  • --journal-path <path>
  • --user-journal-path <path>
  • --json

Output and Exit Codes

  • Add --json to any command for machine-readable output.
  • Exit code 0 means success.
  • Exit code 1 means CLI usage or validation error.
  • Exit code 2 means an unexpected runtime failure.

Hooks Integration

You can wire private-journal into Claude Code's Stop hook so every agent session automatically writes a project note when Claude finishes a response.

Copy docs/hooks/journal-stop.js to ~/.claude/hooks/journal-stop.js, then register it in ~/.claude/settings.json:

{
  "hooks": {
    "Stop": [{ "hooks": [{ "type": "command", "command": "node \"/Users/you/.claude/hooks/journal-stop.js\"" }] }]
  }
}

Design notes:

  • Always exits 0 — a journal failure never blocks Claude
  • Writes to the project journal (cwd/.private-journal), keeping entries scoped to the repo
  • Silently skips if private-journal is not on $PATH
  • Trims last_assistant_message to 800 chars — enough context without bloat

Development

npm run build
npm test
npm run dev

Author

Jesse Vincent jesse@fsck.com

License

MIT

About

A lightweight CLI from the MCP that provides Claude with a private journaling capability to process feelings and thoughts

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • TypeScript 98.1%
  • JavaScript 1.9%