/cf-remember
Extract and save project knowledge. User input: $ARGUMENTS
Purpose
After a coding session, key knowledge gets lost — logic flows, conventions, decisions, gotchas. This skill captures that knowledge into the project's memory folder so future sessions (and humans) can quickly understand the project.
Folder
Output goes to {docsDir}/memory/ (default: docs/memory/). Check .coding-friend/config.json for custom docsDir if it exists.
IMPORTANT — path resolution:
- Use
MAIN_REPO_ROOTfrom the SessionStart bootstrap context (injected via session-init.sh). If absent, fall back to runningpwdfor$CWDand use$CWDasMAIN_REPO_ROOT. - Read config from
CF_CONFIG_FILE(=$MAIN_REPO_ROOT/.coding-friend/config.json) — do NOT search sub-folders - Use
CF_DOCS_ROOTas the docs base dir (=$MAIN_REPO_ROOT/{docsDir}wheredocsDircomes from config, defaultdocs) - Always resolve
file_pathas an absolute path:{CF_DOCS_ROOT}/memory/{category}/{name}.md - Never use relative paths in write specs — they may resolve incorrectly when the working directory contains nested git repos
Workflow
Step 0: Custom Guide
bash "${CLAUDE_PLUGIN_ROOT}/lib/load-custom-guide.sh" cf-remember
If the block above printed anything, apply only the ## Before, ## Rules, and ## After sections; if it shows the raw command instead of output, re-run that exact load-custom-guide.sh fence now.
Step 1: Analyze the Conversation
If $ARGUMENTS is provided, use it as a filter — focus only on conversation content that relates to the user's stated purpose. Otherwise, scan the full conversation.
Identify:
- Features worked on: What was built or modified?
- Logic flows: How does the feature work? Key decision points?
- Conventions: Patterns established (naming, structure, API design)
- Decisions: Why was X chosen over Y?
- Gotchas: Tricky parts, common mistakes, non-obvious behavior
Step 2: Determine the Category
Choose the right location based on what the knowledge is about, not just what task was performed:
| Category | Location | Use For |
|---|---|---|
| Features | {docsDir}/memory/features/YYYY-MM-DD-<name>.md |
Feature-specific logic, flows, APIs |
| Conventions | {docsDir}/memory/conventions/YYYY-MM-DD-<name>.md |
Project-wide patterns and rules |
| Decisions | {docsDir}/memory/decisions/YYYY-MM-DD-<name>.md |
Architecture/design decision records |
| Bugs | {docsDir}/memory/bugs/YYYY-MM-DD-<name>.md |
Bug root causes, fixes, and how to avoid recurrence |
| Infrastructure | {docsDir}/memory/infrastructure/YYYY-MM-DD-<name>.md |
Build, deploy, CI/CD, environment setup |
Backward compat: When reading or updating existing memory files, both
YYYY-MM-DD-<name>.md(new) and<name>.md(legacy) formats are valid — do not rename existing files.
Category selection guide:
- Fixing a bug →
bugs/(root cause, fix, prevention), NOTfeatures/ - Adding/changing a feature →
features/ - Establishing a pattern or rule →
conventions/ - Choosing between approaches →
decisions/ - Build/deploy/tooling knowledge →
infrastructure/
Step 3: Assess Complexity
Before delegating to the cf-writer agent, assess the complexity of the content:
Use cf-writer agent (haiku) when:
- Simple feature docs, naming conventions, straightforward decisions
- Short content with clear structure
Use cf-writer-deep agent (sonnet) when:
- Complex architecture decisions with nuanced trade-offs
- Deep technical explanations requiring careful reasoning
- Long context that needs synthesis
Step 4: Delegate to cf-writer Agent
Dispatch cf-writer or cf-writer-deep (per Step 3) with the complete write spec as the prompt.
Check if the target file already exists:
- File exists →
task: update - File doesn't exist →
task: create
Read the language setting from config (local .coding-friend/config.json overrides global ~/.coding-friend/config.json, default: en).
Build the write spec (use absolute path for file_path):
WRITE SPEC
----------
task: create | update
file_path: {CF_DOCS_ROOT}/memory/{category}/YYYY-MM-DD-{name}.md
language: {language from config}
content: |
---
title: "<Title>"
description: "<One-line summary for grep-based recall, under 100 chars>"
tags: [tag1, tag2, tag3]
created: YYYY-MM-DD
updated: YYYY-MM-DD
type: "<type based on category>"
importance: 3
source: conversation
---
# <Title>
## Overview
<1-2 sentences describing this feature/convention/decision>
## Key Points
- <point 1>
- <point 2>
## Details
<Longer explanation with code examples if needed>
## Gotchas
- <gotcha 1>
- <gotcha 2>
## Related
- <link to related code/docs>
readme_update: false
auto_commit: false
existing_file_action: append
Frontmatter rules:
descriptionis the most important field — it enables fast grep-based recall without reading full docs. Write it as a factual, searchable summary.- Good:
"Config management via .coding-friend/config.json with local/global override"— specific, grep-friendly - Bad:
"How we manage config"— too vague, won't match grep queries tags: 3-5 relevant keywords as array- When
task: update, update theupdateddate in the existing frontmatter. Do NOT changecreated.
Dispatch cf-writer or cf-writer-deep (per Step 3) with the complete write spec as the prompt.
Step 5: Index in CF Memory (MANDATORY)
This step is REQUIRED — do NOT skip it.
After the cf-writer agent completes and the markdown file is saved, you MUST call the memory_store MCP tool to index the memory in the database. This is a separate action from writing the file — the cf-writer agent does NOT do this.
If creating a new memory — call memory_store with:
title: from the frontmatter titledescription: from the frontmatter descriptiontype: infer from category (features →fact, conventions →preference, decisions →context, bugs →episode, infrastructure →procedure)tags: from the frontmatter tagscontent: the full markdown content (including frontmatter)importance: 3 (default)source: "conversation"index_only: truesync_to_claude_md: true — if the memory contains project-wide rules (see below)
If updating an existing memory — call memory_update with:
id: the memory ID (e.g.,features/auth-module— derived from{category}/{name})content: the updated full markdown contenttags: updated tags array (if changed)sync_to_claude_md: true — if the memory contains project-wide rules (see below)
CLAUDE.md sync rules:
Convention memories (type: preference) are always synced to the project's CLAUDE.md automatically. For other categories, set sync_to_claude_md: true when the memory contains project-wide rules, conventions, or decisions that future sessions must follow. Examples:
decisions/api-versioningwith rule "Always use URL-based versioning" →sync_to_claude_md: trueinfrastructure/deploy-checklistwith rule "Run migrations before deploying" →sync_to_claude_md: truebugs/null-pointer-fixdescribing a one-time bug fix → do NOT syncfeatures/auth-flowdescribing how auth works → do NOT sync (unless it contains rules to follow)
Rule of thumb: If the knowledge is prescriptive ("always do X", "never do Y", "use X pattern") and applies project-wide, sync it. If it's descriptive (how something works, what happened), don't.
If the MCP tools are unavailable, log a warning to the user but do NOT fail silently — the user should know the memory was saved as a file but NOT indexed.
Step 6: Confirm
Show the user a 2-line summary:
- Markdown file:
path/to/file.md(created or updated) - Memory DB: indexed ✓ — or: MCP unavailable, file only
Interpreting $ARGUMENTS
$ARGUMENTS is free-form user input. It can express:
A focus/filter (most common) — the main idea, purpose, or requirement that narrows what to remember from the conversation.
- Example:
/cf-remember the auth flow→ filter conversation for auth-related knowledge - Example:
/cf-remember why we chose Redis→ focus on that specific decision - Example:
/cf-remember gotchas from the migration→ extract only gotchas related to migration
- Example:
An explicit topic name — only when the user clearly specifies a filename or category.
- Example:
/cf-remember topic:caching-strategy→ use "caching-strategy" as the topic name - Example:
/cf-remember save as conventions/api-naming→ use the explicit path
- Example:
Default behavior: Always auto-detect the topic name from the filtered content. Only use $ARGUMENTS as the literal topic name when the user explicitly indicates it (e.g., with "topic:", "save as", "call it", "name it").
When $ARGUMENTS acts as a filter:
- Use it to narrow which parts of the conversation to extract knowledge from
- Ignore conversation content that doesn't relate to the user's stated focus
- The topic name should be derived from the filtered content, not from
$ARGUMENTSverbatim
Rules
- If no arguments given, scan the entire conversation for key knowledge
- Be concise — bullet points over paragraphs
- Include code snippets only when they clarify the point
- Create directories as needed