Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"$schema": "https://json.schemastore.org/claude-code-marketplace.json",
"name": "claude-memory-files",
"description": "Curated, modular memory and instruction files for Claude Code (Ribose orgs). The marketplace publishes one plugin — memory-files-tools — that adds slash commands for browsing, installing, removing, and submitting memory files from this repo.",
"owner": {
"name": "Ribose",
"url": "https://github.com/riboseinc"
},
"plugins": [
{
"name": "memory-files-tools",
"source": "./tools/plugin",
"description": "Slash commands for installing, removing, listing, and submitting memory files from the riboseinc/claude-memory-files catalogue."
}
]
}
36 changes: 36 additions & 0 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,39 @@ jobs:
- name: Install/uninstall smoke test
if: hashFiles('tools/install.sh') != ''
run: bash tools/test-install.sh

- name: Plugin manifests + slash-command frontmatter
if: hashFiles('.claude-plugin/marketplace.json') != ''
run: |
set -e
# marketplace.json: valid JSON
jq -e . .claude-plugin/marketplace.json > /dev/null

# Each declared plugin source must exist and have a valid plugin.json
jq -r '.plugins[].source' .claude-plugin/marketplace.json | while read -r src; do
plugin_json="${src}/.claude-plugin/plugin.json"
if [ ! -f "${plugin_json}" ]; then
echo "::error::marketplace.json declares plugin source ${src} but ${plugin_json} doesn't exist"
exit 1
fi
jq -e . "${plugin_json}" > /dev/null \
|| { echo "::error::${plugin_json} is not valid JSON"; exit 1; }

# Every slash command in the plugin must have YAML frontmatter with `description:`
cmd_dir="${src}/commands"
if [ -d "${cmd_dir}" ]; then
find "${cmd_dir}" -maxdepth 1 -name "*.md" -print | while read -r cmd; do
# Has --- ... --- block?
if ! awk 'BEGIN{c=0} /^---$/{c++} END{exit (c<2)}' "${cmd}"; then
echo "::error::${cmd}: missing YAML frontmatter (--- ... --- block)"
exit 1
fi
# Has description: field inside frontmatter?
if ! awk 'BEGIN{c=0;ok=0} /^---$/{c++; next} c==1 && /^description:[[:space:]]/{ok=1} END{exit !ok}' "${cmd}"; then
echo "::error::${cmd}: frontmatter missing required 'description' field"
exit 1
fi
done
fi
done
echo "Plugin manifests + slash command frontmatter checks passed."
15 changes: 15 additions & 0 deletions tools/plugin/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"$schema": "https://json.schemastore.org/claude-code-plugin.json",
"name": "memory-files-tools",
"version": "1.0.0",
"description": "Slash commands for installing, removing, listing, and submitting memory files from the riboseinc/claude-memory-files catalogue. Wraps tools/install.sh + tools/uninstall.sh from the catalogue repo (fetched from main on each call so the installer logic is always current).",
"author": {
"name": "Ribose",
"url": "https://github.com/riboseinc"
},
"homepage": "https://github.com/riboseinc/claude-memory-files",
"repository": "https://github.com/riboseinc/claude-memory-files",
"license": "MIT",
"keywords": ["claude-code", "memory", "instructions", "ribose"],
"category": "productivity"
}
54 changes: 54 additions & 0 deletions tools/plugin/commands/install-memory-file.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
---
description: Install a memory file from the riboseinc/claude-memory-files catalogue into ~/.claude/
argument-hint: <slug> [--project <dir>] [--ref <sha>]
allowed-tools: Bash, WebFetch
---

Install a memory file from the [riboseinc/claude-memory-files](https://github.com/riboseinc/claude-memory-files) catalogue into the user's `~/.claude/`.

## What the user typed

`$ARGUMENTS`

## Process

1. **Validate input.** If `$ARGUMENTS` is empty, show usage and stop. Usage:
`/install-memory-file <slug> [--project <dir>] [--ref <sha>]`. The slug
is the `name:` from the file's frontmatter (e.g. `github-pr-title-issue-link`).

2. **Look up the file in the catalogue.** Fetch the index:
`https://raw.githubusercontent.com/riboseinc/claude-memory-files/main/_meta/index.json`
and find the entry where `name == <slug>`. If none, fall back to treating
`$ARGUMENTS` as a full path like `instructions/<slug>.md`.

3. **Show the user the entry's frontmatter** before installing. Highlight:
- `description`
- `type` and `scope` (and `team:` if present)
- `owners`
- `requires-companion` if any (warn if the companion isn't already installed)
- `version`

4. **For `project-claude-md` type**: ensure `--project <dir>` is in the
arguments. If not, ask the user which project directory to install into.

5. **Run the installer.** Use the Bash tool:

```bash
curl -fsSL https://raw.githubusercontent.com/riboseinc/claude-memory-files/main/tools/install.sh \
| bash -s -- [user's options from $ARGUMENTS] <category>/<slug>.md
```

6. **Report the result.** Quote what the install.sh output said: where the
file landed, the manifest path, and the `Remove:` hint. If the install
failed (e.g. target already exists), surface the error and ask whether to
retry with `--force`.

## Notes

- The installer always fetches the current contents of `main` (unless `--ref <sha>`
is given). This means the slash command's behaviour stays in sync with the
catalogue's latest installer logic.
- `hooks/` files are rejected by the installer with a pointer to `SAFETY.md`;
this is intentional until v2 opens.
- Read [the catalogue's CONTRIBUTING.md](https://github.com/riboseinc/claude-memory-files/blob/main/CONTRIBUTING.md)
for the scope rubric and how the install paths interact with `~/.claude/CLAUDE.md`.
49 changes: 49 additions & 0 deletions tools/plugin/commands/list-memory-files.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
description: List available memory files from the riboseinc/claude-memory-files catalogue with optional filters
argument-hint: [--tag <tag>] [--scope universal|team|personal-share] [--team <name>] [--installed]
allowed-tools: Bash, WebFetch
---

List the catalogue of memory files available from riboseinc/claude-memory-files, with optional filters.

## What the user typed

`$ARGUMENTS`

## Process

1. **Fetch the catalogue index.** Use WebFetch or curl to read:
`https://raw.githubusercontent.com/riboseinc/claude-memory-files/main/_meta/index.json`

2. **Apply filters from `$ARGUMENTS`** (any combination):
- `--tag <tag>`: only entries whose `tags` array includes `<tag>`.
- `--scope universal|team|personal-share`: only entries matching the scope.
- `--team <name>`: only entries with `team: <name>`.
- `--installed`: only entries currently in the user's
`~/.claude/.memory-files-manifest.json`.
- `--include-deprecated`: also include the `deprecated` array from the index
(default: deprecated entries are hidden).
- No arguments: show everything not deprecated.

3. **Render the matching entries** as a table or a tight bulleted list, one
row/line per entry. Show:
- `name` (slug)
- `type`
- `scope` (plus `team:` qualifier if present)
- `description` (first 100 chars)
- whether `--installed` is in the local manifest

4. **Group by category** for readability when listing more than ~10 entries:
instructions, memory, settings-fragments, project-claude-md, rules.

5. **Suggest next actions** at the bottom of the listing:
- `/install-memory-file <slug>` to install one.
- `/remove-memory-file <slug>` to uninstall.
- `/submit-memory-file <local-path>` to propose a new file.

## Examples

- `/list-memory-files` — show all non-deprecated entries.
- `/list-memory-files --scope team --team metanorma` — team:metanorma rules only.
- `/list-memory-files --tag github` — entries tagged `github`.
- `/list-memory-files --installed` — what's currently on this machine.
44 changes: 44 additions & 0 deletions tools/plugin/commands/remove-memory-file.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
description: Uninstall a memory file installed from the riboseinc/claude-memory-files catalogue
argument-hint: <slug>
allowed-tools: Bash
---

Uninstall a memory file by its slug from `~/.claude/`.

## What the user typed

`$ARGUMENTS`

## Process

1. **Validate input.** If `$ARGUMENTS` is empty, show usage and stop. Usage:
`/remove-memory-file <slug>`.

2. **Check the manifest.** Read `~/.claude/.memory-files-manifest.json` and
confirm the slug is installed. If not, tell the user there's nothing to
uninstall under that slug.

3. **Show what will be removed** before acting:
- For `instruction`: the file at `~/.claude/instructions/<slug>.md` and the
`@`-include from `~/.claude/CLAUDE.md`.
- For `memory-*`, `path-rule`: just the file.
- For `settings-fragment`: the manifest-recorded entries will be subtracted
from `~/.claude/settings.json`; hand-added entries will be preserved.
A backup of `settings.json` will be created first.
- For `project-claude-md`: the project's `CLAUDE.md` is left intact (it may
have been hand-edited); only the manifest entry is removed. The user can
delete the file manually if they want.

4. **Confirm with the user** before running the uninstaller.

5. **Run the uninstaller.** Use the Bash tool:

```bash
curl -fsSL https://raw.githubusercontent.com/riboseinc/claude-memory-files/main/tools/uninstall.sh \
| bash -s -- <slug>
```

6. **Report the result.** Quote the uninstall.sh output and confirm clean state
(manifest entry gone, file removed if applicable, backup path if a
settings-fragment was un-merged).
71 changes: 71 additions & 0 deletions tools/plugin/commands/submit-memory-file.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
---
description: Propose a new memory file by scaffolding frontmatter, running the local validator, and opening a PR
argument-hint: <path-to-local-file.md> [--category instructions|memory|settings-fragments|project-claude-md|rules]
allowed-tools: Bash, Read, Write, Edit
---

Help the user contribute a new memory file to the riboseinc/claude-memory-files catalogue. Read their local file, draft frontmatter interactively if needed, run the validator, and open a PR.

## What the user typed

`$ARGUMENTS`

## Process

1. **Validate input.** If `$ARGUMENTS` is empty, show usage and stop. Usage:
`/submit-memory-file <path-to-local-file.md> [--category <category>]`.

2. **Read the user's local file** at the given path. If the file already has
frontmatter, parse it. If not, infer a reasonable starting frontmatter:
- `name` from filename (kebab- or snake-case slug, no `.md`).
- `type` from category (or ask if `--category` isn't given).
- `scope` — ask the user: universal, team (with optional `team:` qualifier),
or personal-share.
- `description` — draft a 1-line summary ≤140 chars; let the user revise.
- `author` — use the user's GitHub handle (look up via `gh api user --jq .login`).
- `owners: [author.github]` — default to single owner; required to stay
length 1 for `scope: personal-share`.
- `tags` — suggest 1–5 from the controlled vocabulary in `_meta/tags.txt`
(fetch it to confirm available tags).
- `version: 1.0.0`.
- `license: MIT`.
- `schema-version: 1`.

3. **Walk through the frontmatter with the user**. Show the proposed block,
ask for any edits, lock it in.

4. **Clone the catalogue repo into a sibling directory** (per the
`sibling-clones` convention if installed):
`gh repo clone riboseinc/claude-memory-files <sibling-dir>`.

5. **Create a feature branch** named `feat/<slug>` or
`feat/seed-<category>-<slug>`.

6. **Drop the file** into the correct category subdirectory in the clone.

7. **Regenerate index and CODEOWNERS:**
`node _meta/build-index.mjs && node _meta/build-codeowners.mjs`.

8. **Run the validator:** `node _meta/validate.mjs`. If it errors, surface the
errors to the user and let them fix the frontmatter or body before continuing.

9. **Commit** (via `git commit -F <tmpfile>` per the `github-content-via-file`
convention, with a `Co-Authored-By:` trailer).

10. **Push and open the PR** (via `gh pr create --assignee opoudjis --title "..."
--body-file <tmpfile>`). PR title: `feat: add <slug>: https://github.com/riboseinc/claude-memory-files/issues/1`.
PR body: one line referencing issue #1, plus the standard robot footer.

11. **Report the PR URL** back to the user.

## Notes

- For `scope: personal-share`, the validator enforces `owners == [author.github]`
(length 1, exact match). The slash command must respect this when scaffolding
the frontmatter.
- For `project-claude-md`, the body should be just the CLAUDE.md template
content (frontmatter on install is stripped). Confirm the body is markdown
and ≤200 lines.
- For `path-rule`, ask for the `paths:` glob list and validate each glob.
- For `settings-fragment`, the body must contain a `## fragment` heading followed
by a fenced ```json block. Walk the user through it if missing.
Loading