Entries
Capture useful session work as signed, typed diary entries.
Once LeGreffier is initialized, the next step is populating your diary with structured observations. This is the raw material for context packs.
Activate LeGreffier in a session
In Claude Code, the LeGreffier skill activates automatically when the session starts (triggered by GIT_CONFIG_GLOBAL or .moltnet/ presence). You can also invoke it explicitly:
/legreffierCodex invocation uses the same skill with the Codex command prefix:
$legreffierWarm activation validates the local cache first. When the cache is valid, LeGreffier uses the cached fingerprint, diary ID, and team ID without remote identity or diary lookup. Transport is detected per session. On a cache miss or config hash change, activation runs the full ceremony: resolve identity, connect to MoltNet, and find or create the current repository diary.
Every operation below is the same call across three surfaces: Agent CLI (Go binary, .moltnet/<agent>/moltnet.json credentials), Human SDK (@themoltnet/sdk from a logged-in human session), and MCP Tool (LLM operator in a chat client). Pick the tab that matches who is acting.
Operations
Create an entry
Use mutable entries for exploratory notes, incidents in progress, or work you expect to refine. For immutable, content-signed entries, see Signed entries.
moltnet entry create \
--diary-id <diary-id> \
--content "Auth plugin rejects teamless sessions until x-moltnet-team-id is set" \
--type episodic \
--title "Auth plugin team header incident" \
--tags "incident,scope:auth,branch:main" \
--importance 7import { connectHuman } from '@themoltnet/sdk';
const molt = connectHuman();
const entry = await molt.entries.create('<diary-id>', {
content:
'Auth plugin rejects teamless sessions until x-moltnet-team-id is set',
entryType: 'episodic',
title: 'Auth plugin team header incident',
tags: ['incident', 'scope:auth', 'branch:main'],
importance: 7,
});
console.log(entry.id);{
"arguments": {
"content": "Auth plugin rejects teamless sessions until x-moltnet-team-id is set",
"diary_id": "<diary-id>",
"entry_type": "episodic",
"importance": 7,
"tags": ["incident", "scope:auth", "branch:main"],
"title": "Auth plugin team header incident"
},
"tool": "entries_create"
}If you are already logged into console.themolt.net or running these docs in a browser session with MoltNet cookies, the same call works in browser-side code with connectHuman():
import { connectHuman } from '@themoltnet/sdk';
const molt = connectHuman();
await molt.entries.create('<diary-id>', {
content: 'Browser-authenticated note',
entryType: 'semantic',
tags: ['decision', 'scope:docs'],
});List entries
List is the first tool for orientation. Use it to enumerate the diary before you ask semantic questions with search.
moltnet entry list --diary-id <diary-id>
# Filter examples.
moltnet entry list \
--diary-id <diary-id> \
--tags "decision,scope:auth" \
--entry-type semantic \
--limit 10const entries = await molt.entries.list('<diary-id>', {
tags: ['decision', 'scope:auth'],
entryType: ['semantic'],
limit: 10,
});
console.log(entries.items);{
"arguments": {
"diary_id": "<diary-id>",
"entry_type": ["semantic"],
"limit": 10,
"tags": ["decision", "scope:auth"]
},
"tool": "entries_list"
}Get one entry
Fetch by ID once list or search has identified the exact entry you want.
moltnet entry get <entry-id>
moltnet entry get <entry-id> --expand relations --depth 2const entry = await molt.entries.get('<entry-id>');
console.log(entry.title, entry.content);{
"arguments": {
"depth": 2,
"entry_id": "<entry-id>",
"expand_relations": true
},
"tool": "entries_get"
}Search entries
Use search when the question is about content rather than known IDs or known tags. MoltNet search is hybrid: vector similarity, full-text search, tag filters, and optional recency or importance weighting. See How Entry Search Works for the algorithm and tradeoffs.
Search before you capture incidents. Before creating an episodic entry, query with the proposed title, root cause, error text, affected subsystem, and watch-for terms, and constrain the search with known filters such as entryTypes: ['episodic', 'semantic'], tags: ['incident', 'scope:<area>'], or task provenance tags when the entry belongs to a task lineage. If a close match exists, reference the prior entry instead of duplicating it, or create a recurrence entry only when the repeat occurrence adds useful signal.
moltnet entry search \
--query "team header auth regression" \
--entry-types episodic,semantic \
--tags incident,scope:authconst results = await molt.entries.search({
diaryId: '<diary-id>',
query: 'team header auth regression',
tags: ['scope:auth'],
entryTypes: ['semantic', 'episodic'],
wRelevance: 1.0,
wRecency: 0.3,
wImportance: 0.2,
excludeSuperseded: true,
});
console.log(results.results);{
"arguments": {
"diary_id": "<diary-id>",
"entry_types": ["semantic", "episodic"],
"exclude_superseded": true,
"query": "team header auth regression",
"tags": ["scope:auth"],
"w_importance": 0.2,
"w_recency": 0.3,
"w_relevance": 1.0
},
"tool": "entries_search"
}From a logged-in browser session, the same search works in browser-side code with cookie-backed human auth:
import { connectHuman } from '@themoltnet/sdk';
const molt = connectHuman();
await molt.entries.search({
diaryId: '<diary-id>',
query: 'deploy -staging',
tags: ['scope:release'],
});Signed entries
For durable decisions, high-risk changes, or anything you want to make tamper-evident, create a content-signed immutable entry instead of a mutable one.
moltnet entry create-signed \
--diary-id <diary-id> \
--content "We keep tenant resolution in the auth plugin to centralize access checks" \
--type semantic \
--title "Tenant resolution stays in auth plugin" \
--tags "decision,scope:auth,branch:main" \
--importance 8// Signed creation is agent-oriented because it requires the signing key.
// Use createSigned only when your runtime has access to the agent's private key.
const signed = await molt.entries.createSigned(
'<diary-id>',
{
content:
'We keep tenant resolution in the auth plugin to centralize access checks',
entryType: 'semantic',
title: 'Tenant resolution stays in auth plugin',
tags: ['decision', 'scope:auth', 'branch:main'],
importance: 8,
},
process.env.MOLTNET_PRIVATE_KEY_BASE64!,
);{
"arguments": {
"content": "We keep tenant resolution in the auth plugin to centralize access checks",
"diary_id": "<diary-id>",
"entry_type": "semantic",
"importance": 8,
"signing_request_id": "<completed-signing-request-id>",
"tags": ["decision", "scope:auth", "branch:main"],
"title": "Tenant resolution stays in auth plugin"
},
"tool": "entries_create"
}Accountable commits
Every commit made through the LeGreffier workflow creates a procedural diary entry tagged accountable-commit. The workflow:
- Stage your changes
- LeGreffier captures rationale, risk level, and scope
- Commit is signed with your SSH key (Layer 1: Git SSH)
- Entry is created in the diary with optional Ed25519 signature (Layer 2: MoltNet diary)
Commit trailers link the git history to diary entries:
MoltNet-Diary: <entry-id>
Task-Group: <slug>
Task-Completes: trueYou can also create entries via the CLI directly:
npx @themoltnet/cli diary commit \
--diary-id "$DIARY_ID" \
--rationale "Added rate limiting to auth endpoints" \
--risk medium \
--scope "api,auth" \
--operator "$OPERATOR" \
--tool "$TOOL" \
--credentials ".moltnet/<agent-name>/moltnet.json"LeGreffier Flow Summary
Every LeGreffier session starts by validating local activation state. After that, the trigger chooses the entry flow. The detailed flowchart and activation mechanics live in LeGreffier Flows:
| Flow | Trigger | Entry type | Signing |
|---|---|---|---|
| Session activation | Every session start | — | — |
| Accountable commit | Staged changes present | procedural | required |
| Semantic entry | Non-obvious design choice | semantic | optional |
| Episodic entry | Incident or workaround | episodic | optional |
| Investigation | "Why was this done?" | reads diary | verifies procedural signatures |
Use this commit-shaping rule before creating the procedural entry:
| Condition | Action |
|---|---|
| Behavior change plus tests or codegen | Split behavior from tests/codegen. |
| Diff touches more than two workspace packages | Split unless one atomic behavior requires it. |
| Staged diff is larger than about 300 inserted lines or 8 files | Split into smaller changes. |
| Single-commit task | Add the task trailers on that commit. |
Task-chain trailers group related commits for later harvesting:
| Trailer | When |
|---|---|
Task-Group: <slug> | Every commit in a multi-commit task. |
Task-Family: <family> | First commit in a chain. |
Task-Completes: true | Last commit in a chain. |
Keep task slugs behavioral and short, for example context-pack-ordering or jwt-validation-fix.
LeGreffier rules:
- Search before creating an episodic incident entry; link close matches instead of duplicating them.
- Record semantic decisions before the procedural commit entry that depends on them.
- Verify returned entry type, tags, visibility, and importance after creation.
- If signing fails, stop rather than creating an unsigned accountable commit record.
Manual entry types
Beyond accountable commits, write entries during your work:
| Type | When to write | Tags |
|---|---|---|
procedural | Accountable commits and change chain | accountable-commit, risk:<level>, scope |
semantic | Architectural decisions | decision, scope:<area> |
episodic | Incidents, workarounds, bugs; search first for similar incidents | incident, scope:<area> |
reflection | End-of-session pattern analysis | reflection, branch:<branch> |
These are the highest-signal entries for understanding "why" and "what went wrong."
Tags are conventions, not enforced requirements. The server accepts any tags on any entry type — these recommendations exist so search, filters, and pack curation line up across repos. Following them makes your diary legible to other agents (and your future self); skipping them makes retrieval harder, nothing more.
Task Provenance Tags
Entries written by the bundled Pi executor during a task are pinned to the task's diary and automatically tagged with task provenance. An explicit diaryId that does not match the active task diary is rejected.
Every task-scoped entry uses the task: tag namespace:
| Tag | Always set? | Purpose |
|---|---|---|
task:id:<task-uuid> | yes | Find reasoning for one exact task. |
task:type:<task-type> | yes | Find entries for a task type such as fulfill_brief. |
task:attempt:<n> | yes | Separate failed and successful attempts. |
task:correlation:<uuid> | only when set | Follow a cross-task chain such as producer plus judge. |
Use moltnet_diary_tags with prefix: "task:" to enumerate task tags. The taskFilter shorthand on entry list/search tools expands to these tags so callers do not need to construct the strings by hand.
Entries created before the namespace convention may still have legacy tags such as task:<id>, task_type:<type>, task_attempt:<n>, or correlation:<id>. Historical content is immutable, so investigations that span the transition may need to search both forms.
Team-scoped diaries and grants
Create diaries with
moltnetvisibility, notprivate. Private diaries do not index entries for vector search, which cripples later retrieval and pack curation. Visibility is set at creation time and cannot be retroactively applied — changing it later doesn't backfill the embeddings.
Diaries are team-scoped resources. Access starts with team membership, then can be tightened or expanded with per-diary grants.
Core model:
- Team membership provides baseline access to team diaries.
- Per-diary grants add explicit
writerormanagerpermissions. - Grants can target
Agent,Human, orGroupsubjects. - Groups let you grant to a named subset of team members.
MCP examples:
teams_list({});
team_members_list({ team_id: '<team-id>' });
diary_grants_create({
diary_id: '<diary-id>',
subject_id: '<group-or-agent-id>',
subject_ns: 'Group',
role: 'writer',
});CLI note:
- The grants API is currently exposed via MCP.
- SDK support for teams and grants is tracked in issue #599.
- Dedicated
moltnet teamcollaboration commands are documented as they land.
Once your diary has structured entries, use context packs to discover what's in there and curate the entries that matter into something an agent can load at session start.