ima-claude 2.14.1 → 2.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -1
- package/dist/cli.js +16 -1
- package/package.json +1 -1
- package/plugins/ima-claude/.claude-plugin/plugin.json +2 -2
- package/plugins/ima-claude/skills/ima-copywriting/SKILL.md +232 -0
- package/plugins/ima-claude/skills/ima-copywriting/references/format-blog-post.md +51 -0
- package/plugins/ima-claude/skills/ima-copywriting/references/format-fundraising-email.md +54 -0
- package/plugins/ima-claude/skills/ima-copywriting/references/format-newsletter.md +54 -0
- package/plugins/ima-claude/skills/ima-copywriting/references/format-op-ed.md +41 -0
- package/plugins/ima-claude/skills/ima-copywriting/references/format-press-release.md +45 -0
- package/plugins/ima-claude/skills/ima-copywriting/references/format-social-media.md +141 -0
- package/plugins/ima-claude/skills/ima-copywriting/references/format-webinar-email.md +37 -0
- package/plugins/ima-claude/skills/ima-copywriting/references/ima-copy-frameworks.md +299 -0
- package/plugins/ima-claude/skills/ima-copywriting/references/ima-transitions.md +199 -0
- package/plugins/ima-claude/skills/ima-editorial-scorecard/SKILL.md +159 -0
- package/plugins/ima-claude/skills/ima-editorial-scorecard/references/format-expectations.md +66 -0
- package/plugins/ima-claude/skills/ima-editorial-scorecard/references/scoring-rubrics.md +73 -0
- package/plugins/ima-claude/skills/ima-editorial-workflow/SKILL.md +171 -0
- package/plugins/ima-claude/skills/ima-email-creator/SKILL.md +104 -0
- package/plugins/ima-claude/skills/ima-email-creator/assets/base-template.html +256 -0
- package/plugins/ima-claude/skills/ima-email-creator/references/drip-sequence.md +66 -0
- package/plugins/ima-claude/skills/ima-email-creator/references/email-css-safe.md +104 -0
- package/plugins/ima-claude/skills/ima-email-creator/references/espocrm-compat.md +58 -0
- package/plugins/ima-claude/skills/ima-email-creator/references/newsletter-layout.md +127 -0
- package/plugins/ima-claude/skills/ima-email-creator/references/wp-transactional.md +77 -0
- package/plugins/ima-claude/skills/ima-email-creator/scripts/css-inliner.py +47 -0
- package/plugins/ima-claude/skills/ima-email-creator/scripts/espocrm-prep.py +52 -0
- package/plugins/ima-claude/skills/ima-email-creator/scripts/requirements.txt +2 -0
- package/plugins/ima-claude/skills/prompt-starter/SKILL.md +128 -0
- package/plugins/ima-claude/skills/prompt-starter/references/brainstorm.md +25 -0
- package/plugins/ima-claude/skills/prompt-starter/references/plan-implement.md +35 -0
- package/plugins/ima-claude/skills/prompt-starter/references/quick.md +11 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# PHP Email Template Patterns for WordPress
|
|
2
|
+
|
|
3
|
+
## Architecture: Pure Function + WordPress Wrapper
|
|
4
|
+
|
|
5
|
+
The IMA codebase separates email generation from sending:
|
|
6
|
+
- **Pure functions** generate HTML/text with zero WordPress dependencies (testable)
|
|
7
|
+
- **WordPress wrappers** handle side effects (wp_mail, user lookups, logging)
|
|
8
|
+
|
|
9
|
+
## Brand Alignment Note
|
|
10
|
+
|
|
11
|
+
WordPress transactional emails use the **ima-brand plugin colors**: `#00066F` Indigo headers, `#00B8B8` Aquatic Pulse CTAs, `#494949` Gravel text — applied via `ima_brand_email_wrapper()`.
|
|
12
|
+
|
|
13
|
+
Marketing emails (BeeFree/EspoCRM drip and campaign) are now aligned to the same brand book colors: `#00B8B8` Aquatic Pulse CTAs, `#494949` Gravel text — replacing the old `#0296a1`/`#374751` palette. The only distinction is that transactional emails also use `#00066F` Indigo for headers (via `ima_brand_email_wrapper()`), which marketing email templates handle in their own header blocks.
|
|
14
|
+
|
|
15
|
+
## The Brand Wrapper
|
|
16
|
+
|
|
17
|
+
`ima_brand_email_wrapper()` from `ima-brand` plugin provides:
|
|
18
|
+
- Consistent outer HTML structure (header with logo, footer)
|
|
19
|
+
- Brand colors and typography
|
|
20
|
+
- Location: `wp-content/plugins/ima-brand/includes/email-template.php`
|
|
21
|
+
|
|
22
|
+
```php
|
|
23
|
+
$html = ima_brand_email_wrapper($inner_html, $subject);
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Pure Template Pattern
|
|
27
|
+
|
|
28
|
+
```php
|
|
29
|
+
// inc/pure/email-templates.php
|
|
30
|
+
declare(strict_types=1);
|
|
31
|
+
|
|
32
|
+
function ima_build_invitation_email(array $data): string {
|
|
33
|
+
// Pure function — no WordPress calls, no side effects
|
|
34
|
+
$name = htmlspecialchars($data['name'], ENT_QUOTES, 'UTF-8');
|
|
35
|
+
// ... build HTML with inline styles ...
|
|
36
|
+
return $html;
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## WordPress Wrapper Pattern
|
|
41
|
+
|
|
42
|
+
```php
|
|
43
|
+
// inc/invitation-emails.php
|
|
44
|
+
function ima_send_invitation_email(int $user_id, string $code): bool {
|
|
45
|
+
$user = get_userdata($user_id);
|
|
46
|
+
$html = ima_build_invitation_email([
|
|
47
|
+
'name' => $user->display_name,
|
|
48
|
+
'code' => $code,
|
|
49
|
+
]);
|
|
50
|
+
$wrapped = ima_brand_email_wrapper($html, 'Your Invitation');
|
|
51
|
+
return wp_mail($user->user_email, 'Your Invitation', $wrapped, [
|
|
52
|
+
'Content-Type: text/html; charset=UTF-8',
|
|
53
|
+
]);
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Existing Email Modules
|
|
58
|
+
|
|
59
|
+
| Module | Location | Purpose |
|
|
60
|
+
|--------|----------|---------|
|
|
61
|
+
| Invitations | child theme `inc/pure/email-templates.php` | Invitation, activation, application emails |
|
|
62
|
+
| Payments | `ima-payments` plugin | Receipt emails with PDF attachments |
|
|
63
|
+
| Memberships | `ima-memberships` plugin | Retention and welcome emails |
|
|
64
|
+
| Registration | `ima-registration` plugin | Email verification codes |
|
|
65
|
+
| Contact forms | `ima-forms` plugin | Form submission notifications |
|
|
66
|
+
|
|
67
|
+
## Key Rules
|
|
68
|
+
|
|
69
|
+
- Always escape: `htmlspecialchars($value, ENT_QUOTES, 'UTF-8')`
|
|
70
|
+
- Set content type header: `Content-Type: text/html; charset=UTF-8`
|
|
71
|
+
- Use `do_action('ima_log_info', 'Email sent to: ' . $email)` for logging
|
|
72
|
+
- Plain text fallback via `wp_mail` multipart (optional but good practice)
|
|
73
|
+
|
|
74
|
+
## When to Use This vs. Newsletter/Campaign
|
|
75
|
+
|
|
76
|
+
- **This pattern**: System-triggered emails (verification, receipts, notifications) — lives in PHP, runs in WordPress
|
|
77
|
+
- **Newsletter/Campaign**: Marketing emails created in Claude, pasted into EspoCRM — platform-agnostic HTML
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Inline <style> blocks into element style attributes.
|
|
4
|
+
|
|
5
|
+
Uses premailer to handle CSS specificity correctly. Designed for emails
|
|
6
|
+
built with style blocks (e.g. BeeFree exports) that need inlining for
|
|
7
|
+
Gmail compatibility.
|
|
8
|
+
|
|
9
|
+
Usage:
|
|
10
|
+
python3 css-inliner.py input.html
|
|
11
|
+
python3 css-inliner.py input.html --out output.html
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import argparse
|
|
15
|
+
import sys
|
|
16
|
+
import premailer
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def inline_css(html: str) -> str:
|
|
20
|
+
return premailer.transform(
|
|
21
|
+
html,
|
|
22
|
+
remove_classes=False,
|
|
23
|
+
strip_important=True,
|
|
24
|
+
keep_style_tags=False,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def main():
|
|
29
|
+
parser = argparse.ArgumentParser(description="Inline CSS for email compatibility")
|
|
30
|
+
parser.add_argument("input", help="Input HTML file")
|
|
31
|
+
parser.add_argument("--out", help="Output file (default: stdout)")
|
|
32
|
+
args = parser.parse_args()
|
|
33
|
+
|
|
34
|
+
with open(args.input, "r", encoding="utf-8") as f:
|
|
35
|
+
html = f.read()
|
|
36
|
+
|
|
37
|
+
result = inline_css(html)
|
|
38
|
+
|
|
39
|
+
if args.out:
|
|
40
|
+
with open(args.out, "w", encoding="utf-8") as f:
|
|
41
|
+
f.write(result)
|
|
42
|
+
else:
|
|
43
|
+
sys.stdout.write(result)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
if __name__ == "__main__":
|
|
47
|
+
main()
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Extract body content from any HTML email and wrap it in a styled div.
|
|
4
|
+
|
|
5
|
+
Strips document-level tags (<html>, <head>, <body>) and migrates body styles
|
|
6
|
+
to a wrapping div. Works on BeeFree exports, IMA emails, or any HTML.
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
python3 espocrm-prep.py input.html
|
|
10
|
+
python3 espocrm-prep.py input.html --out output.html
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import argparse
|
|
14
|
+
import sys
|
|
15
|
+
from bs4 import BeautifulSoup
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def extract_body_content(html: str) -> str:
|
|
19
|
+
soup = BeautifulSoup(html, "html.parser")
|
|
20
|
+
body = soup.find("body")
|
|
21
|
+
|
|
22
|
+
if body is None:
|
|
23
|
+
return html
|
|
24
|
+
|
|
25
|
+
style = body.get("style", "")
|
|
26
|
+
inner_html = body.decode_contents()
|
|
27
|
+
|
|
28
|
+
if style:
|
|
29
|
+
return f'<div style="{style}">{inner_html}</div>'
|
|
30
|
+
return inner_html
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def main():
|
|
34
|
+
parser = argparse.ArgumentParser(description="Prepare HTML email for EspoCRM")
|
|
35
|
+
parser.add_argument("input", help="Input HTML file")
|
|
36
|
+
parser.add_argument("--out", help="Output file (default: stdout)")
|
|
37
|
+
args = parser.parse_args()
|
|
38
|
+
|
|
39
|
+
with open(args.input, "r", encoding="utf-8") as f:
|
|
40
|
+
html = f.read()
|
|
41
|
+
|
|
42
|
+
result = extract_body_content(html)
|
|
43
|
+
|
|
44
|
+
if args.out:
|
|
45
|
+
with open(args.out, "w", encoding="utf-8") as f:
|
|
46
|
+
f.write(result)
|
|
47
|
+
else:
|
|
48
|
+
sys.stdout.write(result)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
if __name__ == "__main__":
|
|
52
|
+
main()
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: prompt-starter
|
|
3
|
+
description: Zero-friction prompt templates (quick, brainstorm, plan-implement). Selects template, pre-fills from Jira, opens in GUI editor, reads back on close.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Prompt Starter
|
|
7
|
+
|
|
8
|
+
Load a structured prompt template, pre-fill it with Jira context, open it in the user's GUI editor, and execute the result when they close the file.
|
|
9
|
+
|
|
10
|
+
**Trigger words:**
|
|
11
|
+
- `brainstorm`, `research`, `explore` → `references/brainstorm.md`
|
|
12
|
+
- `plan`, `implement`, `build`, `execute` → `references/plan-implement.md`
|
|
13
|
+
- `quick`, or a short one-liner task → `references/quick.md`
|
|
14
|
+
- Just a Jira key with no clear workflow → ask the user which template
|
|
15
|
+
|
|
16
|
+
## Relationship to prompt_coach.py
|
|
17
|
+
|
|
18
|
+
- **prompt-starter** = "What should my prompt say?" (template + context + editor)
|
|
19
|
+
- **prompt_coach.py** = "Is my prompt good enough?" (quality evaluation)
|
|
20
|
+
|
|
21
|
+
Different lanes, complementary. The coach may fire on the final prompt — that's fine.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Template Selection
|
|
26
|
+
|
|
27
|
+
Match the user's trigger words to select a template. Examples:
|
|
28
|
+
|
|
29
|
+
| User says | Template |
|
|
30
|
+
|---|---|
|
|
31
|
+
| "brainstorm FNR-1234" | brainstorm.md |
|
|
32
|
+
| "research auth options" | brainstorm.md |
|
|
33
|
+
| "plan and implement FNR-567" | plan-implement.md |
|
|
34
|
+
| "build the PDF export" | plan-implement.md |
|
|
35
|
+
| "quick task: add validation" | quick.md |
|
|
36
|
+
| "FNR-1234" (ambiguous) | Ask which workflow |
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Flow
|
|
41
|
+
|
|
42
|
+
### Step 1: Select template
|
|
43
|
+
|
|
44
|
+
Read the appropriate template from `references/`.
|
|
45
|
+
|
|
46
|
+
### Step 2: Fetch Jira context (if Jira key present)
|
|
47
|
+
|
|
48
|
+
Use mcp-atlassian to fetch the issue. Extract:
|
|
49
|
+
- **Summary** → fills the one-line goal / user story
|
|
50
|
+
- **Description** → fills the Problem section
|
|
51
|
+
- **Acceptance Criteria** (from description or subtasks) → fills Acceptance / Test sections
|
|
52
|
+
|
|
53
|
+
Map Jira fields to template `[bracket]` placeholders naturally — don't create a rigid substitution engine. Use judgment: if the Jira description is rich, use it; if sparse, leave the bracket hint for the user to fill in.
|
|
54
|
+
|
|
55
|
+
### Step 3: Check prior work (plan-implement only)
|
|
56
|
+
|
|
57
|
+
For plan-implement templates, search Serena memory for `{feature-name}-brainstorm`. If found, pre-fill the **Prior Work** section with a reference to it and incorporate key decisions into the **Plan** section.
|
|
58
|
+
|
|
59
|
+
### Step 4: Write the pre-filled template
|
|
60
|
+
|
|
61
|
+
Create the prompt directory if needed:
|
|
62
|
+
```bash
|
|
63
|
+
mkdir -p ~/.claude/prompts
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Write the pre-filled template to `~/.claude/prompts/{session-name}.md` where session-name is descriptive:
|
|
67
|
+
- `brainstorm-pdf-export.md`
|
|
68
|
+
- `quick-email-validation.md`
|
|
69
|
+
- `plan-fnr-1234.md`
|
|
70
|
+
|
|
71
|
+
### Step 5: Open in editor (or present inline)
|
|
72
|
+
|
|
73
|
+
**Quick template exception:** Quick templates are short (12 lines). Present them inline in the conversation — no editor spawn. Skip to Step 7.
|
|
74
|
+
|
|
75
|
+
**For brainstorm and plan-implement templates**, spawn the user's GUI editor.
|
|
76
|
+
|
|
77
|
+
#### Editor Resolution
|
|
78
|
+
|
|
79
|
+
Claude Code owns the terminal, so terminal editors (nano, vim) cannot be used — the user can't interact with them. Only GUI editors work.
|
|
80
|
+
|
|
81
|
+
Resolution order:
|
|
82
|
+
1. `$VISUAL` — the Unix convention for GUI editors
|
|
83
|
+
2. `$EDITOR` — but **only** if it's a known GUI editor: `zed`, `code`, `subl`, `gedit`, `kate`
|
|
84
|
+
3. Auto-detect: check `which zed`, then `which code`, then `which subl` — use the first found
|
|
85
|
+
4. **Fallback:** no suitable editor found → present inline and modify via conversation
|
|
86
|
+
|
|
87
|
+
#### Spawning the editor
|
|
88
|
+
|
|
89
|
+
Use Bash with `run_in_background: true`:
|
|
90
|
+
```bash
|
|
91
|
+
zed --wait ~/.claude/prompts/{session-name}.md
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
All GUI editors use `--wait` so the process blocks until the user closes the file/tab.
|
|
95
|
+
|
|
96
|
+
Tell the user:
|
|
97
|
+
> Template is open in {editor}. Edit and close the tab when done — I'll pick up from there.
|
|
98
|
+
|
|
99
|
+
### Step 6: Read the result
|
|
100
|
+
|
|
101
|
+
When the background task completes (editor closed), read the file back:
|
|
102
|
+
```
|
|
103
|
+
Read ~/.claude/prompts/{session-name}.md
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Step 7: Confirm and execute
|
|
107
|
+
|
|
108
|
+
Present the final prompt to the user. Ask for confirmation:
|
|
109
|
+
> Here's your prompt. Ready to execute, or want to adjust anything?
|
|
110
|
+
|
|
111
|
+
On confirmation, treat the prompt content as working instructions and execute accordingly.
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Editor Notes for Team Onboarding
|
|
116
|
+
|
|
117
|
+
Team members should set `$VISUAL` in their shell profile for the best experience:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
# Zed
|
|
121
|
+
echo 'export VISUAL="zed --wait"' >> ~/.bashrc
|
|
122
|
+
|
|
123
|
+
# VS Code
|
|
124
|
+
echo 'export VISUAL="code --wait"' >> ~/.bashrc
|
|
125
|
+
|
|
126
|
+
# Sublime Text
|
|
127
|
+
echo 'export VISUAL="subl --wait"' >> ~/.bashrc
|
|
128
|
+
```
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
[One-line goal as a user story]
|
|
2
|
+
|
|
3
|
+
## Problem
|
|
4
|
+
[What's broken or missing. Be specific about the symptom.]
|
|
5
|
+
|
|
6
|
+
## Context
|
|
7
|
+
[Repo, branch, related systems, infrastructure details]
|
|
8
|
+
|
|
9
|
+
## Research
|
|
10
|
+
- [Specific things to investigate, with scoped locations]
|
|
11
|
+
- [Reference patterns to follow: "like X" or "see Y"]
|
|
12
|
+
|
|
13
|
+
## Q&A
|
|
14
|
+
After completing research, interview me using the AskUserQuestion tool.
|
|
15
|
+
Dig into edge cases, tradeoffs, and constraints — skip obvious questions.
|
|
16
|
+
|
|
17
|
+
- [Seed questions/concerns you already have]
|
|
18
|
+
|
|
19
|
+
## Document
|
|
20
|
+
Save the outcome to Serena memory as `{feature-name}-brainstorm`.
|
|
21
|
+
Include:
|
|
22
|
+
- Original user story and problem statement
|
|
23
|
+
- Key findings from research
|
|
24
|
+
- Decisions and tradeoffs from Q&A
|
|
25
|
+
- Recommended approach (not a full plan — just direction)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
[One-line goal as a user story]
|
|
2
|
+
Save this prompt and plan to Serena memory as `{feature-name}-plan`.
|
|
3
|
+
|
|
4
|
+
## Problem
|
|
5
|
+
[What's broken or missing. Be specific about the symptom.]
|
|
6
|
+
|
|
7
|
+
## Prior Work
|
|
8
|
+
[Reference brainstorming: "See Serena memory `{feature-name}-brainstorm`"]
|
|
9
|
+
|
|
10
|
+
## Context
|
|
11
|
+
[Repo, branch, infrastructure — if not already in brainstorming]
|
|
12
|
+
|
|
13
|
+
## Plan
|
|
14
|
+
- [Approach, informed by brainstorming outcomes]
|
|
15
|
+
- [Open implementation questions with `?`]
|
|
16
|
+
- [Constraints: "prefer X unless evidence shows Y"]
|
|
17
|
+
|
|
18
|
+
## Implement
|
|
19
|
+
[Numbered deliverables in priority order]
|
|
20
|
+
|
|
21
|
+
For each story: Implement → Test → Review, then repeat for the full picture.
|
|
22
|
+
|
|
23
|
+
## Test
|
|
24
|
+
- [How to verify EACH deliverable]
|
|
25
|
+
|
|
26
|
+
## Review
|
|
27
|
+
- [Which review tool/agent and what to check for]
|
|
28
|
+
|
|
29
|
+
## Document
|
|
30
|
+
- [Explicit list of files to update]
|
|
31
|
+
|
|
32
|
+
## Agents (recommended for multi-story work)
|
|
33
|
+
- ima-claude:implementer for [phase] with skills: [...]
|
|
34
|
+
- ima-claude:tester with /unit-testing
|
|
35
|
+
- ima-claude:reviewer after implementation
|