agentleFS
zirkelczirkelc/agent-reminders/skills/remind/SKILL.md

remind

Skill0 starsChanged 3 months agoMITView on GitHub

Create, review, and close reminders that resurface later: tasks, follow-ups, shared project TODOs, recurring checks. Each reminder is a markdown file carrying its own context, so a future session can act on it without the user re-explaining anything. Instructions are free-form with no keywords, e.g. "delete the legacy auth shim once v4 ships", "check the error rate again in two weeks", "the migration is done", "what's due?". Use when the user wants something remembered for later, or asks to close, amend or list existing reminders.

10 other projects use a version of this.

Adopted by

Most recently taken up by

Used with

Projects with it also use deep-research.

Other files people use alongside this one.

Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
  • NVIDIASkill

    deep-research

    Queue deep, multi-step research and analysis tasks to the DeepAgents worker. Supports execution depth presets, request-specific rubrics, SubAgent delegation, and RubricMiddleware cross-validation.

    Also in 3 projects that use this

The file

Show its rules and text

We split this skill into the rules it gives an agent

19 rules. 0 are common, 7 are distinctive, and 12 are very specific to this project.

  • 0

    Common

    Most of the 7 edited versions we read keep these.

  • 7

    Distinctive

    This author's own choices. Worth a look.

  • 12

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Never hardcode a path and never guess one.

    line 20
  2. Very specific:

    Run it from the user's working directory, or pass --cwd <their cwd>, since most of what it resolves depends on where they are.

    line 33
  3. Distinctive:

    Always read the open reminders before acting.

    line 66
  4. Very specific:

    Read closed/ only when the user asks about something already closed ("what did the last changelog reminder say?").

    line 73
  5. Very specific:

    Reference to an existing reminder: If the instruction names something already in a store, it is almost never a Create.

    line 97
  6. Distinctive:

    If genuinely ambiguous, ask one short question rather than guessing.

    line 102
  7. Very specific:

    All dates are ISO YYYY-MM-DD.

    line 107
  8. Very specific:

    Use the project value from paths verbatim as the name.

    line 180
  9. Very specific:

    Do not touch .gitignore, and do not commit anything.

    line 204
  10. Very specific:

    Every key is optional except id.

    line 241
  11. Distinctive:

    No invented facts: Only what was established this session or verified from the code.

    line 373
  12. Very specific:

    Leave ## Log present and empty.

    line 376
  13. Very specific:

    Use plain mv, not git mv: a reminder created this session may still be untracked, and git mv fails outright on an untracked file.

    line 405
  14. Very specific:

    If on_close=delete, delete the file instead of moving it.

    line 409
  15. Distinctive:

    If the user reports how it went ("changelog's updated", "billing numbers still look right"), log what they said.

    line 416
  16. Very specific:

    Do not read closed/ unless asked.

    line 426
  17. Very specific:

    Add closed_at: <today> and move the file to closed/, with a log line saying it was dropped and why it stopped mattering.

    line 443
  18. Distinctive:

    Do not paste the file back.

    line 461
  19. Distinctive:

    If the user genuinely wants a bare nudge with no context, that is fine — say so, and keep it light rather than padding it.

    line 477

“Common” is measured: kept by at least 6 in 10 of the 7 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Remind

Reminders that survive the session that created them. The user will not remember the context weeks from now and should not have to: the reminder carries what it needs to be acted on. This fits anything worth resurfacing later — a task to do before a release, a follow-up to make, a value to rotate, a shared TODO for whoever next opens the repo, or a recheck of live data against a baseline.

The instruction is free-form natural language. There are no subcommands and no required word order. Infer what is being asked.

Step 1: Resolve

Never hardcode a path and never guess one. One command answers where everything is, and it is the only place those rules exist:

BIN="${CLAUDE_PLUGIN_ROOT:-$(cd -P "<skill dir>/../.." && pwd)}/bin/agent-reminders"
"$BIN" paths

Substitute the "Base directory for this skill" path from the invocation for <skill dir>. CLAUDE_PLUGIN_ROOT is set on a plugin install and unset when the skill was symlinked by install.sh, which is what the fallback is for; cd -P resolves that symlink, so the fallback lands on the repository rather than on ~/.claude.

Run it from the user's working directory, or pass --cwd <their cwd>, since most of what it resolves depends on where they are.

It prints nine key=value lines. Four matter now:

key
todaytoday's date. Use this; never a date from memory
projectthe name this directory belongs to. What a reminder is matched against, and what goes in its project: line
user_dirroot of the user store
project_dirroot of this repo's store. Empty outside a repo, or when the user keeps reminders out of repos

Each store root has open/ and closed/ inside it. Build those yourself: $user_dir/open. Nothing is created for you, so mkdir -p before writing.

The rest are used where they are needed, not here: store and project_exists in Step 5, on_close when closing, cwd and repo_root when writing frontmatter.

Which directory a reminder sits in is the only record of whether it is outstanding. open/ means outstanding, closed/ means finished, and closing is moving the file. There is no status field, deliberately: a second record of the same fact can disagree with the first. It also keeps session start proportional to what is outstanding rather than to everything ever written, since the hook reads only open/.

To read or change a setting, ask the same command rather than opening the config file:

"$BIN" config                          # every setting, its value, and where it came from
"$BIN" config set store.<project> user # the only supported way to write one

Step 2: Read what already exists

Always read the open reminders before acting. There are few of them, and every intent except creating a brand-new one needs them.

head -14 "$user_dir/open"/*.md "$project_dir/open"/*.md 2>/dev/null

Read closed/ only when the user asks about something already closed ("what did the last changelog reminder say?"). It is not part of the normal path:

grep -rl changelog "$user_dir/closed" "$project_dir/closed" 2>/dev/null

Step 3: Infer the intent

Classify the instruction by what it describes, not by keywords it contains. The user will not say "add", "list", or "done".

The instruction…IntentExample
describes something to do or check laterCreate"update the changelog before the 1.2 release", "check the billing metrics again next week"
reports a task finished, or a check's resultClose"done with the changelog", "billing numbers still look right"
asks what is outstandingReview"what's pending?", "anything due?"
changes an existing reminder's timing or contentAmend"push the vendor follow-up to next month"
cancels somethingDrop"forget the changelog reminder", "that one's not relevant anymore"

Signals worth weighing:

  • Tense. Future or imperative ("update X", "check Y next week") creates a new one. Past tense ("updated X", "did the billing one", "that's sorted") closes an existing one.
  • Reference to an existing reminder. If the instruction names something already in a store, it is almost never a Create. Match loosely: "the changelog one" should find update-changelog, "the billing check" should find check-billing-metrics.
  • Bare invocation. /remind with no instruction is a Review.

If genuinely ambiguous, ask one short question rather than guessing. Creating a duplicate or closing the wrong reminder both cost more than asking.

Step 4: Resolve the date

All dates are ISO YYYY-MM-DD. Take today from paths, and compute the rest with date, never by hand:

date -v+7d +%F              # macOS: in one week
date -v+1m +%F              # macOS: next month
date -d '+7 days' +%F       # GNU coreutils fallback

Interpret relative language generously: "in a week" → +7d, "next month" → +1m, "in a couple of weeks" → +14d, "end of the quarter" → the actual date. If the user ties the reminder to an event with no date ("before the release"), ask for the date or pick the best available anchor; do not invent one.

No date at all

due is optional. A reminder without one is outstanding rather than due: it surfaces every session in the project it belongs to, until it is closed. That is the right shape for a shared repo TODO ("whoever touches this next, rename the thing") and the wrong shape for a nudge, since something that appears every session stops being read.

So when the user gives no time: offer both rather than defaulting. "Whenever I'm next in here" is a real answer, and so is a date. Do not create undated reminders freely — each one costs every future session in that project a line of banner.

Recurrence

Set repeat only when the language is genuinely recurring: "every two weeks", "each month", "weekly", "keep checking". A one-off reminder has no repeat, even when phrased as "again" — "check X in a week again" means once, next week. repeat needs a due; it means nothing without one.

repeat is completion-relative: when a repeating reminder is closed, the next due date is computed from today, not from the old due date. "Every 14 days" means 14 days since it was last actually done. This is deliberate: date-relative recurrence piles up overdue instances after a skipped cycle, which is exactly when the user is least able to deal with them.

Step 5: Choose the store

Two stores, and which one a reminder belongs in is a real decision, not a default.

  • User store — private, on this machine only, holds reminders for every project.
  • Project store — .agent-reminders/ inside the repo, and if committed it is shared with everyone who clones and travels with the code.

Outside a repository there is no decision: repo_root is empty, so it is the user store. Inside one, store decides.

storewhat to do
useruser store. Do not offer the project store, do not ask
projectproject store, creating the directory if project_exists=false
ask_onceproject store if project_exists=true, otherwise ask and record the answer
ask_every_timeask, every time, and record nothing

ask_once is the default. Under it, the directory already existing is treated as the answer, because someone put it there on purpose and it is where that repo's reminders live.

ask_every_time is the setting for a repo that keeps its own reminders but where some of them are still personal. It asks even when project_exists=true, which is the only way a reminder about a repo with a project store can be filed privately instead. Do not record an answer under it: being asked every time is the point.

Remembering the answer

Under ask_once only, when you have asked, record the answer before writing the reminder:

"$BIN" config set store.<project> user      # or: project

Use the project value from paths verbatim as the name. Do not edit the config file to do this; config set is the only thing that knows its format, and it keeps everything else in the file intact.

Without this the question returns on every reminder created here, since an answer otherwise leaves no trace: the only signal is a directory that was or was not created. It reports back as store_from=override.

Say that it has been remembered, in a few words, so it is clear the question is settled and not merely skipped this once.

An explicit request outranks a recorded answer. If they ask for a project reminder in a project recorded as user, run config set store.<project> project rather than asking again, then create the store.

Creating the project store

Creating it is one command:

mkdir -p "$project_dir/open" "$project_dir/closed"
cp "<plugin root>/templates/project-readme.md" "$project_dir/README.md"

Do not touch .gitignore, and do not commit anything. Whether the directory belongs in the repository is the user's call to make on their own terms, and guessing at it means either committing something private on their behalf or writing to a shared file they did not ask you to edit.

Tell them once, when the directory is created, in a sentence: it is untracked right now, committing it shares every reminder in it with anyone who clones, and anything private belongs in the user store instead. Then leave it. This is the only time it comes up, so do not raise it again on later reminders in the same repo.

Step 6: Act

Create a new reminder

Write <open dir>/<id>.md.

id — short kebab-case slug describing the task, derived from the instruction: "update the changelog" → update-changelog, "check the billing metrics" → check-billing-metrics. It must be unique within its store and it must never change, since it is the reminder's identity. If the slug already exists, this is probably an Amend, not a Create; check before overwriting.

Frontmatter — flat key: value lines, no quotes, no nesting, no lists, no multiline values. A hook parses this with a regex at every session start, so anything fancier silently breaks it:

---
id: update-changelog
due: 2026-07-24
project: acme-api
cwd: /Users/chris/Developer/acme-api
session_id: <current session id>
created: 2026-07-17
---

Every key is optional except id. Omit a line rather than writing it empty, and never invent a placeholder value to fill one.

  • due — omit entirely for an undated reminder. Never invent a date.
  • project — write it only inside a git repository, taken from paths. Outside one, paths reports the directory's own basename, which is a false identity rather than a weak one: ~/notes and ~/work/notes both resolve to notes, and a reminder created in one would fire in the other. Omitting it there leaves cwd as the match, which is exact.
  • cwd — write it only in the user store, always. It is what matches outside a repository, and the only record of which worktree a reminder was created in. Leave it out of the project store: it is a local absolute path, the file may be committed, and it says nothing to anyone else who reads it.
  • repeat — add the line only when recurring (repeat: 14d); omit it otherwise.
  • session_id — the current session, so the original conversation stays findable.

There is no status key. A reminder is outstanding because it is in open/, and nothing in the file says otherwise.

Body — this is the part that matters. The reminder must be actionable by a future session with no memory of this conversation. Two sections, and no more:

<One or two sentences: what this is and why it matters later.>

## Context

<Everything a future session needs in order to act on this without seeing this
conversation. For example: the commands to run, the files and line numbers to
change, the URLs or dashboards to look at, the people to chase, the numbers to compare
against, the constraint that decides whether it is time yet.>

## Log

<Empty at creation. One `### YYYY-MM-DD` entry is appended each time someone acts on this,
including the time that closes it.>

Nothing beyond those two. Headings inside ## Context are fine when a reminder is long enough to need them, but the shape is not fixed and most reminders do not need any.

What belongs there depends on the task, which is why the section is not subdivided. A task to do names the files and the change. A check against live data carries the query and the baseline number to compare against, which is what makes the next run meaningful. A shared TODO may need little more than the reason it exists and who to ask.

<example> As created, with the log empty:
---
id: drop-legacy-auth-shim
due: 2026-10-01
project: acme-api
cwd: /Users/chris/Developer/acme-api
created: 2026-08-09
session_id: 4d1f0c92-1b7a-4a55-9c31-0b2e6a7f8d10
---

The auth shim exists only for the two mobile clients still on v3. Both ship v4 in August,
after which it is dead code that everyone will be afraid to touch.

## Context

Delete `src/auth/legacy.ts`, the branch that calls it at `src/auth/index.ts:41`, the
`LEGACY_AUTH` flag in `config/flags.ts`, and `test/auth/legacy.test.ts`.

Do not start before v3 is under 1% of mobile traffic; it was 6% on 2026-08-09. The figure
is the "client version" panel on the mobile dashboard. `rg LEGACY_AUTH` should come back
empty when this is finished.

## Log

The same reminder in December. Two sessions have picked it up, found the condition not met, logged what they saw and moved the date. It is still in open/, and the log is now the most useful part of it:

---
id: drop-legacy-auth-shim
due: 2026-12-15
project: acme-api
cwd: /Users/chris/Developer/acme-api
created: 2026-08-09
session_id: 4d1f0c92-1b7a-4a55-9c31-0b2e6a7f8d10
---

The auth shim exists only for the two mobile clients still on v3. Both ship v4 in August,
after which it is dead code that everyone will be afraid to touch.

## Context

Delete `src/auth/legacy.ts`, the branch that calls it at `src/auth/index.ts:41`, the
`LEGACY_AUTH` flag in `config/flags.ts`, and `test/auth/legacy.test.ts`.

Do not start before v3 is under 1% of mobile traffic; it was 6% on 2026-08-09. The figure
is the "client version" panel on the mobile dashboard. `rg LEGACY_AUTH` should come back
empty when this is finished.

## Log

### 2026-10-01

Not yet. v4 shipped on schedule, but v3 is still 6% of mobile traffic, unchanged since
August: the auto-update rollout is paused for App Store review. Pushed to 2026-11-15.

### 2026-11-15

Down to 2.3%, so it is moving now that the rollout resumed on 2026-10-28. Still above the
1% bar. At the current rate it clears in about a month, so pushed to 2026-12-15. Also
found a second caller at `src/auth/session.ts:88` that the original list missed; added it
to the context above.
</example>

Two things the example does. It logs the failed checks rather than only the finish, so the 2.3% can be read against the 6% and the trend is visible without anyone remembering it. And the second entry corrects the context in place when it found something the first pass had missed, because the next session reads the context, not the history.

Note also what it does not do: it never says "the file we just looked at", it gives figures as numbers rather than as "still too high", and it names the panel rather than assuming the reader knows where the figure lives.

Quality bar, in order of importance:

  1. Concrete over descriptive. Paste the query. Name the file. Give the number. "Fix the changelog" is not enough; "add the 1.2 entry listing the retry changes" is.
  2. Self-contained. The future session cannot see this conversation. No "as we discussed", no "the file we just edited".
  3. Enough to act cold. Whatever future-you must compare against or reference — a baseline number, a target state, a link — goes in the body now, not in memory.
  4. No invented facts. Only what was established this session or verified from the code. Unknowns go in the body as open questions, not as guesses.

Leave ## Log present and empty. It fills in on close.

Close a reminder

Append to ## Log, newest entry last:

### 2026-07-17

<What happened. For a task, that it was done and anything notable. For a recheck, what was
found and the numbers — compare against the previous log entry or the recorded baseline,
since the comparison is the value.>

Then, depending on the reminder:

  • With repeat — it does not close. Leave it in open/ and set due to today plus the interval (date -v+14d +%F for repeat: 14d). It stays alive and comes back. Repeating reminders never reach closed/.
  • Otherwise — add closed_at: <today>, and move the file out of open/:

    mv "$open/<id>.md" "$closed/<id>.md"

    The move is the close, and closed_at records when. There is no key recording how it ended: whether it was done or abandoned is prose, and the log entry already says it in a form worth reading later.

    Use plain mv, not git mv: a reminder created this session may still be untracked, and git mv fails outright on an untracked file. Nothing is lost, since git infers renames from content at diff time rather than recording them.

If on_close=delete, delete the file instead of moving it. Log the entry first and show the user what it said before it goes, since that text is about to be unrecoverable outside git history.

Otherwise never delete. This is a soft close: the log is the record, and what a reminder concluded is often worth finding long after it stopped mattering.

If the user reports how it went ("changelog's updated", "billing numbers still look right"), log what they said. If they ask you to actually do or run it, do it first, then log the outcome.

Review

Show what is outstanding, which is exactly the contents of both open/ directories. Group by urgency: overdue first, then due today, then undated, then upcoming. For each: id, due date, how overdue, and which store it is in — the store is the interesting half, since it says whether the team can see it. Keep it to a line each unless the user asks for detail. Do not read closed/ unless asked; "what's pending" is not a question about finished work.

Amend

Edit the file in place. Never change id, and never move a file between open/ and closed/: an amend changes what a reminder says, not whether it is outstanding. Do not touch ## Log — it is append-only history, and rewriting it destroys the comparison the reminder may exist for.

Moving a reminder between the user and project stores is a legitimate amend (a shared TODO turns out to be private, or vice versa). Move the file, then fix the frontmatter for where it now lives — the project store drops cwd, the user store needs it back — and say so.

Drop

Add closed_at: <today> and move the file to closed/, with a log line saying it was dropped and why it stopped mattering. Same as a close in every respect: the move is what ends it, and the log is what says it was abandoned rather than finished. Honour on_close the same way.

Step 7: Report

One or two lines, no ceremony:

  • Filed — the id, the due date in plain terms ("2026-07-24, in one week") or that it is undated, whether it repeats, and which store, since that determines both where it surfaces and who else can see it. If a project store was just created, add the one-time note that committing it is their call.
  • Closed — the id, what was logged, and either the next due date (repeating) or that it is done.
  • Reviewed — the list.
  • Amended / Dropped — what changed.

Do not paste the file back. The user asked for a reminder, not a document.

Notes

  • A SessionStart hook surfaces outstanding reminders automatically, filtered to the current project. It runs on startup and resume, and again on clear and compact, which discard the context it injected. Those two re-inject silently, with no banner, so seeing no banner does not mean there is nothing outstanding. Reminders created against another project appear as a bare count once overdue, never as a full banner. Project stores in repos the user is not currently inside are invisible, which is the point of them.
  • Nothing has to be set up. Every setting has a default and paths reports the effective value, so never block on configuration; mention /agent-reminders:config only if they ask where things live or want to change something.
  • The value over a plain calendar entry is the context a reminder carries. Never write one whose body just restates its title; capture at least where to act and what "done" means. If the user genuinely wants a bare nudge with no context, that is fine — say so, and keep it light rather than padding it.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.