@heylemon/lemonade 0.2.2 → 0.2.3
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/dist/build-info.json +3 -3
- package/dist/canvas-host/a2ui/.bundle.hash +1 -1
- package/package.json +1 -1
- package/skills/brave-search/SKILL.md +57 -0
- package/skills/brave-search/content.js +86 -0
- package/skills/brave-search/package.json +14 -0
- package/skills/brave-search/search.js +179 -0
- package/skills/caldav-calendar/SKILL.md +104 -0
- package/skills/frontend-design/SKILL.md +39 -0
- package/skills/self-improving-agent/SKILL.md +128 -0
- package/skills/stock-analysis/SKILL.md +131 -0
- package/skills/stock-analysis/scripts/analyze_stock.py +2532 -0
- package/skills/stock-analysis/scripts/dividends.py +365 -0
- package/skills/stock-analysis/scripts/hot_scanner.py +565 -0
- package/skills/stock-analysis/scripts/portfolio.py +528 -0
- package/skills/stock-analysis/scripts/rumor_scanner.py +330 -0
- package/skills/stock-analysis/scripts/watchlist.py +318 -0
- package/skills/tavily-search/SKILL.md +38 -0
- package/skills/tavily-search/scripts/extract.mjs +59 -0
- package/skills/tavily-search/scripts/search.mjs +101 -0
- package/skills/youtube-watcher/SKILL.md +46 -0
- package/skills/youtube-watcher/scripts/get_transcript.py +81 -0
package/dist/build-info.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
dda15b99462cc0b2ef3beeaf3b47c8ead319daf27fd6466820c14e02ea7b21a3
|
package/package.json
CHANGED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: brave-search
|
|
3
|
+
description: Web search and content extraction via Brave Search API. Use for searching documentation, facts, or any web content. Lightweight, no browser required.
|
|
4
|
+
metadata: {"lemonade":{"emoji":"🦁","requires":{"bins":["node"]}}}
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Brave Search
|
|
8
|
+
|
|
9
|
+
Headless web search and content extraction using Brave Search. No browser required.
|
|
10
|
+
|
|
11
|
+
## Setup
|
|
12
|
+
|
|
13
|
+
Run once before first use:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
cd {baseDir}
|
|
17
|
+
npm ci
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Search
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
node {baseDir}/search.js "query" # Basic search (5 results)
|
|
24
|
+
node {baseDir}/search.js "query" -n 10 # More results
|
|
25
|
+
node {baseDir}/search.js "query" --content # Include page content as markdown
|
|
26
|
+
node {baseDir}/search.js "query" -n 3 --content # Combined
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Extract Page Content
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
node {baseDir}/content.js https://example.com/article
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Fetches a URL and extracts readable content as markdown.
|
|
36
|
+
|
|
37
|
+
## Output Format
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
--- Result 1 ---
|
|
41
|
+
Title: Page Title
|
|
42
|
+
Link: https://example.com/page
|
|
43
|
+
Snippet: Description from search results
|
|
44
|
+
Content: (if --content flag used)
|
|
45
|
+
Markdown content extracted from the page...
|
|
46
|
+
|
|
47
|
+
--- Result 2 ---
|
|
48
|
+
...
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## When to Use
|
|
52
|
+
|
|
53
|
+
- Searching for documentation or API references
|
|
54
|
+
- Looking up facts or current information
|
|
55
|
+
- Fetching content from specific URLs
|
|
56
|
+
- Any task requiring web search without interactive browsing
|
|
57
|
+
```
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { Readability } from "@mozilla/readability";
|
|
4
|
+
import { JSDOM } from "jsdom";
|
|
5
|
+
import TurndownService from "turndown";
|
|
6
|
+
import { gfm } from "turndown-plugin-gfm";
|
|
7
|
+
|
|
8
|
+
const url = process.argv[2];
|
|
9
|
+
|
|
10
|
+
if (!url) {
|
|
11
|
+
console.log("Usage: content.js <url>");
|
|
12
|
+
console.log("\nExtracts readable content from a webpage as markdown.");
|
|
13
|
+
console.log("\nExamples:");
|
|
14
|
+
console.log(" content.js https://example.com/article");
|
|
15
|
+
console.log(" content.js https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html");
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function htmlToMarkdown(html) {
|
|
20
|
+
const turndown = new TurndownService({ headingStyle: "atx", codeBlockStyle: "fenced" });
|
|
21
|
+
turndown.use(gfm);
|
|
22
|
+
turndown.addRule("removeEmptyLinks", {
|
|
23
|
+
filter: (node) => node.nodeName === "A" && !node.textContent?.trim(),
|
|
24
|
+
replacement: () => "",
|
|
25
|
+
});
|
|
26
|
+
return turndown
|
|
27
|
+
.turndown(html)
|
|
28
|
+
.replace(/\[\\?\[\s*\\?\]\]\([^)]*\)/g, "")
|
|
29
|
+
.replace(/ +/g, " ")
|
|
30
|
+
.replace(/\s+,/g, ",")
|
|
31
|
+
.replace(/\s+\./g, ".")
|
|
32
|
+
.replace(/\n{3,}/g, "\n\n")
|
|
33
|
+
.trim();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
try {
|
|
37
|
+
const response = await fetch(url, {
|
|
38
|
+
headers: {
|
|
39
|
+
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
|
40
|
+
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
|
|
41
|
+
"Accept-Language": "en-US,en;q=0.9",
|
|
42
|
+
},
|
|
43
|
+
signal: AbortSignal.timeout(15000),
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
if (!response.ok) {
|
|
47
|
+
console.error(`HTTP ${response.status}: ${response.statusText}`);
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const html = await response.text();
|
|
52
|
+
const dom = new JSDOM(html, { url });
|
|
53
|
+
const reader = new Readability(dom.window.document);
|
|
54
|
+
const article = reader.parse();
|
|
55
|
+
|
|
56
|
+
if (article && article.content) {
|
|
57
|
+
if (article.title) {
|
|
58
|
+
console.log(`# ${article.title}\n`);
|
|
59
|
+
}
|
|
60
|
+
console.log(htmlToMarkdown(article.content));
|
|
61
|
+
process.exit(0);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Fallback: try to extract main content
|
|
65
|
+
const fallbackDoc = new JSDOM(html, { url });
|
|
66
|
+
const body = fallbackDoc.window.document;
|
|
67
|
+
body.querySelectorAll("script, style, noscript, nav, header, footer, aside").forEach(el => el.remove());
|
|
68
|
+
|
|
69
|
+
const title = body.querySelector("title")?.textContent?.trim();
|
|
70
|
+
const main = body.querySelector("main, article, [role='main'], .content, #content") || body.body;
|
|
71
|
+
|
|
72
|
+
if (title) {
|
|
73
|
+
console.log(`# ${title}\n`);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const text = main?.innerHTML || "";
|
|
77
|
+
if (text.trim().length > 100) {
|
|
78
|
+
console.log(htmlToMarkdown(text));
|
|
79
|
+
} else {
|
|
80
|
+
console.error("Could not extract readable content from this page.");
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
83
|
+
} catch (e) {
|
|
84
|
+
console.error(`Error: ${e.message}`);
|
|
85
|
+
process.exit(1);
|
|
86
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "brave-search",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Headless web search via Brave Search - no browser required",
|
|
6
|
+
"author": "Mario Zechner",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"dependencies": {
|
|
9
|
+
"@mozilla/readability": "^0.6.0",
|
|
10
|
+
"jsdom": "^27.0.1",
|
|
11
|
+
"turndown": "^7.2.2",
|
|
12
|
+
"turndown-plugin-gfm": "^1.0.2"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { Readability } from "@mozilla/readability";
|
|
4
|
+
import { JSDOM } from "jsdom";
|
|
5
|
+
import TurndownService from "turndown";
|
|
6
|
+
import { gfm } from "turndown-plugin-gfm";
|
|
7
|
+
|
|
8
|
+
const args = process.argv.slice(2);
|
|
9
|
+
|
|
10
|
+
const contentIndex = args.indexOf("--content");
|
|
11
|
+
const fetchContent = contentIndex !== -1;
|
|
12
|
+
if (fetchContent) args.splice(contentIndex, 1);
|
|
13
|
+
|
|
14
|
+
let numResults = 5;
|
|
15
|
+
const nIndex = args.indexOf("-n");
|
|
16
|
+
if (nIndex !== -1 && args[nIndex + 1]) {
|
|
17
|
+
numResults = parseInt(args[nIndex + 1], 10);
|
|
18
|
+
args.splice(nIndex, 2);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const query = args.join(" ");
|
|
22
|
+
|
|
23
|
+
if (!query) {
|
|
24
|
+
console.log("Usage: search.js [-n] [--content]");
|
|
25
|
+
console.log("\nOptions:");
|
|
26
|
+
console.log(" -n Number of results (default: 5)");
|
|
27
|
+
console.log(" --content Fetch readable content as markdown");
|
|
28
|
+
console.log("\nExamples:");
|
|
29
|
+
console.log(' search.js "javascript async await"');
|
|
30
|
+
console.log(' search.js "rust programming" -n 10');
|
|
31
|
+
console.log(' search.js "climate change" --content');
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async function fetchBraveResults(query, numResults) {
|
|
36
|
+
const url = `https://search.brave.com/search?q=${encodeURIComponent(query)}`;
|
|
37
|
+
|
|
38
|
+
const response = await fetch(url, {
|
|
39
|
+
headers: {
|
|
40
|
+
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36",
|
|
41
|
+
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
|
|
42
|
+
"Accept-Language": "en-US,en;q=0.9",
|
|
43
|
+
"sec-ch-ua": '"Chromium";v="142", "Google Chrome";v="142", "Not_A Brand";v="99"',
|
|
44
|
+
"sec-ch-ua-mobile": "?0",
|
|
45
|
+
"sec-ch-ua-platform": '"macOS"',
|
|
46
|
+
"sec-fetch-dest": "document",
|
|
47
|
+
"sec-fetch-mode": "navigate",
|
|
48
|
+
"sec-fetch-site": "none",
|
|
49
|
+
"sec-fetch-user": "?1",
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
if (!response.ok) {
|
|
54
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const html = await response.text();
|
|
58
|
+
const dom = new JSDOM(html);
|
|
59
|
+
const doc = dom.window.document;
|
|
60
|
+
|
|
61
|
+
const results = [];
|
|
62
|
+
|
|
63
|
+
// Find all search result snippets with data-type="web"
|
|
64
|
+
const snippets = doc.querySelectorAll('div.snippet[data-type="web"]');
|
|
65
|
+
|
|
66
|
+
for (const snippet of snippets) {
|
|
67
|
+
if (results.length >= numResults) break;
|
|
68
|
+
|
|
69
|
+
// Get the main link and title
|
|
70
|
+
const titleLink = snippet.querySelector('a.svelte-14r20fy');
|
|
71
|
+
if (!titleLink) continue;
|
|
72
|
+
|
|
73
|
+
const link = titleLink.getAttribute('href');
|
|
74
|
+
if (!link || link.includes('brave.com')) continue;
|
|
75
|
+
|
|
76
|
+
const titleEl = titleLink.querySelector('.title');
|
|
77
|
+
const title = titleEl?.textContent?.trim() || titleLink.textContent?.trim() || '';
|
|
78
|
+
|
|
79
|
+
// Get the snippet/description
|
|
80
|
+
const descEl = snippet.querySelector('.generic-snippet .content');
|
|
81
|
+
let snippetText = descEl?.textContent?.trim() || '';
|
|
82
|
+
// Remove date prefix if present
|
|
83
|
+
snippetText = snippetText.replace(/^[A-Z][a-z]+ \d+, \d{4} -\s*/, '');
|
|
84
|
+
|
|
85
|
+
if (title && link) {
|
|
86
|
+
results.push({ title, link, snippet: snippetText });
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return results;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function htmlToMarkdown(html) {
|
|
94
|
+
const turndown = new TurndownService({ headingStyle: "atx", codeBlockStyle: "fenced" });
|
|
95
|
+
turndown.use(gfm);
|
|
96
|
+
turndown.addRule("removeEmptyLinks", {
|
|
97
|
+
filter: (node) => node.nodeName === "A" && !node.textContent?.trim(),
|
|
98
|
+
replacement: () => "",
|
|
99
|
+
});
|
|
100
|
+
return turndown
|
|
101
|
+
.turndown(html)
|
|
102
|
+
.replace(/\[\\?\[\s*\\?\]\]\([^)]*\)/g, "")
|
|
103
|
+
.replace(/ +/g, " ")
|
|
104
|
+
.replace(/\s+,/g, ",")
|
|
105
|
+
.replace(/\s+\./g, ".")
|
|
106
|
+
.replace(/\n{3,}/g, "\n\n")
|
|
107
|
+
.trim();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
async function fetchPageContent(url) {
|
|
111
|
+
try {
|
|
112
|
+
const response = await fetch(url, {
|
|
113
|
+
headers: {
|
|
114
|
+
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36",
|
|
115
|
+
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
|
|
116
|
+
},
|
|
117
|
+
signal: AbortSignal.timeout(10000),
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
if (!response.ok) {
|
|
121
|
+
return `(HTTP ${response.status})`;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const html = await response.text();
|
|
125
|
+
const dom = new JSDOM(html, { url });
|
|
126
|
+
const reader = new Readability(dom.window.document);
|
|
127
|
+
const article = reader.parse();
|
|
128
|
+
|
|
129
|
+
if (article && article.content) {
|
|
130
|
+
return htmlToMarkdown(article.content).substring(0, 5000);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Fallback: try to get main content
|
|
134
|
+
const fallbackDoc = new JSDOM(html, { url });
|
|
135
|
+
const body = fallbackDoc.window.document;
|
|
136
|
+
body.querySelectorAll("script, style, noscript, nav, header, footer, aside").forEach(el => el.remove());
|
|
137
|
+
const main = body.querySelector("main, article, [role='main'], .content, #content") || body.body;
|
|
138
|
+
const text = main?.textContent || "";
|
|
139
|
+
|
|
140
|
+
if (text.trim().length > 100) {
|
|
141
|
+
return text.trim().substring(0, 5000);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return "(Could not extract content)";
|
|
145
|
+
} catch (e) {
|
|
146
|
+
return `(Error: ${e.message})`;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Main
|
|
151
|
+
try {
|
|
152
|
+
const results = await fetchBraveResults(query, numResults);
|
|
153
|
+
|
|
154
|
+
if (results.length === 0) {
|
|
155
|
+
console.error("No results found.");
|
|
156
|
+
process.exit(0);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (fetchContent) {
|
|
160
|
+
for (const result of results) {
|
|
161
|
+
result.content = await fetchPageContent(result.link);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
for (let i = 0; i < results.length; i++) {
|
|
166
|
+
const r = results[i];
|
|
167
|
+
console.log(`--- Result ${i + 1} ---`);
|
|
168
|
+
console.log(`Title: ${r.title}`);
|
|
169
|
+
console.log(`Link: ${r.link}`);
|
|
170
|
+
console.log(`Snippet: ${r.snippet}`);
|
|
171
|
+
if (r.content) {
|
|
172
|
+
console.log(`Content:\n${r.content}`);
|
|
173
|
+
}
|
|
174
|
+
console.log("");
|
|
175
|
+
}
|
|
176
|
+
} catch (e) {
|
|
177
|
+
console.error(`Error: ${e.message}`);
|
|
178
|
+
process.exit(1);
|
|
179
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: caldav-calendar
|
|
3
|
+
description: Sync and query CalDAV calendars (iCloud, Google, Fastmail, Nextcloud, etc.) using vdirsyncer + khal. Works on Linux.
|
|
4
|
+
metadata: {"lemonade":{"emoji":"📅","os":["linux"],"requires":{"bins":["vdirsyncer","khal"]},"install":[{"id":"apt","kind":"apt","packages":["vdirsyncer","khal"],"bins":["vdirsyncer","khal"],"label":"Install vdirsyncer + khal via apt"}]}}
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# CalDAV Calendar (vdirsyncer + khal)
|
|
8
|
+
|
|
9
|
+
**vdirsyncer** syncs CalDAV calendars to local `.ics` files. **khal** reads and writes them.
|
|
10
|
+
|
|
11
|
+
## Sync First
|
|
12
|
+
|
|
13
|
+
Always sync before querying or after making changes:
|
|
14
|
+
```bash
|
|
15
|
+
vdirsyncer sync
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## View Events
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
khal list # Today
|
|
22
|
+
khal list today 7d # Next 7 days
|
|
23
|
+
khal list tomorrow # Tomorrow
|
|
24
|
+
khal list 2026-01-15 2026-01-20 # Date range
|
|
25
|
+
khal list -a Work today # Specific calendar
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Search
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
khal search "meeting"
|
|
32
|
+
khal search "dentist" --format "{start-date} {title}"
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Create Events
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
khal new 2026-01-15 10:00 11:00 "Meeting title"
|
|
39
|
+
khal new 2026-01-15 "All day event"
|
|
40
|
+
khal new tomorrow 14:00 15:30 "Call" -a Work
|
|
41
|
+
khal new 2026-01-15 10:00 11:00 "With notes" :: Description goes here
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
After creating, sync to push changes:
|
|
45
|
+
```bash
|
|
46
|
+
vdirsyncer sync
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Initial Setup
|
|
50
|
+
|
|
51
|
+
### 1. Configure vdirsyncer (`~/.config/vdirsyncer/config`)
|
|
52
|
+
|
|
53
|
+
Example for iCloud:
|
|
54
|
+
```ini
|
|
55
|
+
[general]
|
|
56
|
+
status_path = "~/.local/share/vdirsyncer/status/"
|
|
57
|
+
|
|
58
|
+
[pair icloud_calendar]
|
|
59
|
+
a = "icloud_remote"
|
|
60
|
+
b = "icloud_local"
|
|
61
|
+
collections = ["from a", "from b"]
|
|
62
|
+
conflict_resolution = "a wins"
|
|
63
|
+
|
|
64
|
+
[storage icloud_remote]
|
|
65
|
+
type = "caldav"
|
|
66
|
+
url = "https://caldav.icloud.com/"
|
|
67
|
+
username = "you@icloud.com"
|
|
68
|
+
password.fetch = ["command", "cat", "~/.config/vdirsyncer/icloud_password"]
|
|
69
|
+
|
|
70
|
+
[storage icloud_local]
|
|
71
|
+
type = "filesystem"
|
|
72
|
+
path = "~/.local/share/vdirsyncer/calendars/"
|
|
73
|
+
fileext = ".ics"
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Provider URLs:
|
|
77
|
+
- iCloud: `https://caldav.icloud.com/`
|
|
78
|
+
- Google: Use `google_calendar` storage type
|
|
79
|
+
- Fastmail: `https://caldav.fastmail.com/dav/calendars/user/EMAIL/`
|
|
80
|
+
- Nextcloud: `https://YOUR.CLOUD/remote.php/dav/calendars/USERNAME/`
|
|
81
|
+
|
|
82
|
+
### 2. Configure khal (`~/.config/khal/config`)
|
|
83
|
+
|
|
84
|
+
```ini
|
|
85
|
+
[calendars]
|
|
86
|
+
[[my_calendars]]
|
|
87
|
+
path = ~/.local/share/vdirsyncer/calendars/*
|
|
88
|
+
type = discover
|
|
89
|
+
|
|
90
|
+
[default]
|
|
91
|
+
default_calendar = Home
|
|
92
|
+
highlight_event_days = True
|
|
93
|
+
|
|
94
|
+
[locale]
|
|
95
|
+
timeformat = %H:%M
|
|
96
|
+
dateformat = %Y-%m-%d
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### 3. Discover and sync
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
vdirsyncer discover
|
|
103
|
+
vdirsyncer sync
|
|
104
|
+
```
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: frontend-design
|
|
3
|
+
description: Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
This skill guides creation of distinctive, production-grade frontend interfaces that avoid generic "AI slop" aesthetics. Implement real working code with exceptional attention to aesthetic details and creative choices.
|
|
7
|
+
|
|
8
|
+
The user provides frontend requirements: a component, page, application, or interface to build. They may include context about the purpose, audience, or technical constraints.
|
|
9
|
+
|
|
10
|
+
## Design Thinking
|
|
11
|
+
|
|
12
|
+
Before coding, understand the context and commit to a BOLD aesthetic direction:
|
|
13
|
+
- **Purpose**: What problem does this interface solve? Who uses it?
|
|
14
|
+
- **Tone**: Pick an extreme: brutally minimal, maximalist chaos, retro-futuristic, organic/natural, luxury/refined, playful/toy-like, editorial/magazine, brutalist/raw, art deco/geometric, soft/pastel, industrial/utilitarian, etc.
|
|
15
|
+
- **Constraints**: Technical requirements (framework, performance, accessibility).
|
|
16
|
+
- **Differentiation**: What makes this UNFORGETTABLE? What's the one thing someone will remember?
|
|
17
|
+
|
|
18
|
+
**CRITICAL**: Choose a clear conceptual direction and execute it with precision. Bold maximalism and refined minimalism both work - the key is intentionality, not intensity.
|
|
19
|
+
|
|
20
|
+
Then implement working code (HTML/CSS/JS, React, Vue, etc.) that is:
|
|
21
|
+
- Production-grade and functional
|
|
22
|
+
- Visually striking and memorable
|
|
23
|
+
- Cohesive with a clear aesthetic point-of-view
|
|
24
|
+
- Meticulously refined in every detail
|
|
25
|
+
|
|
26
|
+
## Frontend Aesthetics Guidelines
|
|
27
|
+
|
|
28
|
+
Focus on:
|
|
29
|
+
- **Typography**: Choose fonts that are beautiful, unique, and interesting. Avoid generic fonts like Arial and Inter; opt instead for distinctive choices that elevate the frontend's aesthetics; unexpected, characterful font choices. Pair a distinctive display font with a refined body font.
|
|
30
|
+
- **Color & Theme**: Commit to a cohesive aesthetic. Use CSS variables for consistency. Dominant colors with sharp accents outperform timid, evenly-distributed palettes.
|
|
31
|
+
- **Motion**: Use animations for effects and micro-interactions. Prioritize CSS-only solutions for HTML. Focus on high-impact moments: one well-orchestrated page load with staggered reveals creates more delight than scattered micro-interactions.
|
|
32
|
+
- **Spatial Composition**: Unexpected layouts. Asymmetry. Overlap. Diagonal flow. Grid-breaking elements. Generous negative space OR controlled density.
|
|
33
|
+
- **Backgrounds & Visual Details**: Create atmosphere and depth rather than defaulting to solid colors. Add contextual effects and textures that match the overall aesthetic.
|
|
34
|
+
|
|
35
|
+
NEVER use generic AI-generated aesthetics like overused font families (Inter, Roboto, Arial, system fonts), cliched color schemes (particularly purple gradients on white backgrounds), predictable layouts, and cookie-cutter design that lacks context-specific character.
|
|
36
|
+
|
|
37
|
+
Interpret creatively and make unexpected choices that feel genuinely designed for the context. No design should be the same. Vary between light and dark themes, different fonts, different aesthetics.
|
|
38
|
+
|
|
39
|
+
**IMPORTANT**: Match implementation complexity to the aesthetic vision. Maximalist designs need elaborate code with extensive animations and effects. Minimalist or refined designs need restraint, precision, and careful attention to spacing, typography, and subtle details.
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: self-improvement
|
|
3
|
+
description: "Captures learnings, errors, and corrections to enable continuous improvement. Use when: (1) A command or operation fails unexpectedly, (2) User corrects the agent, (3) User requests a capability that doesn't exist, (4) An external API or tool fails, (5) Agent realizes its knowledge is outdated or incorrect, (6) A better approach is discovered for a recurring task."
|
|
4
|
+
metadata: {"lemonade":{"emoji":"🧠"}}
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Self-Improvement Skill
|
|
8
|
+
|
|
9
|
+
Log learnings and errors to markdown files for continuous improvement. Important learnings get promoted to project memory.
|
|
10
|
+
|
|
11
|
+
## Quick Reference
|
|
12
|
+
|
|
13
|
+
| Situation | Action |
|
|
14
|
+
|-----------|--------|
|
|
15
|
+
| Command/operation fails | Log to `.learnings/ERRORS.md` |
|
|
16
|
+
| User corrects you | Log to `.learnings/LEARNINGS.md` with category `correction` |
|
|
17
|
+
| User wants missing feature | Log to `.learnings/FEATURE_REQUESTS.md` |
|
|
18
|
+
| API/external tool fails | Log to `.learnings/ERRORS.md` with integration details |
|
|
19
|
+
| Knowledge was outdated | Log to `.learnings/LEARNINGS.md` with category `knowledge_gap` |
|
|
20
|
+
| Found better approach | Log to `.learnings/LEARNINGS.md` with category `best_practice` |
|
|
21
|
+
| Broadly applicable learning | Promote to project memory files |
|
|
22
|
+
|
|
23
|
+
## Setup
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
mkdir -p ~/.lemonade/workspace/.learnings
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Logging Format
|
|
30
|
+
|
|
31
|
+
### Learning Entry
|
|
32
|
+
|
|
33
|
+
Append to `.learnings/LEARNINGS.md`:
|
|
34
|
+
|
|
35
|
+
```markdown
|
|
36
|
+
## [LRN-YYYYMMDD-XXX] category
|
|
37
|
+
|
|
38
|
+
**Logged**: ISO-8601 timestamp
|
|
39
|
+
**Priority**: low | medium | high | critical
|
|
40
|
+
**Status**: pending
|
|
41
|
+
**Area**: frontend | backend | infra | tests | docs | config
|
|
42
|
+
|
|
43
|
+
### Summary
|
|
44
|
+
One-line description of what was learned
|
|
45
|
+
|
|
46
|
+
### Details
|
|
47
|
+
Full context: what happened, what was wrong, what's correct
|
|
48
|
+
|
|
49
|
+
### Suggested Action
|
|
50
|
+
Specific fix or improvement to make
|
|
51
|
+
|
|
52
|
+
### Metadata
|
|
53
|
+
- Source: conversation | error | user_feedback
|
|
54
|
+
- Related Files: path/to/file.ext
|
|
55
|
+
- Tags: tag1, tag2
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Error Entry
|
|
59
|
+
|
|
60
|
+
Append to `.learnings/ERRORS.md`:
|
|
61
|
+
|
|
62
|
+
```markdown
|
|
63
|
+
## [ERR-YYYYMMDD-XXX] skill_or_command_name
|
|
64
|
+
|
|
65
|
+
**Logged**: ISO-8601 timestamp
|
|
66
|
+
**Priority**: high
|
|
67
|
+
**Status**: pending
|
|
68
|
+
|
|
69
|
+
### Summary
|
|
70
|
+
Brief description of what failed
|
|
71
|
+
|
|
72
|
+
### Error
|
|
73
|
+
Actual error message or output
|
|
74
|
+
|
|
75
|
+
### Context
|
|
76
|
+
- Command/operation attempted
|
|
77
|
+
- Input or parameters used
|
|
78
|
+
|
|
79
|
+
### Suggested Fix
|
|
80
|
+
If identifiable, what might resolve this
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Feature Request Entry
|
|
84
|
+
|
|
85
|
+
Append to `.learnings/FEATURE_REQUESTS.md`:
|
|
86
|
+
|
|
87
|
+
```markdown
|
|
88
|
+
## [FEAT-YYYYMMDD-XXX] capability_name
|
|
89
|
+
|
|
90
|
+
**Logged**: ISO-8601 timestamp
|
|
91
|
+
**Priority**: medium
|
|
92
|
+
**Status**: pending
|
|
93
|
+
|
|
94
|
+
### Requested Capability
|
|
95
|
+
What the user wanted to do
|
|
96
|
+
|
|
97
|
+
### User Context
|
|
98
|
+
Why they needed it
|
|
99
|
+
|
|
100
|
+
### Suggested Implementation
|
|
101
|
+
How this could be built
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Detection Triggers
|
|
105
|
+
|
|
106
|
+
Automatically log when you notice:
|
|
107
|
+
|
|
108
|
+
**Corrections**: "No, that's not right...", "Actually, it should be...", "You're wrong about..."
|
|
109
|
+
|
|
110
|
+
**Feature Requests**: "Can you also...", "I wish you could...", "Is there a way to..."
|
|
111
|
+
|
|
112
|
+
**Knowledge Gaps**: User provides information you didn't know, documentation is outdated
|
|
113
|
+
|
|
114
|
+
**Errors**: Command returns non-zero exit code, exception or stack trace
|
|
115
|
+
|
|
116
|
+
## Resolving Entries
|
|
117
|
+
|
|
118
|
+
When an issue is fixed, update `**Status**: pending` to `**Status**: resolved` and add a resolution block.
|
|
119
|
+
|
|
120
|
+
## Best Practices
|
|
121
|
+
|
|
122
|
+
1. Log immediately - context is freshest right after the issue
|
|
123
|
+
2. Be specific - future agents need to understand quickly
|
|
124
|
+
3. Include reproduction steps - especially for errors
|
|
125
|
+
4. Link related files - makes fixes easier
|
|
126
|
+
5. Suggest concrete fixes - not just "investigate"
|
|
127
|
+
6. Promote aggressively - if in doubt, add to project memory
|
|
128
|
+
```
|