---
name: ekg
description: "Use this skill to supplement memory - both looking for and using memory to understand how to do things, and the state of tasks."
model: inherit
---
# ekg Skill — Emacs Knowledge Graph
`ekg` is an Emacs package ([source](https://github.com/ahyatt/ekg)) for taking
and retrieving notes, backed by a `sqlite` database. It should be used as a form
of agent memory, and it may also be used by users for their notes as well.
Here's how to use it from the command-line. Each script calls `emacsclient` so
the user must have run `M-x server-start` on their emacs, as well as loaded the
`ekg` package.
## Setup: Locating the Scripts
The command-line scripts live in the `agent_tools/` directory of the `ekg`
package. Since Emacs packages aren't normally on `$PATH`, resolve the directory
at the start of any session by asking Emacs where ekg is installed:
```sh
EKG_DIR=$(emacsclient --eval '(file-name-directory (locate-library "ekg"))' | tr -d '"')
```
Then invoke scripts with their full path, e.g. `"$EKG_DIR/agent_tools/ekg-read"`.
Alternatively, if you prefer, you can add the directory to your `$PATH`:
```sh
export PATH="$EKG_DIR/agent_tools:$PATH"
```
## ekg-add-note
Create a new note.
```sh
ekg-add-note --title "Title" --tag tag1 --tag tag2 --note "content" --mode org-mode
```
- `--title TEXT` — Note title. **Required for org tasks** (`org/task` tag),
optional otherwise.
- `--tag TAG` — Tags (repeatable, at least one required).
- `--note TEXT` — Note content (required).
- `--mode MODE` — `org-mode` (default), `markdown-mode`, or `text-mode`.
The `--note` text **must be formatted for this mode** (e.g. org markup for
`org-mode`, markdown for `markdown-mode`).
- Returns the numeric note ID on success.
- The note is automatically tagged with `agent` and the current date (`date/YYYY-MM-DD`).
- Content is automatically wrapped in LLM output markers.
## ekg-read
Read notes by tag, ID, search, or recency.
```sh
# By tags (AND logic)
ekg-read --tag tag1 --tag tag2 -n 10 -w 100
# By note ID
ekg-read 31123361376
# Semantic search (uses embeddings)
ekg-read --semantic-search "query string"
# Full-text search
ekg-read --search "query string"
# Latest modified notes
ekg-read --latest -n 5
```
- `-n NUM` — Max notes to return (default: 10).
- `-w NUM` — Max words per note (default: 100).
- Output is JSON: array of objects with `id`, `text`, `mode`, `tags`,
`creation_time`, `modified_time`.
## ekg-update-tags
Add or remove tags on an existing note.
```sh
ekg-update-tags <note-id> --add tag1 --remove tag2
```
## ekg-tags
Search and list tags in ekg.
```sh
# List all tags
ekg-tags
# Tags matching a regex
ekg-tags --regex "org/state/.*"
# Tags with a given prefix
ekg-tags --prefix "project/"
# Tags containing a substring
ekg-tags --including "moltbot"
# Tags co-occurring with another tag (notes that have BOTH tags)
ekg-tags --co-tagged prompt
# Combine filters (AND logic)
ekg-tags --prefix "project/" --co-tagged moltbot
```
- `--regex PATTERN` — Filter tags matching a regex.
- `--prefix PREFIX` — Filter tags starting with prefix.
- `--including TEXT` — Filter tags containing substring.
- `--co-tagged TAG` — Find tags that appear on notes also tagged with TAG
(repeatable, AND logic).
Output is a JSON array of tag strings.
## ekg-append-note
Append text to an existing note. Works with any note type (not just org tasks).
```sh
ekg-append-note <note-id> --text "text to append"
```
- `<note-id>` — The note's ID (required, positional).
- `--text TEXT` — Text to append (required). The text **must be formatted for
the note's mode** (e.g. org markup for org-mode notes, markdown for
markdown-mode notes).
## ekg-trash
Soft-delete a note (trash it). Running again on a trashed note permanently
deletes it.
```sh
ekg-trash <note-id>
```
## ekg-org-add-child
Create a child org task under an existing parent task.
```sh
ekg-org-add-child <parent-id> --title "Subtask title" [--note "description"]
[--tag extra-tag] [--status TODO] [--mode org-mode] [--property KEY=VALUE]
```
- `<parent-id>` — The parent task's note ID (required, positional).
- `--title TEXT` — Task title/headline (required).
- `--note TEXT` — Task content/description (default: empty). Text **must be
formatted for the `--mode`** (e.g. org markup for `org-mode`, markdown for
`markdown-mode`).
- `--tag TAG` — Additional tags (repeatable).
- `--status STATUS` — Task status: TODO, DONE, WAITING, etc. (default: TODO).
- `--mode MODE` — `org-mode` (default), `markdown-mode`, or `text-mode`.
- `--property KEY=VALUE` — Set an org property (repeatable). Keys are
case-insensitive and stored uppercase.
- Returns the new note's ID on success.
- The `org/task` tag and state tag are added automatically.
## ekg-org-edit
Edit an existing ekg org task. Only specified fields are changed.
```sh
ekg-org-edit <note-id> [--title "new title"] [--note "new content"]
[--append "additional text"] [--status DONE]
[--set-property KEY=VALUE] [--remove-property KEY]
```
- `<note-id>` — The task's note ID (required, positional).
- `--title TEXT` — Set the task title/headline.
- `--note TEXT` — Replace the task content/body. Text **must be formatted for
the note's mode** (e.g. org markup for org-mode notes, markdown for
markdown-mode).
- `--append TEXT` — Append text to the existing content (cannot combine with
`--note`). Text must match the note's mode format.
- `--status STATUS` — Set the status (TODO, DONE, WAITING, STARTED, etc.).
- `--set-property KEY=VALUE` — Set an org property (repeatable). Keys are
case-insensitive and stored uppercase.
- `--remove-property KEY` — Remove an org property (repeatable).
## Tag Conventions
### Org Task Tags
With an `org/task` tag, notes will appear in the org-mode agenda (`/ekg:tasks.org`) once the
user sets it up by adding the file `/ekg:tasks.org` to the agenda.
| Tag | Purpose |
|---|---|
| `org/task` | Marks the note as an org task (required) |
| `org/state/todo` | Task is pending |
| `org/state/done` | Task is complete |
| `org/state/waiting` | Task is blocked |
| `org/archive` | Archived task (hidden from active agenda) |
**Org tasks require a `--title`** — this becomes the headline in the org agenda.
#### Creating an org task
```sh
ekg-add-note
--title "Implement feature X"
--tag "org/task"
--tag "org/state/todo"
--tag "moltbot"
--note "Description of the work to do."
--mode org-mode
```
### Marking a task done
```sh
ekg-update-tags <note-id> --add "org/state/done" --remove "org/state/todo"
```
### Archiving a completed task
```sh
ekg-update-tags <note-id> --add "org/archive"
```
### Prompt Co-Tags
Notes tagged with `prompt` plus other tags act as **injected instructions**.
This is used by the built-in ekg agent, but as an outside agent, you also need
to retrieve relevant prompts (if there are any) and use them before performing
any significant action.
Example: A note tagged `prompt` + `slack` should inject its instructions into any
agentic use of `slack`.
#### Creating a prompt note
```bash
ekg-add-note
--tag "prompt"
--tag "slack"
--tag "moltbot"
--note "Always reply in threads in Slack channels, never top-level."
--mode markdown-mode
```
To find all tags that have prompt co-tags:
```sh
ekg-tags --co-tagged prompt
```
To see all prompt notes:
```sh
ekg-read --tag "prompt" -n 20 -w 200
```
### General Tags
- `agent` — Automatically added to all notes created via `ekg-add-note`.
- `date/YYYY-MM-DD` — Automatically added with the current date.
- Project-specific tags (e.g., `project/ekg`, `slack`) for organization.
## Advanced: Direct Emacsclient
For operations not covered by the scripts, you can call elisp directly:
```bash
# Set a property on a note
emacsclient --eval '(progn
(let ((note (ekg-get-note-with-id NOTE_ID)))
(setf (ekg-note-properties note)
(plist-put (ekg-note-properties note) :org/deadline TIMESTAMP))
(ekg-save-note note)
"done"))'
# Check a note's properties
emacsclient --eval '(ekg-note-properties (ekg-get-note-with-id NOTE_ID))'
# Get all org tasks as org-mode text
emacsclient --eval '(ekg-org-generate-org-content)'
```
Key properties for org tasks:
- `:titled/title` — List containing the title string (e.g., `(list "My Task")`)
- `:org/parent` — Parent task note ID (for subtasks)
- `:org/deadline` — Unix timestamp integer
- `:org/scheduled` — Unix timestamp integer
## Recommended Agent Workflow
1. **When starting work on something:** Create an `org/task` + `org/state/todo`
note (add your own tag, e.g., `claude`) so it shows up in the org agenda.
2. **When finishing:** Update the tag to `org/state/done`.
3. **For reusable instructions:** Create `prompt` co-tagged notes so they get
injected into future relevant tasks.
4. **For general knowledge:** Create regular notes with descriptive tags.
5. **Always search first:** Before creating notes, check if relevant ones
already exist with `ekg-read`. Before doing an action, check to see if
any notes co-tagged with the `prompt` tag works.