Skip to main content
Glama
stuartmhannon

grainjournal

README.md
# grainjournal

**MCP-native journaling with verbatim capture.**

A Model Context Protocol server that prompts you to journal one question per day and captures your answers verbatim — no AI reads your words, no AI rewrites them, nothing added.

## Why

The journaling space has apps that ingest your raw material and give you back "insights." grainjournal does the opposite. It's a philosophical position: **your journal is yours.** We don't touch your words. We just make it easier to write and preserve exactly what you wrote.

- **MCP-native.** Works as an MCP server — integrate it with Claude Desktop, Cline, your AI agent, or run it as a standalone cron job.
- **Prompt sequencing.** One prompt per day from a curated sequence. Build a life narrative over weeks, not a firehose of generic questions.
- **Verbatim capture.** When you write, we copy your exact words. Nothing summarized, nothing rewritten, nothing analyzed.
- **Markdown as platform.** Prompts are `.md` files in your vault. Responses are `.md` files in your vault. Sync is whatever sync you already use.
- **Silence is fine.** If you write nothing, nothing happens. No nudge, no guilt, no follow-up.

## Quick Start

### Prerequisites

- Python 3.10+
- An Obsidian vault (or any directory of markdown files)

### Install

```bash
pip install grainjournal-mcp-server
```

### Run as MCP Server

```bash
grainjournal --vault ~/my-vault/Journal
```

This starts the MCP server on stdio transport. Configure it as an MCP client tool in Claude Desktop, Cline, or any MCP-compatible agent.

### Run as Cron Scripts

Two standalone scripts:

```bash
# Morning — writes today's prompt (run daily ~8AM)
grainjournal-prompt --vault ~/my-vault/Journal

# Evening — checks for written content (run daily ~10PM)
grainjournal-check --vault ~/my-vault/Journal
```

Or set the `GRAINJOURNAL_VAULT` environment variable:

```bash
export GRAINJOURNAL_VAULT=~/my-vault/Journal
grainjournal-prompt
grainjournal-check
```

## MCP Tools

### `journal_prompt`

Writes today's journal prompt note. One prompt per day from a curated sequence. Idempotent — safe to call multiple times.

**Optional parameter:** `custom_prompt` — override today's prompt with your own.

### `journal_check`

Checks today's journal note for user-written content. If content exists beyond the header, captures it verbatim to the resume base. Silent if empty.

## The Prompt Sequence

The initial sequence walks through a resume-gap meditation — one question per day:

1. Your first job after college
2. The bridge between disciplines
3. Specific roles and what you did
4. Education and study
5. A turning-point project
6. Your narrative thread — the story you tell yourself

After the sequence wraps, it cycles back with room for custom prompts.

## Architecture

```
grainlocal/Journal/           ← Your Obsidian vault (or any .md directory)
├── 2026-07-12 Journal Prompt.md    ← Written by Cron A / journal_prompt
├── 2026-07-12 Journal.md           ← Written by you (in Obsidian)
├── 2026-07-13 Journal Prompt.md
├── 2026-07-13 Journal.md
└── .grainjournal-state.json        ← Tracking state (auto-managed)

grainjournal-mcp-server/
├── grainjournal/
│   ├── server.py          ← MCP server entrypoint
│   ├── vault.py           ← Obsidian vault read/write
│   ├── prompts.py         ← Prompt sequence + state tracking
│   └── scripts/
│       ├── write_prompt.py   ← Cron A
│       └── check_content.py  ← Cron B
└── pyproject.toml
```

## Philosophy

The field is surprisingly empty where grainjournal sits:

- **MCP-native journaling doesn't exist yet.** The entire ecosystem of MCP journal servers is 5 repos with zero stars.
- **Verbatim capture is a philosophical position.** No tool in this space explicitly says "I will not touch your words."
- **Your existing tools, your way.** Not a standalone app — works inside whatever you already have.

## License

MIT — use it, fork it, build on it. That's the point.