---
name: nessie
description: Access the user's personal context layer from an AI agent session. Use when the user references prior work, asks what they know about a topic, needs answers grounded in past AI conversations, or wants Nessie to generate a structured context. Agents can search transcripts, read contexts, answer questions, and create or update contexts.
---

# IMPORTANT: Codex Sandbox - `nessie` Must Escape It

Codex runs shell commands in a sandbox by default (`workspace-write`, network
disabled, no writes outside the working directory). The `nessie` CLI talks to
the Nessie macOS app over a localhost socket and reads/writes files outside the
workspace, so **every `nessie` invocation must run with escalated permissions**
or it may fail with sandbox or network errors that are not real Nessie failures.

When you call the shell tool to run any `nessie ...` command:

1. Set `with_escalated_permissions: true` on the call.
2. Provide a short justification, e.g. `"nessie CLI requires localhost network + access to ~/Library/Application Support/Nessie"`.
3. If a command fails with a sandbox / permission denied / network unreachable error, retry the same command with escalated permissions before reporting a Nessie failure.

# Nessie Skill

When this skill is invoked, always use the local `nessie` CLI through the
shell. Do not use Nessie MCP tools exposed by other connector surfaces; those
belong to the MCP connector surface, not the CLI skill surface.

The only Codex-specific rule is the sandbox rule above: every `nessie` command,
including read-only commands like `nessie status`, `nessie ls`, `nessie grep`,
and `nessie cat`, must use escalated permissions.

---

# Nessie Agent Behavior

This is the shared behavior guide for agent surfaces that read from or write to
Nessie. Interface-specific docs should explain how to operate a surface, but
the product semantics below should stay consistent across CLI skills, MCP
connectors, and future agent integrations.

## Mental Model

Nessie is the user's personal context layer. It gives agents access to saved
contexts, profile sections, raw AI conversation transcripts, and synced source
graphs such as Obsidian vaults and Granola meeting notes so they can answer
questions, reconstruct prior decisions, and preserve durable knowledge for
future sessions.

When the user says "use Nessie" or asks what Nessie can do, lead with the
agent-access mental model:

> I can use Nessie to browse the sources you have connected, search your past
> AI conversations and notes, read your saved contexts, and bring that context
> into this agent session. You can ask a question, ask for a brief or memo, or
> ask me to generate a structured context when you want something reusable.

The user does not need to switch into the Nessie app before getting value.
Treat their natural-language request as the interface: search what Nessie
knows, read the relevant sources, and answer directly. Context generation is
one powerful capability, not the only way to use Nessie.

Nessie builds context by analyzing the user's AI conversation history across
supported AI providers, including chat apps, coding agents, and research tools.
It can also expose connected source graphs, such as Obsidian vaults with
folders and notes, or Granola meeting notes organized into folders, when those
sources are synced.

## Default User Experience

When a user asks what Nessie can do, explain that Nessie gives agents access
to the context they have already built. Give generic examples of normal
back-and-forth use:

- "What do I know about this topic?"
- "What did I decide about this project?"
- "Summarize my past conversations about this topic."
- "Show me what sources Nessie has available."
- "Search my Obsidian notes about this project."
- "What have I already tried for this bug?"
- "Use what I know from Nessie and help me draft this reply."

It is fine to show a command or tool table when it helps the user understand
the tooling. Do not frame context generation as the only or default thing the
user should ask for. Many requests are answered through research,
source-reading, and back-and-forth synthesis in the agent session; context
generation is for deeper or reusable outputs.

## Search Strategy

Use source browsing before search when the user asks what is available, wants
to inspect a vault or folder, or is unsure which source world contains the
answer. Source listing is the "ls" affordance: it shows connected source
groups, root nodes, and folder-like children without requiring a query.

For navigational queries - when the user asks for a specific artifact by name
(task log, daily journal, a specific file) - prefer source browsing over
search. Navigate directly to the relevant folder and read the latest entry.
These artifacts often live in synced note sources, not in contexts or
transcripts, so searching contexts alone will miss them.

Choose the source order from the user's intent, not from a global ranking:

- Discovery, navigation, and "what sources exist" requests should start by
  listing source roots and traversing hierarchies.
- Specific files, notes, journals, task logs, and memos should start in the
  relevant source hierarchy. For Obsidian, browse vaults and folders first when
  the user gives a path-like or artifact-like clue.
- Knowledge questions about something the user has researched should use
  contexts for synthesized orientation, then read primary sources when freshness,
  provenance, or deeper detail matters.
- Latest/current-development questions should be grounded in recent source
  activity, especially recent transcripts. Use stale contexts only as
  orientation, then search or browse recent transcripts and notes broadly enough
  to synthesize what changed.
- Verification and exact grounding should read primary sources. Use transcripts
  for what happened in AI conversations, and notes for user-authored or
  user-maintained material.
- Resume and takeover requests should be transcript-first, with beginning and
  recent-tail reads before synthesis.

Context search is an orientation tool, not the universal first step. A matching
context often gives the compiled picture quickly, but it may be stale or omit
details that live only in primary sources. Obsidian notes and conversation
transcripts are not fallback sources when the user's request clearly points to
them.

For topics with multiple relevant contexts, one context is often not enough.
Read the obviously relevant context results, compare their recency metadata,
and check recent transcripts before making a strong claim. A stale context is
orientation, not the final answer.

For questions like "latest developments on X", "what changed recently", "where
are we now", or "what is the current state", do not stop at existing contexts.
Start with recent source discovery and recent transcript search for the relevant
project, product, people, repository, issue, or distinctive terms. Read several
recent matching conversations or notes, including relevant tail windows for long
transcripts, and synthesize across them. Existing contexts can explain the
background, but recent primary sources establish the latest state.

For broad discovery where you are unsure what source worlds exist, list
available sources first. Then search the relevant source types for the user's
intent rather than defaulting to contexts.

Run multiple searches with related terms when the first query is too narrow:
names, companies, product names, distinctive wording, and likely synonyms.

After searching, always read full content with the appropriate context,
transcript, note, folder, or profile reader. Search results are starting
points, not answers.

When a search result or transcript chunk cuts off mid-sentence or mid-thought,
paginate forward with the source document reader. Do not run another search,
guess at the missing content, or report "I don't know" when you have the
document ID and chunk index to continue reading from. A cutoff is a signal to
keep reading, not to stop.

## Source Authority Hierarchy

Source types serve different purposes:

- Contexts are compiled knowledge: synthesized, structured summaries of what
  the user knows about a topic. Use them for orientation and reusable summaries
  when the user asks a knowledge question. They may be stale, so verify
  freshness by checking the context date against recent activity and primary
  sources when the answer depends on current or exact details.
- Conversation transcripts are ground truth for the user's actual AI
  conversations: words, decisions, and thinking as they happened. Use
  transcripts to verify context claims, fill in details, or when no context
  exists.
- Obsidian notes are user-authored or user-maintained source material. Use
  them when the user refers to notes, vaults, files, memos, source docs, or
  asks for project knowledge that likely lives outside AI transcripts. Preserve
  their path and hierarchy when citing or selecting them.
- Granola notes are AI-generated summaries of the user's recorded meetings,
  organized into folders. Use them when the user refers to a meeting, call,
  interview, or who-said-what, or asks for decisions and action items from a
  conversation that happened on a call rather than in an AI chat. Browse granola
  folders to find a meeting; reading a note returns its AI meeting summary, and
  the raw transcript turns are indexed for search (they surface under transcript
  or all-type search), not as browsable child nodes.
- Profile sections contain structured biographical facts about the user. Check
  the profile for identity, connections, project info, and other recurring
  personal context.

For discovery: browse source roots and hierarchies first.
For synthesized orientation: read relevant contexts.
For verification: primary sources are authoritative over contexts. Prefer
transcripts for claims about what happened in conversations, and notes for
claims about user-authored source material.
For creation: ground new contexts in primary-source evidence, not only in other
contexts.

## Authenticated User and Personal Sources

For first-person questions such as "what did I do", "what am I working on",
"what did I decide", "who am I", "my recent work", or "what do you know about
me", treat the authenticated user's own profile and personal source roots as
the primary scope.

Start with profile or check-in data for orientation when the surface exposes
it. Profile data may be sparse or incomplete; do not stop there. If the profile
does not answer the question, list the user's source roots and inspect their
personal transcript or note roots. Browse or search within those personal roots
before falling back to broad global search.

Do not use team-shared roots as the default scope for first-person questions.
Use team and team-shared roots when the user asks about a teammate by name,
asks about shared team work, or explicitly asks to compare their work with
someone else's.

When a surface exposes an owner or source-owner selector, leave it omitted or
set it to `current_user` / `me` for first-person questions. Pass an explicit
teammate identifier, teammate email, or `team` only when the user asks for that
person's sources or shared team scope.

Use `sourceOwner` as the sole authority for source ownership, owner scoping,
and profile inclusion. It identifies whose source/transcript was queried; it is
not semantic proof that the source owner personally did every business task
mentioned inside the content. Read the content before attributing work. Treat
integration/provider/account fields as provenance and debugging context only;
never infer who owns a source from an integration display name, device label,
provider account email, or account name. A current user's ChatGPT, Claude,
Codex, or other provider account may use a different email or machine label
while still being owned by the current Nessie user.

## Temporal Interpretation

For relative date phrases such as "today", "yesterday", "this week", "last
week", or "so far", resolve the time window in the user's local timezone before
filtering Nessie sources. The local CLI can parse date-only filters using the
Mac's current timezone. Hosted MCP surfaces should pass date-only filters with
`since` and `until` as `yyyy-mm-dd` values plus an explicit IANA timezone so
the MCP server can resolve the local window programmatically.

If the surface exposes a user timezone, use it. If no reliable user timezone is
available and the date boundary matters, ask the user or state the timezone
assumption before applying a strict date filter. Prefer recent-source browsing
or a wider window over silently using UTC for first-person "today" questions.

## Query Interpretation

Before searching, infer the likely purpose and scope:

- Identity and relationship queries ("who are my collaborators", "what tools do
  I use") need broad searches with related names and terms. These answers
  accumulate over time.
- Topics with several plausible sources need multiple relevant contexts, recency
  comparison, and recent transcript checks before answering. Do not infer from
  the first matching context or external information alone.
- Queries with temporal signals ("recent", "lately", "this week") should prefer
  recent conversations and notes, then read them. Existing contexts are
  background only until checked against recent primary sources.
- Current-state queries ("what am I working on") should prefer recent content
  without excluding older foundational context.
- Latest-development queries ("latest developments on Nessie", "what changed
  recently on X", "where are we now") need a broad synthesis over recent
  transcript/source activity. Search multiple related terms, read several recent
  sources, and compare against any existing context before answering.
- Open-ended exploration ("what have I learned about X") should start with a
  broad search and expand with more specific searches if results are thin.
- Generation with audience ("brief for my team", "summary for my team") should
  infer purpose, audience, and tone before researching.
- Agent takeover or resume requests ("take over this session", "resume this
  Claude/Codex conversation", "continue from this transcript", "here is a
  session ID") need transcript-first reading. The relevant work is often near
  the end of a long conversation, so do not stop after reading the beginning.
- When uncertain, run a few searches with exact names, related terms, and
  broader conceptual phrases. Synthesize across the results.

## Agent Takeover / Resume

Use this workflow when the user asks an agent to take over, resume, continue,
or recover context from a prior AI session, especially when they provide a
session, transcript, node, or conversation ID.

1. Identify the target conversation or source node. If the user gave an ID,
   read that node directly. If they gave a title, project, tool, teammate,
   date, or workspace, search and browse until you find the matching recent
   conversation.
2. Read both the beginning and the end before synthesizing. The beginning
   usually explains the goal and constraints; the end usually contains the
   current state, latest decisions, open blockers, and uncommitted next steps.
3. Bias toward the tail for handoff state. For long transcripts, read the last
   available page or chunk window first after a light beginning skim, then page
   backward until the latest work is coherent. Do not assume offset 0 is the
   most important part of an old session.
4. Search within or around the transcript for distinctive terms from the recent
   tail, such as file paths, branch names, issue IDs, errors, people, or
   project names. Read adjacent chunks when results land in the middle.
5. Produce a compact takeover brief before acting: goal, current state, files
   or artifacts touched, decisions made, blockers, and exact next actions. Then
   continue the user's requested work from that brief.

If the session is too long to read fully, say that you read the beginning, the
recent tail, and the relevant middle sections you found by search. Be explicit
about any remaining uncertainty rather than presenting a partial read as a full
resume.

## Core Loop: Read -> Respond -> Optional Write Back

On every Nessie invocation, follow this loop:

1. Read first. Before responding, search Nessie for relevant context. Use the
   source order implied by the user's intent: browse source hierarchies for
   discovery, read contexts for synthesized orientation, and read primary
   sources for verification or exact grounding. Read matching documents in full.
   The response is better when grounded in what Nessie already knows.
2. Respond with Nessie context. Use what you found to inform the answer. Surface
   relationships, prior discussions, and cross-references the user may have
   forgotten.
3. Optionally write back if new information emerged. After the exchange, if the
   conversation produced durable new knowledge, handle the write-back for the
   user or offer it proactively:
   - Update the relevant context when a targeted addition is enough.
   - Create a new context if no existing one covers the topic.
   - Update the user's profile if biographical facts changed.
   Do not make this sound like maintenance the user has to remember. Frame it
   as: "I can save this back to Nessie so future sessions can pick it up."

## When to Use

1. Start of session: read the profile to understand the user. If profile data
   is sparse, inspect the user's personal source roots and recent transcripts
   before concluding Nessie lacks information about them.
2. User references prior work: use contexts for orientation when the request is
   a knowledge question, but start with source browsing or primary-source search
   when the prior work likely lives in files, memos, vaults, source documents,
   or a specific conversation. Read full content, not just snippets.
3. User asks "what do I know about X": search contexts for the compiled
   picture, then read transcripts or notes for verification, freshness, or
   deeper detail.
4. User asks about past conversations: search transcripts for matching
   conversations, then read the relevant transcript content.
5. User asks what sources are available or asks to browse a connected source:
   list source groups or children before searching.
6. Synthesizing answers or new knowledge: follow the manual research workflow
   at the right depth for the request. Save a context only when the user asks
   for a reusable artifact or the exchange produced durable new knowledge worth
   preserving.
7. Organizing contexts: use context and folder organization operations to help
   the user organize their context library.
8. Accessing and updating the profile: use profile operations to read what
   Nessie has built so far and update it when new information emerges about the
   user, such as a new job, new connection, changed project status, or new
   decision.

## Manual Research Workflow

This workflow mirrors the Nessie backend agent's context generation flow. When
the user asks you to research a topic and produce a structured output, follow
these steps. Every step is mandatory for substantial synthesis.

### Step 1: Interpret the Query

Infer purpose, audience, and time scope. Decompose the topic into facets:

- A person query needs their name, company or role, related people, relevant
  events, and key dates. Always start by checking profile or connection data
  when available. Use that as your starting point before searching transcripts.
- A product or project query needs the product name, related decisions,
  adjacent products or projects, and evolution over time.
- A relationship query needs both parties, the timeline, key interactions, and
  current status. Check profile connections for both parties first when
  relevant.

### Step 2: Search Broadly

Cast a wide net with multiple searches. A single search is almost never
sufficient.

- List source groups or source children when the user asks what is available,
  references a vault or folder, or you need to understand a source hierarchy.
- Search exact names or terms in contexts when compiled knowledge would help
  orient the task.
- Search exact names or terms in transcripts and notes when primary-source
  verification is needed, no context exists, or the user asks about artifacts,
  notes, files, conversations, task logs, journals, or other source material.
- Search broader conceptual topics when you are unsure what exists.
- Search related terms separately. If researching a person, also search their
  company, related people, and relevant events.
- When a topic can be described several ways, search the user's wording plus
  obvious alternate names or related terms before concluding that sources are
  unrelated or newly changed.

### Step 3: Read Deeply

Search results are breadcrumbs, not answers. Search snippets are short excerpts
from conversations that may span thousands of words. Read full sources before
synthesizing.

For each relevant search result:

- Read the full transcript or relevant paginated transcript sections.
- Read full synced notes when note results match the task.
- Read relevant existing contexts in full.
- Read at least 3-5 full sources before synthesizing when enough sources exist.
- If multiple contexts match the same entity or topic, read the relevant set;
  do not stop at the first context that confirms a plausible answer.
- Conversations often build over many exchanges. Read enough to understand the
  full picture.

If you create a context based only on search snippets without reading full
sources, the output will be thin and missing critical details. This is not
acceptable.

### Step 4: Cross-Reference and Synthesize

Follow threads across multiple conversations and contexts. Surface patterns,
timelines, contradictions, and insights that no single source contains alone.
If a transcript mentions another person, event, or decision, search for that
too.

### Step 5: Save with Editorial Judgment

Save only structured, source-grounded work. The body should be useful prose:
headers, bullets, narrative paragraphs, dates, names, and concrete details when
they matter. Every claim should trace back to something you actually read in
full.

Do not include the context title as the first H1 in the body. Nessie stores
titles separately from context body markdown.

When creating a context from Nessie research, attach the document IDs of every
transcript and context read during research. Without provenance, the user cannot
trace claims back to original conversations.

Output quality rules:

- Thoroughness over brevity. Capture substance, nuance, and key details. A thin
  summary is not useful. Err on the side of comprehensive; the user can ask for
  edits later.
- Specific details, not vague summaries. Include dates, quotes, amounts, and
  names when they matter.
- Every claim must trace to a specific source. While drafting, mentally tag each
  claim with the source document ID it came from. If you cannot identify which
  source supports a claim, do not include it.
- Relevance filtering. A search match does not automatically earn inclusion.
  Ask whether it serves the purpose of the context.
- Match tone to audience. Use professional tone for external stakeholders,
  casual tone for personal notes, and precise tone for technical briefs.

### Multi-Person Attribution

When a transcript discusses multiple people, verify who said or did what before
attributing. Names appearing in the same document do not mean the same person
said everything. When uncertain, ask the user to confirm.

### Epistemic Rules

Only state something as a biographical fact about a real person if the user
explicitly established it as true.

When synthesizing content from conversations, distinguish between:

1. User statements of fact: things the user explicitly said are true about
   themselves or someone they know. State these as facts in the context.
2. User questions and hypotheticals: explorations, not assertions. The user
   asking about something does not mean it is true. Never convert a question
   into a stated fact.
3. External information the user analyzed: research, articles, or data the user
   looked up. This is reference material, not biographical fact.

Use "discussed", "explored", "asked about", or "researched" for anything that
is not an explicitly established biographical fact.

## Generated vs Manual Research

Generated context research is available only on surfaces that expose Nessie's
backend generation workflow, such as the app and CLI. Adapter-specific
instructions may narrow this guidance when a surface does not expose that
workflow.

Use generated context research when:

- The user wants a comprehensive brief, memo, summary, or prep doc grounded
  purely in their conversation history.
- The task needs synthesis across their overall history or profile, and manual
  search is likely to overfit to granular transcript citations.
- You need higher-accuracy synthesis from Nessie's backend research agent.
- The user pushes back on manual output quality after multiple rounds.

Use the manual research workflow when:

- You need to combine Nessie data with external information or code context.
- You want to control exactly which sources are consulted.
- You are answering a question directly in the agent session and need to search,
  read, and synthesize from Nessie sources before responding.
- You are creating a context that synthesizes across Nessie data and other
  sources such as files, web, or codebase context.

Both workflows have the same source authority rules. Manual research gives you
control over exactly which sources to read and how to synthesize them. Use
pagination when reading long transcripts rather than loading everything at once.
Generated context research re-runs research from scratch, so treat it as a
deliberate escalation for deeper synthesis rather than the default next step
after every manual answer.

Never search once, skim snippets, and save a context. This produces thin,
unreliable output that misses critical details the user expects.

Do not keep forcing a manual answer after the user has pushed back on quality.
If the task needs deeper synthesis or the user is not satisfied after multiple
rounds, use a generated research workflow when available and incorporate that
output.

## Auto Write-Back

This is step 3 of the core loop. After any substantive exchange where new
information emerged about a topic Nessie tracks:

- Prompt naturally. If there are durable takeaways, offer to save them back to
  Nessie or just do it when the user has asked you to preserve the work. The
  user should not feel responsible for manual library maintenance.
- Existing context on the topic? Add the new information to that context.
  Targeted edits are better than full rewrites.
- No existing context? If the research was substantial, with 3+ sources read
  and meaningful synthesis, offer to create one. Keep the prompt simple:
  "Want me to save this back to Nessie for next time?"
- Profile changed? Update the relevant profile section or card.

When creating new contexts, search for existing ones on the topic first to
avoid duplicates. Use file-backed body inputs when available for creation to
avoid escaping issues with special characters. Organize into an appropriate
folder.

## Non-Destructive Operations

Context operations should be additive whenever possible:

- Do not delete contexts to "replace" them. If consolidating multiple contexts
  into one, create the new context first, verify it captures all information,
  and only delete originals after explicit user confirmation.
- Use targeted edits for corrections and additions. When correcting or updating
  part of a context, replace specific text rather than deleting and recreating
  the entire context.
- Do not overwrite without preserving. If updating a context, the original
  information should not be lost.
- Prefer creating alongside, not instead of. If the user has existing contexts
  on a topic, create your new synthesis as a separate context rather than
  deleting and replacing the originals.

---

# Nessie CLI Adapter

This is the CLI adapter section for agent surfaces that call the local
`nessie` CLI.

## Operating Model

The CLI talks to the Nessie macOS app over localhost and reads or writes the
app's local data. The app must be running before CLI commands can succeed.
Check with:

```bash
nessie status
```

CLI surfaces should document their own sandbox or permission requirements. For
Codex, every `nessie` command must run with escalated permissions because the
CLI needs localhost networking and access outside the workspace.

## Filesystem Model

The CLI exposes Nessie as a filesystem and uses Unix coreutil verbs. Everything
the product calls a "source" — an integration root, an Obsidian vault or folder,
a Granola folder, a synced transcript, a saved context, a profile section, a
single chat message — is a **node** addressed by its UUID (the node's identity,
like an inode). There are no path strings yet; you navigate by UUID.

Two node roles, mapped to Unix:

- **Directories** are container nodes (integration roots, vaults, folders).
  List them with `ls`. They have no readable body.
- **Files** are readable nodes (contexts, notes, transcripts, messages). Read
  them with `cat`, `head`, or `tail`.

A node can be **both** at once. A `granola_note` is a readable meeting summary
*and* a container for the meeting transcript. `ls` shows the raw `kind` rather
than a single file/dir bit for exactly this reason; the read commands decide
container-ness internally and will tell you to use `ls` if you `cat` a pure
directory.

The verb map:

| Read / navigate | Write |
| --- | --- |
| `ls` — list a directory (or the roots) | `mkdir` — create a folder |
| `cat` — read a file in full | `tee` — create a context |
| `head` / `tail` — read the first/last N lines | `sed` — string-replace a context body |
| `stat` — metadata only, no body | `mv` — move / rename / unfile a context |
| `grep` — search content in a subtree | `rm` — delete a context |
| | `rmdir` — delete an empty folder |
| | `generate` — research-and-create a context |

`ls`/`cat`/`head`/`tail`/`stat`/`grep` are the documented contract for reading.
The older namespaced commands (`nessie source ...`, `nessie node ...`,
`nessie search`, `nessie transcript ...`, `nessie context ...`, `nessie folder
...`) still work and map onto the same endpoints, but prefer the coreutil verbs.
`nessie check-in`, `nessie profile`, `nessie team list`, and `nessie
integration list` are not filesystem operations and keep their own names.

## Check-In

```bash
nessie check-in
nessie check-in --recent-limit 10
nessie check-in --hook
```

Use `nessie check-in` when the user starts with "Nessie check-in", says "check
in with Nessie", asks to load their Nessie context before continuing, or when a
local agent session needs a compact startup briefing. The command returns the
user's generated profile sections plus recent Nessie activity. `--recent-limit`
defaults to 10 and accepts values from 1 through 25.

Use `nessie check-in --hook` only from Claude Code or Codex `SessionStart` hook
configuration. In hook mode, the CLI emits the host hook JSON payload with
`hookSpecificOutput.additionalContext`; it does not print the raw check-in
response. The hook is fail-closed: if the Nessie app is closed, too old, or
unreachable, it emits no context rather than blocking session startup.

## Navigating: ls and stat

```bash
nessie ls                                   # source roots (no parent)
nessie ls <node-id>                         # direct children of a directory
nessie ls <node-id> --type transcript       # children filtered by type/kind
nessie ls <node-id> --since 2026-05-30 --until 2026-05-31
nessie ls --owner team                      # roots across the whole team
nessie ls <node-id> --limit 100 --offset 0
nessie ls <node-id> --json                  # raw JSON instead of the table
nessie stat <node-id>                        # metadata only, files or dirs
```

`ls` is the first-class browser and the equivalent of Unix `ls`. With no
argument it lists the **roots**: connected integration roots, the virtual
Contexts root, and team-shared roots — not a flat document feed. Integration
roots created with the same API key are combined into one entry, the way the
app groups them. Pass a directory UUID to list its direct children, then drill
in by listing a child's UUID.

`ls` prints an aligned table: `kind  owner  updated  id  name`. `kind` is the
raw `NodeKind`. `owner` shows `me` or the owner's email. Copy the `id` to read,
search, or list deeper.

`stat` prints a node's metadata (kind, owner, counts, dates) without dumping its
content. Use it to size a node or inspect a directory before reading.

Filters (shared with `grep`):

- `--type` — a group (`context`, `transcript`, `profile`, `obsidian`,
  `granola`) or a raw node kind (`claude_code_chat`, `codex_chat`,
  `obsidian_note`, `granola_note`).
- `--since` / `--until` — recency window. Both accept ISO-8601 timestamps or
  `yyyy-mm-dd` dates. Date-only filters are resolved in the local Mac timezone,
  matching the user's "today"/"yesterday" expectation, so no timezone flag is
  needed. A date-only `--until` resolves to the local day's final second; pass a
  full ISO timestamp when you need sub-second end-of-day precision.
- `--limit` / `--offset` — pagination. `ls` defaults to 100, max 500.
- `--owner` — Nessie source owner scope; see below.

There is no `find` or `ls -r` yet. To search a whole subtree by content, scope a
`grep` to the parent UUID rather than walking it directory by directory.

### Owner scope

Discovery and search default to **everything you can read** — your own sources
plus team-shared (`ls`, `grep`, and the root listing all default this way). To
narrow to just your own sources, pass `--owner me` / `--owner current_user`. Pass
a teammate user ID or email (`--owner tiger@nessielabs.com`) only when the
user asks about that teammate's sources. To resolve a named teammate, run
`nessie team list` or `nessie integration list --status team_remote` first, then
pass the member `userId` / resource `ownerUserId` with `--owner`. Email
selectors resolve only from existing team-member email metadata; an unknown
email returns an invalid-input error rather than empty results.

Use `sourceOwner` on a returned descriptor as the **only** ownership and scoping
signal — it tells you whose source this is, not who semantically performed every
task mentioned inside it. Read the content before assigning work to a person.
Treat `integration` fields (`accountName`, `providerName`, `deviceId`, provider
labels) as provenance only; do not decide whether a result is "mine" or
"Tiger's" from an integration account email or display name, which can differ
from the authenticated Nessie owner.

## Teams and Integrations

```bash
nessie team list
nessie integration list
nessie integration list --platform claude_code
nessie integration list --status team_remote
nessie integration list --team-id <team-id>
```

Use these to resolve team-shared work and named teammates before scoping an `ls`
or `grep`. `team list` returns teams, members, and shared resources.
`integration list` returns connected and team-shared roots with provenance
fields such as `teamId`, `teamName`, `ownerUserId`, `ownerDisplayName`,
`ownerEmail`, `status`, `deviceId`, `platform`, and provider labels. For "what
did Tiger do yesterday?", start here, identify Tiger's shared root and
`ownerUserId`, then `nessie grep "<topic>" <root-id> --owner <tiger-user-id>` or
`nessie ls <root-id> --owner <tiger-user-id> --since/--until`.

Do not use team-shared roots as the default for first-person questions about
"me" or "my work"; personal roots are the primary scope for the authenticated
user.

## Reading: cat, head, tail

```bash
nessie cat <node-id>             # full content, no length cap
nessie head <node-id>            # first 10 lines
nessie head <node-id> -n 40      # first 40 lines (--lines also works)
nessie tail <node-id>            # last 10 lines
nessie tail <node-id> -n 40      # last 40 lines
```

`cat` prints a node's readable content as raw text — no JSON wrapper. It works
on contexts, Obsidian notes, Granola summaries, whole transcripts, and a single
chat message. It has **no length cap**: a long transcript prints in full.

`head` and `tail` print the first or last N lines (default 10) and read only
enough from that edge, so they are cheap on large transcripts where `cat` would
be expensive. Lines are faithful for both regular slice content (a note, one
message) and the special whole-chat-transcript case.

All three reject a pure container (e.g. an integration root) with an
"is a directory" error pointing you back to `ls`. For nodes that are both file
and directory, the read commands return the readable body.

## Searching: grep

```bash
nessie grep "<query>"                         # hybrid search, everything you can read
nessie grep "<query>" <parent-id>             # scope to a subtree
nessie grep "<query>" --type transcript
nessie grep "<query>" --type obsidian -F      # fixed-string (literal) match
nessie grep "<query>" --since 2026-05-30 --until 2026-05-31
nessie grep "<query>" --owner me              # narrow to just your own sources
nessie grep "<query>" --owner <teammate-user-id>
nessie grep "<query>" --repo .                 # only the current git repo
nessie grep "<query>" --repo github.com/org/repo
nessie grep "<query>" --limit 20
```

`grep` searches node content and is the recursive-search affordance: the
optional second positional argument is a parent UUID that scopes the search to
that node and all its descendants. It is the right tool for "find X anywhere
under this vault / root / folder" because there is no `find` yet.

It searches hybrid (semantic + keyword) by default. Pass `-F` / `--literal` for
fixed-string matching when the user asks which documents contain an exact quoted
or exact wording; literal matches the whole query as one contiguous substring,
so split a multi-word natural-language request into salient exact terms instead
of treating it as one phrase. Results are grouped by document with the matching
content and carry `sourceOwner` for attribution. `--limit` defaults to 10, max
500. `--type`, `--since`, `--until`, and `--owner` behave as for `ls`.

Search is a starting point, not an answer. One `grep` is rarely enough: vary the
wording and search related names and topics separately, and run several searches
(serially — see the caution below) before you conclude. For each relevant hit,
`cat` (or `head`/`tail` for long nodes) the full node before synthesizing — read
several matching sources, not just the first, and follow threads into the people,
events, and decisions they mention. Do not stop at the first node that confirms a
plausible answer; the fullest discussion is often not the top hit. If a chunk
cuts off mid-thought, read more of that node.

`--repo` narrows to specific git repos — pass a repo path (`.` for the repo you
are working in) or a canonical repoKey like `github.com/org/repo`; repeatable, or
comma-separated. It can only narrow, never widen. Because the repo identity lives
only on coding-session content, **any `--repo` filter excludes everything that
isn't tied to a git repo** (notes, meeting transcripts, profile sections). Use it
to scope a search to the code you are working on; drop it to search everything.

If `grep` reports `truncated: true`, the scope hit an internal safety cap before
searching; narrow it with a smaller `--since`/`--until` window, a more specific
parent UUID, or a narrower `--type`, then retry. `scopeNodeCount` reports how
many nodes were in scope.

Local CLI search does not support concurrent requests. Never fan out multiple
`nessie grep` commands in parallel — run them serially and wait for each to
finish. Concurrent local searches can slow each other enough to time out and may
be misreported as "Nessie is not running" even when the app is open.

## Agent Takeover / Resume

For "Nessie resume", "Nessie takeover", "resume this Claude/Codex session", or a
pasted conversation/node ID, treat resume as a search-then-read workflow.

If the user gives a UUID, read a small beginning window and the recent tail:

```bash
nessie head <id> -n 5
nessie tail <id> -n 40
```

If the user gives no ID, find candidates from their clue (title, error, branch,
file path, project), then read the match the same way:

```bash
nessie grep "<user-provided clue>" --type transcript
```

The handoff state usually lives near the **end** of a long transcript, so bias
toward `tail`. If the tail references specific files, branches, errors, or
decisions, `grep` those terms (scoped to the transcript or its root) and `cat`
the adjacent nodes. Produce a compact takeover brief — goal, current state,
files touched, decisions, blockers, next actions — before continuing the work.

## Profile Access and Updates

```bash
nessie profile
nessie profile get
nessie profile get --section connections
nessie profile edit-field --field <field> --value "<value>"
nessie profile edit-text --section <section> --content "<markdown>"
nessie profile edit-text --section <section> --content-file <path>
nessie profile add-card --section <section> --fields '{"key":"value"}'
nessie profile update-card --section <section> --index <n> --updates '{"key":"value"}'
nessie profile remove-card --section <section> --index <n>
```

Profile commands return or edit the user's structured profile. The profile may
still be building for new users, so describe this as accessing and updating
their profile rather than assuming every section is complete. `nessie profile`
or `nessie profile get` returns the full profile; `--section` reads one section.

For first-person questions ("what did I do", "what am I working on", "who am I"),
start with `nessie profile` or `nessie check-in` for orientation, then drill
into raw sources with `nessie ls` / `nessie grep` if the profile is sparse.
Sparse profile data does not mean sparse raw data.

Scalar fields for `edit-field`: `name`, `preferredName`, `dateOfBirth`, `email`,
`phone`, `address`, `employer`, `jobTitle`.

Text sections for `edit-text`: `biography`, `communication`, `personality`.
These accept full markdown that replaces the section.

Card sections for `add-card`, `update-card`, `remove-card`: `education`,
`workExperience`, `connections`, `projects`, `decisions`, `expertise`,
`upcoming`.

Card fields:

- `education`: `school`, `degree`, `years`, `description`
- `workExperience`: `employer`, `title`, `years`, `description`
- `connections`: `name`, `shortDescription`, `description`
- `projects`: `name`, `status`, `description`, `techStack`
- `decisions`: `title`, `description`, `category`, `timeHorizon`, `date`
- `expertise`: `name`, `category`, `description`
- `upcoming`: `title`, `date`, `category`, `description`

Cards are identified by 0-based index within their section. Run
`nessie profile get --section <section>` to see current cards and indices before
updating or removing. For `add-card`, provide all fields; for `update-card`,
include only the fields you want to change. Profile changes are immediately
visible in the Nessie app.

## Writing: mkdir, tee, sed, mv, rm, rmdir

```bash
nessie mkdir "<name>" [<parent-folder-id>] [--emoji "<emoji>"]
echo "<markdown>" | nessie tee "<title>" [--emoji "<emoji>"] [--folder <folder-id>] [--sources <uuid1> <uuid2> ...]
nessie tee "<title>" --from-file <path> [--emoji "<emoji>"] [--folder <folder-id>] [--sources <uuid1> ...]
nessie sed <id> --old "<text to find>" --new "<replacement>" [--all]
nessie sed <id> --old-file <path> --new-file <path> [--all]
nessie mv <id> --to <folder-id>
nessie mv <id> --name "<new name>"
nessie mv <id> --unfiled
nessie rm <id>
nessie rmdir <folder-id>
```

These write to the user's context library. Folders organize contexts; contexts
are the user's saved context documents.

- `mkdir` creates a folder. Pass an optional parent folder ID to nest it inside
  another folder; omit it to create at the top level. `rmdir` deletes an
  **empty** folder — move or delete its contents first.
- `tee` creates a context. The markdown body comes from **stdin** (pipe or
  heredoc) or from `--from-file`; prefer `--from-file` when the body contains
  apostrophes, asterisks, or backslashes to avoid shell escaping. Do not put the
  title as an H1 at the top of the body — titles are stored separately, so start
  with the first real section. Include an `--emoji` that represents the topic.
  Always pass `--sources` with the document UUIDs of every transcript and
  context you read while researching; this creates the provenance badges that
  let the user trace claims back to original conversations. Without `--sources`
  there is no source badge. The context is indexed for search automatically.
- `sed` edits a context body by exact string replacement. The match must be
  unique unless `--all` is set. Prefer `--old-file` / `--new-file` when the text
  contains markdown, dashes, or special characters. Only contexts can be edited;
  transcripts and other documents are read-only.
- `mv` moves a context into a folder (`--to`), renames it (`--name`), or removes
  it from its folder (`--unfiled`). Provide exactly one.
- `rm` deletes a context by ID.

## generate

```bash
nessie generate "<prompt>"
```

`generate` has Nessie's backend research agent search the user's conversation
history and synthesize a structured context automatically. This takes 30-120
seconds. The backend agent generally produces higher-quality deep synthesis than
a manual workflow because it is optimized for context research and attribution.
Use it for comprehensive briefs, memos, or profile/history-level synthesis, or
when manual answers are not reaching the right abstraction. Because it re-runs
research from scratch, treat it as a deliberate escalation, not a default retry.

## CLI-Specific Cautions

Track source document IDs as you read; pass them with `--sources` when creating
contexts from Nessie research.

All read commands are instant local reads. Context creation is an instant local
write plus async embedding. All data is local to the user's machine; Nessie does
not send documents to external services for CLI reads and writes.

Transcripts are read-only. Do not try to modify synced conversation documents.
