AtlatestRepositoryfolio
1# Folio
2
3A markdown-native knowledge and project management system, exposed as an MCP server. Folio stores all state as structured markdown files — human-readable, git-committable, and programmatically queryable.
4
5Built with [Sigil](https://codeberg.org/sigil/sigil).
6
7## Install
8
9```bash
10sigil app install codeberg:sigil/folio \
11 --mcp \
12 --env FOLIO_ROOT=~/folio
13```
15This installs the `folio` binary, registers it as a user-level MCP server, and points it at `~/folio` as the data directory. The folio directory will be created on first run.
17To install for a specific project instead (registers in the project's `.mcp.json`):
19```bash
20cd ~/my-project
21sigil app install codeberg:sigil/folio \
22 --mcp \
23 --mcp-scope project \
24 --env FOLIO_ROOT=./folio
25```
27Or add to `.mcp.json` manually:
29```json
31 "mcpServers": {
32 "folio": {
33 "command": "folio",
34 "env": {
35 "FOLIO_ROOT": "./folio"
36 }
37 }
38 }
40```
42## What it does
44For many local MCP clients, run one shared server:
46```bash
47FOLIO_ROOT=~/folio folio serve --http 18765 \
48 --token-file ~/.config/folio/http.token
49```
51Clients connect to `http://127.0.0.1:18765/mcp` with a bearer token read from
52that private file. Default stdio remains supported. See
53[shared HTTP operation and dependency status](docs/shared-http.md)
54before building or preparing a service/client migration.
56Folio gives AI agents structured access to tasks, projects, and notes through MCP tools. The agent gets clean operations; you get readable markdown files with clean git diffs.
58### Tasks
60Checkbox items with inline metadata:
62```markdown
63- [ ] Add contact lookup tool {id: t-a3f2, priority: high, due: 2026-03-20}
64- [x] Fix reply identity selection {id: t-b1c4, completed: 2026-03-13}
65```
67### Projects
69One markdown file per project in `projects/`, with YAML frontmatter, a task list, and a reverse-chronological log:
71```markdown
72---
73status: active
74goal: Add contact management and improve search
75area: development
76last-updated: 2026-03-13
77---
79# Bureau v2
81## Tasks
83- [ ] Add contact lookup tool {id: t-a3f2, priority: high, due: 2026-03-20}
84- [ ] Improve search result ranking {id: t-b1c4, priority: medium}
86## Log
88### 2026-03-13
90Fixed identity selection for replies. Bureau now auto-detects the
91correct sending identity from the original email's To field.
92```
94### Notes
96Atomic reference notes in `notes/` with `[[crosslinks]]` between them:
98```markdown
99---
100tags:
101 - fastmail
102 - jmap
103created: 2026-03-12
104last-updated: 2026-03-13
105---
107# Fastmail JMAP Quirks
109Fastmail rejects the `#draft` back-reference key in `onSuccessUpdateEmail`.
111## Related
113- [[caldav-discovery]] - CalDAV has similar redirect issues
114- [[bureau-send-pipeline]] - Where these quirks manifest
115```
117Notes support subdirectories for organization: `procedures/`, `contacts/`, `preferences/`, etc. Crosslinks resolve across both notes and projects.
119Backlinks and note summaries are cached in `.folio-index.db` alongside the
120existing search index. The offline `--migrate-index` step below is required
121before the first v0.3.1 server start. It populates the backlink cache; server
122starts then reuse it and parse only changed files. Writes through Folio
123refresh affected entries immediately. External edits are discovered by a
124metadata census every 15 seconds in both stdio and HTTP modes.
126An edit made outside Folio (an editor, sync, or an older Folio process) can
127therefore take up to about 15 seconds to appear in backlinks or status.
128If checking a backlink after such an edit, retry after the next census.
129Writes through this version of Folio update the index before returning.
131### Upgrade an existing store to 0.3.1
133The offline migration is required before starting any v0.3.1 server.
134Use this order: **stop, migrate, install, reconnect**. Do not let multiple
135clients perform the initial migration concurrently. On a large store this
136first pass can take minutes; subsequent starts reuse the persisted cache.
1381. Stop every MCP client process and shared server using the store. Disable
139 automatic restarts for the duration of the upgrade.
1402. Run the approved new executable directly, before installing it:
142 ```bash
143 export FOLIO_ROOT=/absolute/path/to/folio-store
144 candidate=/absolute/path/to/new/folio
145 "$candidate" --migrate-index
146 ```
148 Use exactly the same `FOLIO_ROOT` path spelling as the server configuration.
149 Require exit status zero and `Index migration complete`. A failure logs
150 the affected items and exits nonzero. Repair those items and retry; the
151 migration resumes without rebuilding documents already completed.
1523. Install that same executable through the deployment's normal package or
153 service mechanism. For a standalone executable deployment:
155 ```bash
156 destination=/absolute/path/to/installed/folio
157 install -m 755 "$candidate" "$destination"
158 "$destination" --version
159 ```
1614. Re-enable the shared service or MCP clients and reconnect them to the
162 same `FOLIO_ROOT`. The normal metadata census now starts from the migrated
163 cache. Keep the old executable available for rollback.
165`rebuild-index` replaces documents atomically without clearing the shared
166tables, so connected readers retain complete documents during maintenance.
168### Inbox
170A single `inbox.md` for capturing items before they're triaged into projects.
172## Directory structure
174```
175folio/
176├── inbox.md
177├── projects/
178│ ├── bureau-v2.md
179│ └── sigil-gc.md
180├── notes/
181│ ├── fastmail-jmap-quirks.md
182│ ├── procedures/
183│ │ └── email-triage.md
184│ └── contacts/
185│ └── alice.md
186└── archive/
187 ├── projects/
188 └── notes/
189```
191## MCP Tools
193### Overview
195| Tool | Description |
196|------|-------------|
197| `folio/status` | Dashboard: inbox count, overdue tasks, stale projects, orphaned notes |
199### Tasks
201| Tool | Description |
202|------|-------------|
203| `folio/tasks` | Query tasks across all projects and inbox with filters |
204| `folio/task-add` | Add a task to a project or inbox |
205| `folio/task-complete` | Mark a task as done |
206| `folio/task-update` | Update task metadata (priority, due, tags, waiting) |
207| `folio/task-move` | Move a task between projects or to inbox |
209A task's id is stable: moving it between the inbox and a project, or between
210projects, preserves the id it already had.
212### Bulk operations
214Triaging a full inbox one call at a time is slow enough that nobody does it
215routinely, which is how an inbox goes months without being triaged.
217| Tool | Description |
218|------|-------------|
219| `folio/task-move-batch` | Move many tasks at once, with a result line per id |
220| `folio/task-complete-batch` | Mark many tasks done by id list |
221| `folio/task-sweep` | Remove completed tasks from projects |
222| `folio/inbox-sweep` | Remove completed items from the inbox |
224`folio/task-move-batch` takes either one shared target or per-id targets, so a
225single call can fan out across many projects:
227```json
228{"ids": ["t-a3f2", "t-b1c4"], "project": "bureau-v2"}
230{"moves": [{"id": "t-a3f2", "project": "bureau-v2"},
231 {"id": "t-b1c4", "project": "sigil-gc"},
232 {"id": "t-c5d6"}]}
233```
235An entry with no `project` moves that task to the inbox. Every id gets its own
236result line, so a partial failure is visible rather than swallowed.
238### Inbox
240| Tool | Description |
241|------|-------------|
242| `folio/inbox` | List all inbox items |
243| `folio/inbox-add` | Add an item to the inbox |
244| `folio/inbox-triage` | Move an inbox item to a project |
246> **Keep inbox captures to a single line.** An item whose text contains
247> newlines is currently written in a shape folio cannot read back: the
248> `{id: ...}` metadata lands on the item's last line, the parser sees only the
249> first, and the item becomes invisible to every tool while a phantom
250> one-line duplicate takes its place. For anything longer, create a note and
251> reference it from a one-line inbox item. See the Known issues section of
252> CHANGELOG.md.
254### Projects
256| Tool | Description |
257|------|-------------|
258| `folio/projects` | List projects with task counts |
259| `folio/project-info` | Full project details: tasks and log entries |
260| `folio/project-create` | Create a new project |
261| `folio/project-log` | Add a dated log entry to a project |
262| `folio/project-archive` | Archive a completed project |
263| `folio/project-clean` | Move completed tasks to the project log |
265### Notes
267| Tool | Description |
268|------|-------------|
269| `folio/notes` | Search notes by text or tag |
270| `folio/note-read` | Read a note's full content |
271| `folio/note-create` | Create a new note |
272| `folio/note-edit` | Replace a note's content |
273| `folio/note-links` | Show outgoing links and backlinks |
274| `folio/note-rename` | Rename a note and update all crosslinks |
276## Development
278Requires [Sigil](https://codeberg.org/sigil/sigil) v0.22.15, sigil-json 0.16.2,
279sigil-mcp 0.18.4 and sigil-http 0.18.8. Install the published dependency graph
280from the committed lock without redirects; see
281[dependency status](docs/shared-http.md#development-status) before building.
283```bash
284# Install dependencies
285sigil deps install
287# Build
288sigil build
290# Test
291sigil test
293# Run locally
294FOLIO_ROOT=/tmp/folio ./build/dev/bin/folio
296# Build release bundle (standalone binary)
297sigil build --config release
298FOLIO_ROOT=/tmp/folio ./build/release/bin/folio
299```
301## License
303BSD-3-Clause