Skip to content

Commit 2eb3ad4

Browse files
committed
fix: use marketplace actions for git operations, add memory-manager README
- Replace custom bash scripts with stefanzweifel/git-auto-commit-action - Remove .github/scripts/ directory (git-push-with-retry.sh, collect-lint-errors.sh, create-brew-formula.sh) - Add README.md for memory-manager plugin - Update ci-cd conventions to prefer marketplace actions over custom scripts - Simplify workflow files (~200 lines removed)
1 parent a1125e0 commit 2eb3ad4

4 files changed

Lines changed: 105 additions & 211 deletions

File tree

.ai/rules/ci-cd/conventions.md

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,21 @@ Every action in `.github/actions/` must:
2727

2828
1. Have a test workflow that runs when the action changes
2929
2. Include a dry-run mode for PR validation
30-
3. Scripts >3 lines should be in separate files for linting
31-
4. Work locally via justfile commands
30+
3. Work locally via justfile commands
3231

33-
## Git Push Retry Logic
32+
## Prefer Marketplace Actions Over Custom Scripts
3433

35-
All workflows use exponential backoff (4 attempts: 2s, 4s, 8s, 16s).
34+
**CRITICAL:** When working with GitHub Actions workflows:
35+
36+
1. **Prefer popular upstream actions** over writing custom bash scripts
37+
2. **Check what's already in use** in the repo before introducing new dependencies
38+
3. **Be consistent** - if refactoring to use a different action, update all similar usages
39+
4. Keep inline bash to a minimum (simple one-liners only)
40+
41+
Common actions already in use:
42+
- `stefanzweifel/git-auto-commit-action@v5` - git config, add, commit, push
43+
- `peter-evans/create-or-update-comment@v4` - PR comments
44+
- `peter-evans/find-comment@v3` - finding existing comments
3645

3746
## Secrets Used
3847

.github/workflows/cd.yaml

Lines changed: 12 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -67,172 +67,44 @@ jobs:
6767
id: update
6868
uses: ./.github/actions/update-marketplace
6969

70-
- name: Commit marketplace changes
71-
if: steps.update.outputs.updated == 'true'
72-
run: |
73-
git config --local user.email "github-actions[bot]@users.noreply.github.com"
74-
git config --local user.name "github-actions[bot]"
75-
76-
git add .claude-plugin/marketplace.json
77-
78-
CHANGED_PLUGINS="${{ steps.update.outputs.changed-plugins }}"
79-
80-
git commit -m "$(cat <<'EOF'
81-
chore: update marketplace metadata [skip ci]
82-
83-
Updated marketplace.json with latest plugin versions.
84-
85-
Changed plugins: $CHANGED_PLUGINS
86-
EOF
87-
)"
88-
89-
echo "::group::Pushing marketplace changes"
90-
set +e
91-
RETRY_COUNT=0
92-
MAX_RETRIES=4
93-
RETRY_DELAY=2
94-
95-
while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
96-
if git push; then
97-
echo "::notice::Successfully pushed marketplace update"
98-
break
99-
else
100-
RETRY_COUNT=$((RETRY_COUNT + 1))
101-
if [ $RETRY_COUNT -lt $MAX_RETRIES ]; then
102-
echo "::warning::Push failed, retrying in ${RETRY_DELAY}s (attempt $RETRY_COUNT/$MAX_RETRIES)"
103-
sleep $RETRY_DELAY
104-
RETRY_DELAY=$((RETRY_DELAY * 2))
105-
else
106-
echo "::error::Failed to push after $MAX_RETRIES attempts"
107-
exit 1
108-
fi
109-
fi
110-
done
111-
echo "::endgroup::"
112-
11370
- name: Create brew formula
11471
if: steps.update.outputs.updated == 'true'
115-
id: brew-formula
11672
run: |
117-
echo "::group::Creating Homebrew formula"
118-
119-
FORMULA_DIR="Formula"
120-
mkdir -p "$FORMULA_DIR"
121-
122-
REPO_URL="https://github.com/${{ github.repository }}"
123-
REPO_NAME="${{ github.event.repository.name }}"
124-
125-
cat > "$FORMULA_DIR/claude-plugin-marketplace.rb" <<'FORMULA_EOF'
73+
mkdir -p Formula
74+
cat > Formula/claude-plugin-marketplace.rb <<'EOF'
12675
class ClaudePluginMarketplace < Formula
127-
desc "Claude Code plugin marketplace - community-driven plugins for Claude Code"
76+
desc "Claude Code plugin marketplace - community-driven plugins"
12877
homepage "https://github.com/${{ github.repository }}"
12978
url "https://github.com/${{ github.repository }}/archive/refs/heads/main.tar.gz"
13079
version "latest"
13180
sha256 :no_check
13281
13382
def install
134-
# This is a meta-formula that doesn't install binaries
135-
# Instead, it sets up the marketplace for Claude Code
13683
libexec.install Dir["*"]
137-
138-
# Create setup script
13984
(bin/"claude-plugin-marketplace-setup").write <<~EOS
14085
#!/bin/bash
14186
set -e
142-
14387
MARKETPLACE_DIR="${HOME}/.claude-code/marketplaces/community"
144-
REPO_URL="#{homepage}"
145-
146-
echo "Setting up Claude Code Plugin Marketplace..."
147-
14888
if [ -d "$MARKETPLACE_DIR" ]; then
149-
echo "Marketplace already exists at $MARKETPLACE_DIR"
150-
echo "Updating..."
151-
cd "$MARKETPLACE_DIR"
152-
git pull
89+
cd "$MARKETPLACE_DIR" && git pull
15390
else
154-
echo "Cloning marketplace to $MARKETPLACE_DIR"
15591
mkdir -p "$(dirname "$MARKETPLACE_DIR")"
156-
git clone "$REPO_URL" "$MARKETPLACE_DIR"
157-
fi
158-
159-
echo "✓ Marketplace setup complete!"
160-
echo ""
161-
echo "Available plugins:"
162-
if command -v jq &> /dev/null; then
163-
jq -r '.plugins[] | " - \\(.name) (v\\(.version)): \\(.description)"' \
164-
"$MARKETPLACE_DIR/.claude-plugin/marketplace.json"
165-
else
166-
echo " Install jq to see plugin list"
92+
git clone "#{homepage}" "$MARKETPLACE_DIR"
16793
fi
94+
echo "Marketplace setup complete!"
16895
EOS
169-
17096
chmod +x bin/"claude-plugin-marketplace-setup"
17197
end
17298
173-
def caveats
174-
<<~EOS
175-
To set up the Claude Code Plugin Marketplace, run:
176-
claude-plugin-marketplace-setup
177-
178-
This will clone the marketplace repository to:
179-
#{ENV["HOME"]}/.claude-code/marketplaces/community
180-
181-
You can then install plugins using Claude Code commands.
182-
EOS
183-
end
184-
18599
test do
186-
assert_predicate bin/"claude-plugin-marketplace-setup", :exist?
187100
assert_predicate bin/"claude-plugin-marketplace-setup", :executable?
188101
end
189102
end
190-
FORMULA_EOF
191-
192-
# Replace template variables
193-
sed -i "s|\${{ github.repository }}|${{ github.repository }}|g" "$FORMULA_DIR/claude-plugin-marketplace.rb"
194-
195-
echo "::notice::Homebrew formula created at $FORMULA_DIR/claude-plugin-marketplace.rb"
196-
echo "::endgroup::"
197-
198-
cat "$FORMULA_DIR/claude-plugin-marketplace.rb"
199-
200-
- name: Commit brew formula
201-
if: steps.update.outputs.updated == 'true'
202-
run: |
203-
git add Formula/
204-
205-
if [ -n "$(git status --porcelain Formula/)" ]; then
206-
git commit -m "$(cat <<'EOF'
207-
chore: update homebrew formula [skip ci]
208-
209-
Updated Homebrew formula for marketplace distribution.
210103
EOF
211-
)"
212104
213-
echo "::group::Pushing formula"
214-
set +e
215-
RETRY_COUNT=0
216-
MAX_RETRIES=4
217-
RETRY_DELAY=2
218-
219-
while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
220-
if git push; then
221-
echo "::notice::Successfully pushed formula update"
222-
break
223-
else
224-
RETRY_COUNT=$((RETRY_COUNT + 1))
225-
if [ $RETRY_COUNT -lt $MAX_RETRIES ]; then
226-
echo "::warning::Push failed, retrying in ${RETRY_DELAY}s (attempt $RETRY_COUNT/$MAX_RETRIES)"
227-
sleep $RETRY_DELAY
228-
RETRY_DELAY=$((RETRY_DELAY * 2))
229-
else
230-
echo "::error::Failed to push after $MAX_RETRIES attempts"
231-
exit 1
232-
fi
233-
fi
234-
done
235-
echo "::endgroup::"
236-
else
237-
echo "::notice::No changes to formula"
238-
fi
105+
- name: Commit changes
106+
if: steps.update.outputs.updated == 'true'
107+
uses: stefanzweifel/git-auto-commit-action@v5
108+
with:
109+
commit_message: 'chore: update marketplace metadata [skip ci]'
110+
file_pattern: '.claude-plugin/marketplace.json Formula/'

.github/workflows/ci.yaml

Lines changed: 10 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -78,42 +78,9 @@ jobs:
7878
7979
- name: Commit and push fixes
8080
if: steps.check-changes.outputs.has-changes == 'true'
81-
run: |
82-
git config --local user.email "github-actions[bot]@users.noreply.github.com"
83-
git config --local user.name "github-actions[bot]"
84-
85-
git add -A
86-
87-
git commit -m "$(cat <<'EOF'
88-
chore: auto-fix lint issues
89-
90-
Automatically fixed lint errors found in CI.
91-
EOF
92-
)"
93-
94-
echo "::group::Pushing changes"
95-
set +e
96-
RETRY_COUNT=0
97-
MAX_RETRIES=4
98-
RETRY_DELAY=2
99-
100-
while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
101-
if git push; then
102-
echo "::notice::Successfully pushed lint fixes"
103-
exit 0
104-
else
105-
RETRY_COUNT=$((RETRY_COUNT + 1))
106-
if [ $RETRY_COUNT -lt $MAX_RETRIES ]; then
107-
echo "::warning::Push failed, retrying in ${RETRY_DELAY}s (attempt $RETRY_COUNT/$MAX_RETRIES)"
108-
sleep $RETRY_DELAY
109-
RETRY_DELAY=$((RETRY_DELAY * 2))
110-
else
111-
echo "::error::Failed to push after $MAX_RETRIES attempts"
112-
exit 1
113-
fi
114-
fi
115-
done
116-
echo "::endgroup::"
81+
uses: stefanzweifel/git-auto-commit-action@v5
82+
with:
83+
commit_message: 'chore: auto-fix lint issues'
11784

11885
- name: Rerun lint after fixes
11986
if: steps.check-changes.outputs.has-changes == 'true'
@@ -128,38 +95,14 @@ jobs:
12895
steps.check-changes.outputs.has-changes != 'true')
12996
id: collect-errors
13097
run: |
131-
echo "::group::Collecting lint errors"
132-
133-
ERROR_LOG=$(mktemp)
134-
135-
# Rerun linters to collect errors
136-
yamllint -f parsable . > $ERROR_LOG 2>&1 || true
137-
npx prettier --check "**/*.json" >> $ERROR_LOG 2>&1 || true
138-
npx markdownlint-cli2 "**/*.md" "#node_modules" >> $ERROR_LOG 2>&1 || true
139-
140-
if [ -f "package.json" ]; then
141-
npx eslint "**/*.{ts,js,tsx,jsx}" >> $ERROR_LOG 2>&1 || true
142-
fi
143-
144-
if find . -name "*.py" -not -path "*/\.*" | grep -q .; then
145-
flake8 . >> $ERROR_LOG 2>&1 || true
146-
fi
147-
148-
# Format errors for comment
149-
ERRORS=$(cat $ERROR_LOG | head -50)
150-
151-
if [ -z "$ERRORS" ]; then
152-
ERRORS="No specific errors captured, but lint check failed."
153-
fi
154-
155-
# Save to output
15698
{
157-
echo 'errors<<EOF'
158-
echo "$ERRORS"
159-
echo 'EOF'
160-
} >> $GITHUB_OUTPUT
161-
162-
echo "::endgroup::"
99+
yamllint -f parsable . 2>&1 || true
100+
npx prettier --check "**/*.json" 2>&1 || true
101+
npx markdownlint-cli2 "**/*.md" "#node_modules" 2>&1 || true
102+
} | head -50 > /tmp/errors.txt
103+
echo 'errors<<EOF' >> $GITHUB_OUTPUT
104+
cat /tmp/errors.txt >> $GITHUB_OUTPUT
105+
echo 'EOF' >> $GITHUB_OUTPUT
163106
164107
- name: Comment unfixable errors on PR
165108
if: >-

plugins/memory-manager/README.md

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Memory Manager Plugin
2+
3+
Intelligent memory management for CLAUDE.md files. Automatically detects and stores user preferences, rules, and instructions with smart scope detection and hierarchical organization.
4+
5+
## Features
6+
7+
- **Automatic Detection**: Watches for phrases like "always", "never", "don't forget", "prefer", "remember to", "from now on"
8+
- **Smart Scope Detection**: Intelligently determines if preferences should be stored globally or per-project
9+
- **Hierarchical Organization**: Organizes memories into categories with proper markdown structure
10+
- **Confirmation Messages**: Shows what was remembered and where it was written
11+
12+
## Installation
13+
14+
```bash
15+
/plugin install memory-manager@nsheaps-claude-plugins
16+
```
17+
18+
## Usage
19+
20+
Simply express preferences naturally in conversation:
21+
22+
- "Never use rebasing, prefer merge instead"
23+
- "Always put API endpoints in src/api/ in this project"
24+
- "Don't forget to run tests before committing"
25+
26+
The plugin will automatically:
27+
1. Detect the memory-worthy statement
28+
2. Determine the appropriate scope (global or project)
29+
3. Update the relevant CLAUDE.md file
30+
4. Confirm with messages like:
31+
- `I'll remember to prefer merging over rebasing`
32+
- `Wrote $HOME/.claude/CLAUDE.md`
33+
34+
## Trigger Phrases
35+
36+
The plugin activates on:
37+
- "always", "never"
38+
- "don't forget", "make sure"
39+
- "prefer X over Y"
40+
- "remember to...", "from now on..."
41+
- "I can't believe you did that"
42+
- "You messed up", "did it wrong"
43+
- Important dates (vacation, birthdays, deadlines)
44+
45+
## Scope Detection
46+
47+
**Global scope** (written to `~/.claude/CLAUDE.md`):
48+
- Mentions "all projects", "everywhere"
49+
- Tool preferences, git workflow, communication style
50+
51+
**Project scope** (written to project's CLAUDE.md):
52+
- Mentions specific files or directories
53+
- Architecture decisions for this codebase
54+
- User says "in this project"
55+
56+
## Memory Categories
57+
58+
Memories are organized under sections:
59+
- Git Workflow
60+
- Code Style
61+
- Development Environment
62+
- Testing Preferences
63+
- Documentation
64+
- Architecture
65+
- Dependencies
66+
- Communication Style
67+
68+
## License
69+
70+
MIT

0 commit comments

Comments
 (0)