---
title: "Keep CLI for notes and saved Markdown context | Keep"
description: "Save links, search Notes and Items, and read or update Markdown from any terminal."
canonical: "https://keep.md/docs/cli"
language: "en"
---

# Use Keep from your terminal

Save links, search Notes and Items, and read or update Markdown from any terminal.

The Keep CLI lets you search notes and saved items together from the terminal. You can also create and update Markdown notes or pipe saved content into another tool.

## Install

Code variants

```
npm i -g keep
keep --version
```

```
yarn global add keep
keep --version
```

```
pnpm add -g keep
keep --version
```

```
bun add -g keep
keep --version
```

Upgrading from the previous package name does not remove your Keep config or credentials:

```
npm uninstall -g keep-markdown
npm i -g keep
```

## Setup

Create a [Keep account](https://app.keep.md/signup), then sign in from your terminal:

```
keep login
keep auth status
```

`keep login` shows a short code and opens Keep in your browser. Check that the code matches, approve it, and the terminal finishes signing in. This client then has its own named, revocable credential. No API key required.

If an AI agent is setting up Keep for you, it should run `keep login` itself. You only need to sign in, check the code, and approve access in the browser.

Use the exact lowercase name for the current client:

| Current client | Login name |
| --- | --- |
| ChatGPT | `chatgpt` |
| Claude Code | `claude-code` |
| Claude Desktop | `claude-desktop` |
| Codex | `codex` |
| Cursor | `cursor` |
| OpenCode | `opencode` |
| Pi | `pi` |

Name the client to control how it appears in Note history, and use `--no-browser` on a machine that cannot open one:

```
keep login codex
keep login --no-browser
```

Credentials are stored in `~/.config/keep/config.json`, readable only by you. Keep detects Codex, Claude Code, and Cursor during login and selects their credentials automatically on later commands. The client name appears in Note history.

Older `claude` connections and optional session hooks continue to work as Claude Code. Claude Desktop always uses its separate `claude-desktop` connection.

Check or remove connections with:

```
keep auth status
keep auth list
keep auth remove codex
```

Connected clients can read and write library content, but cannot create more credentials. Revoking one does not affect your personal key or other clients. You can also pass a key inline with `--key` or set `KEEP_API_KEY` for a specific request.

In an interactive terminal, setup also offers to install the Keep skill. You can manage it later:

```
keep skill install
keep skill install --agent codex --global
keep skill install --copy --yes
keep skill status
keep skill update
```

Keep checks the installed skill at most once per day. Interactive commands can offer to update after they finish. Piped and `--json` commands print any update notice to stderr, leaving stdout unchanged for AI tools and scripts. Set `KEEP_NO_SKILL_UPDATE_CHECK=1` to disable these checks.

You can use a read-only [scoped key](https://keep.md/docs/api-keys) the same way. A scoped key only sees Items inside its scope. Write and delete commands are rejected.

## keep save

Save one URL. Add properties when you already know why it matters.

```
keep save https://suganthan.com/blog/webmcp-implementation-guide/
keep save https://github.com/iannuttall/seo --title "SEO CLI" --tags seo,agents --collection tools
keep save https://suganthan.com/blog/webmcp-implementation-guide/ --notes "Use this in the agent-ready web research Note" --no-summary
```

Options include `--title`, `--notes`, `--tags`, `--collection`, and `--no-summary`.

## keep sync

Bulk sync items from a JSON file.

```
keep sync ./items.json
```

The file can be either an array of item objects or an object with an `items` array.

## keep list

List your saved items. Archived items are excluded by default.

```
keep list
```

```
a1b2c3  https://suganthan.com/blog/webmcp-implementation-guide/  WebMCP implementation guide
d4e5f6  https://github.com/iannuttall/seo    SEO CLI
```

Filter by time, status, tags, or collection:

```
keep list --since 7d --status stashed,flagged --tag agent-tooling --collection x-articles --limit 20
```

Add `--content` to include the extracted markdown in the JSON output as both `content` and `contentMarkdown`. Add `--json` for structured JSON.

## keep search

Search Notes and saved Items together across your library.

```
keep search "react hooks"
keep search "article about authentication" --limit 10
keep search "release decision" --types note --mode lexical
keep search "agent memory" --project https://github.com/iannuttall/seo --exact-project
```

Use `--types item,note` to choose resource types. Use `--mode lexical`, `--mode semantic`, or `--mode hybrid` to choose matching behavior. Add `--content` when you need bounded content. Search stays shallow by default. Project filters remain available for advanced workflows.

## keep items search

Search captured Items only by title, URL, notes, tags, and semantic similarity. Add `--tag` or `--collection` to keep the search inside a specific filter.

```
keep items search "react hooks"
keep items search "agents" --collection x-articles --tag agent-tooling
```

`keep context` is an advanced compatibility command that detects the current Git Project and path. `keep context brief --json` returns a maximum of 20 recent Note titles and retrieval cues for that Project.

## keep notes

Search and read Markdown notes:

```
keep notes search "OAuth verification"
keep notes search "pricing" --project https://github.com/iannuttall/keep --exact-project --limit 5
keep notes get c4e2a975-d582-4fb9-b952-5911365332c7
keep notes get c4e2a975-d582-4fb9-b952-5911365332c7 --full
keep notes get c4e2a975-d582-4fb9-b952-5911365332c7 --overview
keep notes get c4e2a975-d582-4fb9-b952-5911365332c7 --find "rollout"
keep notes get c4e2a975-d582-4fb9-b952-5911365332c7 --lines 40:90 --revision 4
keep notes get c4e2a975-d582-4fb9-b952-5911365332c7 --sources --history
keep notes get c4e2a975-d582-4fb9-b952-5911365332c7 --sources --content --content-bytes 80000
keep notes history c4e2a975-d582-4fb9-b952-5911365332c7
```

Note search returns the same bounded index as `keep search`. It does not download every matching Note body. Use `--content` only when you need the matched text. When a result includes `revision` and `lines`, pass both straight to `notes get --lines` instead of opening the whole Note.

`notes get` returns a compact overview by default. `--find` returns matching line windows, and `--lines` returns an exact slice. Use `--revision` to pin the same content across those steps. Search windows are limited to 200 lines and 16 KB; exact slices are limited to 200 lines and 32 KB. Use `--full` only when those bounded reads are not enough. Reads do not use Note credits. Creating a Note uses one credit. Editing an existing Note does not use another credit.

Expanded reads return JSON. `--sources` adds attached Item summaries and highlights, `--history` adds recent revision summaries, and `--content` adds bounded full item content. Lower the response limits with `--source-limit`, `--history-limit`, or `--content-bytes`.

Create or update a note from a local Markdown file:

```
keep notes create --title "OAuth verification" --body-file note.md
keep notes create --title "OAuth verification" --body-file note.md --tags oauth,seo
keep notes append c4e2a975-d582-4fb9-b952-5911365332c7 --body-file result.md
keep notes update c4e2a975-d582-4fb9-b952-5911365332c7 --body-file replacement.md --revision 3
keep notes update c4e2a975-d582-4fb9-b952-5911365332c7 --revision 4 --change-summary "Clarify the result"
keep notes update c4e2a975-d582-4fb9-b952-5911365332c7 --revision 5 --clear-tags --clear-project
```

Updates use the current revision number. Appends use the latest revision automatically and preserve another append that arrives at the same time. Pass `--revision` to an append only when you want a stale revision to fail.

New Notes do not get Git metadata by default. Use `--project` or `--path` when that metadata is useful. Use `--context` to detect both values from the current Git repository. `--kind`, `--state`, `--tags`, and `--properties-json` remain available. `--properties-json` is for custom properties. Metadata-only updates do not need `--body-file`. The older `--no-context` flag remains accepted.

Fields you omit from an update stay unchanged. Use `--clear-tags`, `--clear-project`, `--clear-kind`, or `--clear-state` to remove first-class metadata. Use `--clear-properties` to remove all custom properties. Append only adds Markdown. It cannot change the title or metadata. Keep reuses the same request ID during conflict recovery, which prevents duplicate text.

JSON write receipts contain Note and revision coordinates without the Markdown body. They include `metadataDiff` when tags, Project, kind, or state changed. The CLI also rejects unknown flags and flags used with the wrong command before it sends a request.

Attach saved items or highlights as supporting context:

```
keep notes attach c4e2a975-d582-4fb9-b952-5911365332c7 item_456 --relation evidence
keep notes attach c4e2a975-d582-4fb9-b952-5911365332c7 item_456 --highlight-id highlight_789
keep notes detach c4e2a975-d582-4fb9-b952-5911365332c7 nlink_456
```

Successful note writes print the bare note ID, revision, title, and its authenticated Keep link. Commands also accept older IDs beginning with `note_`. Add `--json` to receive the link as `webUrl`.

The attach response includes the link id used by `notes detach`. Relations can be `source`, `evidence`, `example`, `inspiration`, or `annotation`.

Export every current and archived Note as portable Markdown:

```
keep notes export
keep notes export --output ./keep-notes.zip
```

The ZIP contains one Markdown file per Note. Frontmatter includes the stable Note ID, revision, timestamps, archive state when present, and custom properties. Without `--output`, Keep writes a dated ZIP in the current folder.

## Advanced Project and session compatibility

Normal setup does not install session hooks or add Git Project metadata to new Notes. Existing hooks, Project data, and session commands continue to work. Use them only when you want that coding-session workflow.

Ask the current AI to prepare one detailed session summary with:

```
keep session prompt
keep session prompt --json
```

The command returns a prompt and write contract. It does not save anything by itself. The summary covers material decisions and reasoning, concrete work, files, URLs, checks, failures, remaining work, and terms that will help you find it later.

To load recent project Notes at session start and save one summary when a Claude Code, Codex, or Pi session ends:

```
npm install -g --ignore-scripts @earendil-works/pi-coding-agent
keep login claude-code
keep login codex
keep login pi
keep hooks install all
keep hooks status
keep hooks doctor
keep session status
keep session retry <job-id>
keep hooks remove all
```

At session start, Keep reads a maximum of 20 matching Note titles and retrieval cues. It does not load Note bodies, make a model request, or write anything. The hook stays quiet when there is no Git project, no matching Note, or Keep is temporarily unavailable.

`all` installs the full start and end lifecycle for Claude Code, Codex, and Pi. Cursor can install the current start-only preview, while OpenCode gets an explicit handoff command:

```
keep login cursor
keep hooks install cursor

npm install -g opencode-ai
keep login opencode
keep hooks install opencode
```

Installation asks for confirmation because each non-empty completed session uses one additional request from that model client at session end. Existing hooks are preserved, and removal deletes only Keep’s managed integration. Authenticate each model CLI and verify that it can answer a prompt first; `keep hooks doctor` checks the executable and version, not provider access.

Session exit queues the summary locally. Empty sessions are skipped, and a stable session ID limits each completed session to one Note even if the hook runs twice or a failed job is retried. Raw transcripts are not uploaded to Keep; only the generated Markdown summary is saved.

Use `keep session status` to see pending, saved, skipped, or failed jobs. After fixing a failed authentication or model CLI check, run `keep session retry <job-id>`.

See [Session hooks](https://keep.md/docs/session-hooks) for installation, privacy, checks, and failure recovery.

## keep extract

Run content extraction again for an existing Item.

```
keep extract a1b2c3
```

Use this after a page changes or a previous extraction fails.

## keep get

Read one Item without loading the complete captured document.

```
keep get a1b2c3
keep get a1b2c3 --find "payment failure"
keep get a1b2c3 --lines 40:90
keep get a1b2c3 --full
keep get a1b2c3 --media
```

The default overview contains metadata, statistics, and headings. `--find` returns matching windows. `--lines` returns an exact slice. Use `--full` only when those smaller reads are not enough. Search windows are capped at 200 lines and 16 KB. Exact slices are capped at 200 lines and 32 KB. `--content` remains an alias for `--full`. `--media` adds one bounded media page.

## keep highlights

List highlights attached to an item.

```
keep highlights a1b2c3 --limit 25 --offset 0
keep highlights a1b2c3 --json
```

The response includes `hasMore` and `nextOffset` when another page is available. Without `--json`, each row is `<highlightId>\t<itemId>\t<text>`.

## keep media

List ordered media references without loading Item content.

```
keep media a1b2c3 --limit 20 --offset 0
```

## keep highlight

Get one highlight by ID.

```
keep highlight hl_123
```

Returns the highlight JSON.

## keep update

Update an item without leaving the terminal. Tags stay as names. Collections accept ids, names, or slugs.

```
keep update a1b2c3 --title "Better title" --tags ai,reading
keep update a1b2c3 --collection x-articles
keep update a1b2c3 --collections x-articles,reading-list
keep update a1b2c3 --clear-collections
keep update a1b2c3 --processed
keep update a1b2c3 --unarchive
```

## keep tags

List tags with both display names and slugs.

```
keep tags list
```

## keep collections

List collections or create one from the terminal.

```
keep collections list
keep collections add "X Articles"
```

## keep content

Print the extracted markdown for an item. Useful for piping into other tools. This is a shortcut for reading content directly without the rest of the item JSON.

```
keep content a1b2c3
```

```
Title: Agent Memory

The full extracted markdown content of the page...
```

## keep archive

Archive an item to hide it from your default list. Shortcut for `keep update --archive`.

```
keep archive a1b2c3
```

## keep whoami

Display your account plan, limits, and usage.

```
keep whoami
keep me
```

## keep stats

Usage statistics for a date range.

```
keep stats --since 30d
```

## keep feed

List unprocessed items with their full content. Designed for AI tools and scripts that use your saved items as context. Supports the same `--tag` and `--collection` filters as `keep list`.

```
keep feed --limit 10
keep feed --collection x-articles --tag agent-tooling
```

## keep changes

Poll for item change events for delta sync. Returns JSON events in order with a cursor so you can sync incrementally instead of re-listing everything. See [Webhooks](https://keep.md/docs/webhooks) for a push alternative.

```
keep changes --updated-since 7d
keep changes --cursor NEXT_CURSOR
keep changes --collection x-articles --tag agent-tooling --content
```

Options: `--cursor`, `--updated-since`, `--tag`, `--collection`, `--limit`, and `--content`. Save the `nextCursor` from each response and pass it back as `--cursor` on the next run to fetch only what changed since.

## keep processed

Mark one or more items as processed so they leave the feed.

```
keep processed a1b2c3 d4e5f6
```

## keep sources

Manage RSS, YouTube, X profile, and email inbox sources.

```
keep sources list
keep sources list --include-settings
keep sources list --include-sensitive
keep sources add rss https://simonwillison.net/atom/everything/
keep sources add youtube @fireship_dev
keep sources add x levelsio --content both
keep sources add email
keep sources update src_123 --summaries off --full-content on
keep sources update src_123 --content posts
keep sources update src_123 --name "Simon Willison" --tags ai,engineering
keep sources remove src_123
```

Source creation supports `--name`, `--tags`, `--smart-tags`, polling and backfill options, `--no-full-content`, and `--no-summaries`. Source updates can change the name, tags, summary setting, and full-content setting. X profile sources also accept `--content posts`, `--content articles`, or `--content both`.

`keep sources list` returns a compact status manifest without configuration, tag rules, or internal cursors. Add `--include-settings` for redacted configuration and rules. Add `--include-sensitive` only when you need to debug a source you control. That output may contain credentials. Do not paste it into a chat, issue, log, or Note.

## keep webhooks

Manage signed webhook endpoints that send item changes to your own app. See [Webhooks](https://keep.md/docs/webhooks) for the payload, signature, and delivery details.

```
keep webhooks list
keep webhooks add "$KEEP_WEBHOOK_URL" --name "Research sync"
keep webhooks add "$KEEP_WEBHOOK_URL" --tag research
keep webhooks add "$KEEP_WEBHOOK_URL" --events item.created,item.tagged
keep webhooks test <webhook-id>
keep webhooks rotate-secret <webhook-id>
keep webhooks remove <webhook-id>
```

`webhooks add` options: `--name`, `--events` (comma-separated event names, default `*`), `--tag` (restrict to one tag), and `--collection` (restrict to one collection id).

Default `webhooks list` output is `<id>\t<status>\t<url>\t<name>\t<events>\t<scope>`. Add `--json` for the full response. `webhooks add` and `webhooks rotate-secret` print the signing secret once, so store it when the command returns.

## Global options

These flags work with any command:

`-v`, `--version`: print the installed CLI version

`--json`: output structured JSON instead of formatted text

`--key <token>`: use a specific API key for this request

`--client <name>`: use one named client credential

`--base <url>`: override the API base URL
