@sulala/agent-os 0.1.5 → 0.1.6

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.
Files changed (56) hide show
  1. package/data/agents/briefing_agent.json +12 -0
  2. package/data/agents/dev_agent.json +10 -0
  3. package/data/agents/manager_agent.json +11 -0
  4. package/data/agents/media_agent.json +10 -0
  5. package/data/agents/personal_agent.json +11 -0
  6. package/data/agents/research_agent.json +10 -0
  7. package/data/agents/social_media_agent.json +10 -0
  8. package/data/agents/writer_agent.json +10 -0
  9. package/data/skills/bluesky/SKILL.md +63 -0
  10. package/data/skills/bluesky/config.schema.json +17 -0
  11. package/data/skills/bluesky/scripts/post.sh +48 -0
  12. package/data/skills/bluesky/scripts/timeline.sh +37 -0
  13. package/data/skills/date/SKILL.md +53 -0
  14. package/data/skills/fetch/SKILL.md +42 -0
  15. package/data/skills/file-search/SKILL.md +122 -0
  16. package/data/skills/file-stats/SKILL.md +68 -0
  17. package/data/skills/git/SKILL.md +60 -0
  18. package/data/skills/gmail/SKILL.md +55 -0
  19. package/data/skills/gmail/references/send-email.md +54 -0
  20. package/data/skills/gmail/scripts/send_email.py +94 -0
  21. package/data/skills/hash/SKILL.md +56 -0
  22. package/data/skills/jq/SKILL.md +66 -0
  23. package/data/skills/markdown-to-html/SKILL.md +47 -0
  24. package/data/skills/memory/SKILL.md +64 -0
  25. package/data/skills/qr-code/SKILL.md +65 -0
  26. package/data/skills/rss/SKILL.md +40 -0
  27. package/data/skills/sulala-portal/SKILL.md +92 -0
  28. package/data/skills/translate/SKILL.md +52 -0
  29. package/data/skills/weather/SKILL.md +59 -0
  30. package/data/skills/web-search/SKILL.md +55 -0
  31. package/data/skills/web-search/config.schema.json +12 -0
  32. package/data/skills/web-search/scripts/search.sh +21 -0
  33. package/data/skills/webhook/SKILL.md +101 -0
  34. package/data/skills/webhook/config.schema.json +11 -0
  35. package/data/skills/webhook/scripts/post.sh +13 -0
  36. package/data/skills/youtube/SKILL.md +91 -0
  37. package/data/skills/youtube/config.schema.json +11 -0
  38. package/data/skills/youtube/package.json +8 -0
  39. package/data/skills/youtube/references/youtube-upload.md +65 -0
  40. package/data/skills/youtube/requirements.txt +3 -0
  41. package/data/skills/youtube/scripts/youtube_upload.js +200 -0
  42. package/data/skills/youtube/scripts/youtube_upload.py +125 -0
  43. package/data/templates/BOOT.md +11 -0
  44. package/data/templates/BOOTSTRAP.md +62 -0
  45. package/data/templates/HEARTBEAT.md +12 -0
  46. package/data/templates/IDENTITY.dev.md +62 -0
  47. package/data/templates/IDENTITY.md +60 -0
  48. package/data/templates/SYSTEM.dev.md +82 -0
  49. package/data/templates/SYSTEM.md +65 -0
  50. package/data/templates/TOOLS.dev.md +24 -0
  51. package/data/templates/TOOLS.md +47 -0
  52. package/data/templates/USER.dev.md +18 -0
  53. package/data/templates/USER.md +23 -0
  54. package/dist/cli.js +22 -13
  55. package/dist/index.js +14 -5
  56. package/package.json +3 -2
@@ -0,0 +1,12 @@
1
+ {
2
+ "id": "briefing_agent",
3
+ "name": "Daily Briefing",
4
+ "description": "Morning-style brief: weather and RSS feeds. Use for 'what's the weather' and 'what's new' from configured feeds. Optionally schedule (e.g. 8:00) for a daily brief.",
5
+ "model": "gpt-4o-mini",
6
+ "skills": ["memory", "weather", "rss"],
7
+ "limits": {
8
+ "max_turns": 15
9
+ },
10
+ "schedule": "0 8 * * *",
11
+ "schedule_input": "Give me a short morning brief: weather for my location and top items from my RSS feeds."
12
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "id": "dev_agent",
3
+ "name": "Dev Assistant",
4
+ "description": "Git status, search the codebase, parse JSON (jq), and fetch APIs. Use when the user asks about git, finding code, or working with JSON/APIs. Operates in the agent workspace.",
5
+ "model": "gpt-4o-mini",
6
+ "skills": ["memory", "git", "file-search", "jq", "fetch"],
7
+ "limits": {
8
+ "max_turns": 15
9
+ }
10
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "id": "manager_agent",
3
+ "name": "Manager Assistant",
4
+ "description": "Coordinates other agents. You don't have social media, email, or search skills yourself—when the user asks to post to Bluesky/social, send an email, search the web, or do something another agent can do, use the run_agent tool to delegate to the right agent (social_media_agent, writer_agent, research_agent, etc.) and then summarize the result for the user.",
5
+ "model": "gpt-4o-mini",
6
+ "skills": ["memory"],
7
+ "tools": ["run_agent"],
8
+ "limits": {
9
+ "max_turns": 15
10
+ }
11
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "id": "media_agent",
3
+ "name": "Media Assistant",
4
+ "description": "Upload to YouTube, generate QR codes, and send webhooks (e.g. Slack, Discord). Configure YouTube credentials and webhook URLs in the respective skills.",
5
+ "model": "gpt-4o-mini",
6
+ "skills": ["memory", "youtube", "qr-code", "webhook"],
7
+ "limits": {
8
+ "max_turns": 15
9
+ }
10
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "id": "personal_agent",
3
+ "name": "Personal Assistant",
4
+ "description": "Personal assistant with long-term memory and tools. Use the memory skill to store explicit user facts (e.g. 'remember that I live in X') and to recall them when the user asks what you remember, where they live, or what they like. Can check weather and search the web.",
5
+ "personality": "Friendly, supportive, and calm. Respond with empathy and a little warmth. When the user shares something personal or asks for help, be encouraging.",
6
+ "model": "gpt-4o-mini",
7
+ "skills": ["memory", "weather", "web-search"],
8
+ "limits": {
9
+ "max_turns": 20
10
+ }
11
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "id": "research_agent",
3
+ "name": "Research Assistant",
4
+ "description": "Search the web, fetch and summarize URLs, and follow RSS feeds. Use when the user asks to search for something, read a page, or get updates from a feed. Configure web-search API key in the skill if required.",
5
+ "model": "gpt-4o-mini",
6
+ "skills": ["memory", "web-search", "fetch", "rss"],
7
+ "limits": {
8
+ "max_turns": 15
9
+ }
10
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "id": "social_media_agent",
3
+ "name": "Social Media Assistant",
4
+ "description": "Post to social networks (e.g. Bluesky), read your timeline, and reply to posts. Configure credentials in the skill (Agents → Edit → Skills, or Settings). Currently supports Bluesky.",
5
+ "model": "gpt-4o-mini",
6
+ "skills": ["memory", "bluesky"],
7
+ "limits": {
8
+ "max_turns": 15
9
+ }
10
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "id": "writer_agent",
3
+ "name": "Writer Assistant",
4
+ "description": "Draft and send email (Gmail) and translate text. Use when the user wants to send an email or translate content. Gmail requires connection via Portal or skill config.",
5
+ "model": "gpt-4o-mini",
6
+ "skills": ["memory", "gmail", "translate"],
7
+ "limits": {
8
+ "max_turns": 15
9
+ }
10
+ }
@@ -0,0 +1,63 @@
1
+ ---
2
+ name: bluesky
3
+ description: Post to Bluesky and read your home timeline (AT Protocol). Use when the user says "post this to Bluesky", "what's on my Bluesky feed", "reply to this post", "post to Bluesky", "my Bluesky timeline".
4
+ credentials:
5
+ - BLUESKY_HANDLE
6
+ - BLUESKY_APP_PASSWORD
7
+ metadata:
8
+ clawdbot:
9
+ emoji: "🦋"
10
+ requires:
11
+ bins:
12
+ - curl
13
+ - jq
14
+ ---
15
+
16
+ # Bluesky
17
+
18
+ Post and read your Bluesky feed via the AT Protocol. Use the **exec** tool with **skill_id: "bluesky"** so `BLUESKY_HANDLE` and `BLUESKY_APP_PASSWORD` are injected from skill config.
19
+
20
+ ## Prerequisites
21
+
22
+ 1. Add the **bluesky** skill to the agent.
23
+ 2. Set **Bluesky handle** and **Bluesky app password** in Skills → bluesky → Setup (see **Setup** below).
24
+ 3. **jq** must be installed (`brew install jq` or `apt install jq`).
25
+
26
+ ## Setup
27
+
28
+ 1. In Bluesky: **Settings** (gear) → **App passwords** → **Add App Password**. Name it (e.g. "Agent OS"), copy the password once (it won’t be shown again).
29
+ 2. Your handle is your Bluesky username (e.g. `yourname.bsky.social`).
30
+ 3. In the dashboard: **Skills** → **bluesky** → ⋮ → **Setup** → set **Bluesky handle** and **Bluesky app password** → Save.
31
+
32
+ Never use your main account password; use only an app password.
33
+
34
+ ### If you get "Invalid identifier or password"
35
+
36
+ - **Handle:** Use your full handle exactly as shown in Bluesky (e.g. `yourname.bsky.social`). Do not include `@`. The script strips a leading `@` and trims spaces automatically.
37
+ - **App password:** You must create one in Bluesky **Settings → App passwords → Add App Password**. Copy it when shown (it’s not shown again). If you lost it, create a new app password and update the skill config.
38
+ - **No account password:** The app password is a separate, long token (e.g. `xxxx-xxxx-xxxx-xxxx`); do not use your normal Bluesky login password.
39
+
40
+ ## Post a new post
41
+
42
+ - **skill_id:** `bluesky`
43
+ - **command:** `./scripts/post.sh "Your post text here"`
44
+
45
+ Post text is the first argument. Max 300 graphemes (Bluesky limit). The script creates a session, then creates the record; the response is the created post URI.
46
+
47
+ ## Get your home timeline
48
+
49
+ - **skill_id:** `bluesky`
50
+ - **command:** `./scripts/timeline.sh`
51
+ - Optional limit: `./scripts/timeline.sh 30` (default 20)
52
+
53
+ Returns JSON: `feed[]` with `post` (author, record.text, etc.). Summarize or list the most recent posts for the user.
54
+
55
+ ## Reply to a post (future)
56
+
57
+ Replies require a `reply` object (parent + root) in the record. The current script only supports top-level posts. For replies, extend the record or add a `reply.sh` script that accepts parent URI and text.
58
+
59
+ ## Tips
60
+
61
+ - Quote the post text in the command so spaces and punctuation are preserved: `./scripts/post.sh "Hello from the agent!"`
62
+ - Timeline entries have `post.author.displayName`, `post.record.text`, `post.uri`. Use these to summarize the feed.
63
+ - Optional env **BLUESKY_PDS** overrides the PDS URL (default `https://bsky.social`); only set if you use a custom PDS.
@@ -0,0 +1,17 @@
1
+ {
2
+ "type": "object",
3
+ "properties": {
4
+ "BLUESKY_HANDLE": {
5
+ "type": "string",
6
+ "title": "Bluesky handle",
7
+ "description": "Your Bluesky handle (e.g. yourname.bsky.social). Used with the app password to create a session."
8
+ },
9
+ "BLUESKY_APP_PASSWORD": {
10
+ "type": "string",
11
+ "format": "password",
12
+ "title": "Bluesky app password",
13
+ "description": "App password from Bluesky Settings → App passwords. Do not use your main account password."
14
+ }
15
+ },
16
+ "required": ["BLUESKY_HANDLE", "BLUESKY_APP_PASSWORD"]
17
+ }
@@ -0,0 +1,48 @@
1
+ #!/bin/sh
2
+ # Post to Bluesky via AT Protocol. BLUESKY_HANDLE and BLUESKY_APP_PASSWORD from skill config.
3
+ # Usage: post.sh "your post text here"
4
+ set -e
5
+ if [ -z "$BLUESKY_HANDLE" ] || [ -z "$BLUESKY_APP_PASSWORD" ]; then
6
+ echo "BLUESKY_HANDLE and BLUESKY_APP_PASSWORD must be set. Configure in Skills → bluesky → Setup." >&2
7
+ exit 1
8
+ fi
9
+ # Trim and normalize: handle without leading @, no leading/trailing whitespace
10
+ BLUESKY_HANDLE=$(echo "$BLUESKY_HANDLE" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//;s/^@//')
11
+ BLUESKY_APP_PASSWORD=$(echo "$BLUESKY_APP_PASSWORD" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
12
+ if [ -z "$BLUESKY_HANDLE" ] || [ -z "$BLUESKY_APP_PASSWORD" ]; then
13
+ echo "BLUESKY_HANDLE and BLUESKY_APP_PASSWORD must be non-empty after trimming." >&2
14
+ exit 1
15
+ fi
16
+ if [ -z "$1" ]; then
17
+ echo "Usage: post.sh \"post text\"" >&2
18
+ exit 1
19
+ fi
20
+ if ! command -v jq >/dev/null 2>&1; then
21
+ echo "jq is required for the Bluesky skill." >&2
22
+ exit 1
23
+ fi
24
+ PDS="${BLUESKY_PDS:-https://bsky.social}"
25
+ # Create session (use jq to build JSON so special chars in password are safe)
26
+ SESSION_BODY=$(jq -n --arg id "$BLUESKY_HANDLE" --arg pw "$BLUESKY_APP_PASSWORD" '{identifier:$id,password:$pw}')
27
+ SESSION=$(curl -sS -X POST "$PDS/xrpc/com.atproto.server.createSession" \
28
+ -H "Content-Type: application/json" \
29
+ -d "$SESSION_BODY")
30
+ if ! echo "$SESSION" | jq -e '.accessJwt' >/dev/null 2>&1; then
31
+ echo "Session failed: $SESSION" >&2
32
+ echo "Check: (1) Handle is your full handle, e.g. yourname.bsky.social (no @). (2) Use an App password from Bluesky Settings → App passwords, not your account password." >&2
33
+ exit 1
34
+ fi
35
+ ACCESS_JWT=$(echo "$SESSION" | jq -r '.accessJwt')
36
+ DID=$(echo "$SESSION" | jq -r '.did')
37
+ # createdAt in ISO 8601
38
+ CREATED_AT=$(date -u +%Y-%m-%dT%H:%M:%S.000Z)
39
+ # Escape post text for JSON
40
+ TEXT=$(printf '%s' "$1" | jq -Rs .)
41
+ RECORD=$(jq -n --arg text "$1" --arg createdAt "$CREATED_AT" \
42
+ '{ ("$type"): "app.bsky.feed.post", text: $text, createdAt: $createdAt }')
43
+ BODY=$(jq -n --arg repo "$DID" --argjson record "$RECORD" \
44
+ '{ repo: $repo, collection: "app.bsky.feed.post", record: $record }')
45
+ curl -sS -X POST "$PDS/xrpc/com.atproto.repo.createRecord" \
46
+ -H "Authorization: Bearer $ACCESS_JWT" \
47
+ -H "Content-Type: application/json" \
48
+ -d "$BODY"
@@ -0,0 +1,37 @@
1
+ #!/bin/sh
2
+ # Get Bluesky home timeline. BLUESKY_HANDLE and BLUESKY_APP_PASSWORD from skill config (injected as env by exec).
3
+ # Usage: timeline.sh [limit]
4
+ # Optional: limit (default 20) - number of posts to return.
5
+ set -e
6
+ if [ -z "$BLUESKY_HANDLE" ] || [ -z "$BLUESKY_APP_PASSWORD" ]; then
7
+ echo "BLUESKY_HANDLE and BLUESKY_APP_PASSWORD must be set. Configure in Skills → bluesky → Setup." >&2
8
+ exit 1
9
+ fi
10
+ # Trim and normalize: handle without leading @
11
+ BLUESKY_HANDLE=$(echo "$BLUESKY_HANDLE" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//;s/^@//')
12
+ BLUESKY_APP_PASSWORD=$(echo "$BLUESKY_APP_PASSWORD" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
13
+ if [ -z "$BLUESKY_HANDLE" ] || [ -z "$BLUESKY_APP_PASSWORD" ]; then
14
+ echo "BLUESKY_HANDLE and BLUESKY_APP_PASSWORD must be non-empty after trimming." >&2
15
+ exit 1
16
+ fi
17
+ if ! command -v jq >/dev/null 2>&1; then
18
+ echo "jq is required. Install with: brew install jq (macOS) or apt install jq (Linux)." >&2
19
+ exit 1
20
+ fi
21
+
22
+ LIMIT="${1:-20}"
23
+ PDS="${BLUESKY_PDS:-https://bsky.social}"
24
+ SESSION_BODY=$(jq -n --arg id "$BLUESKY_HANDLE" --arg pw "$BLUESKY_APP_PASSWORD" '{identifier:$id,password:$pw}')
25
+ SESSION=$(curl -sS -X POST "$PDS/xrpc/com.atproto.server.createSession" \
26
+ -H "Content-Type: application/json" \
27
+ -d "$SESSION_BODY")
28
+ if ! echo "$SESSION" | jq -e '.accessJwt' >/dev/null 2>&1; then
29
+ echo "Session failed: $SESSION" >&2
30
+ echo "Check: (1) Handle is your full handle, e.g. yourname.bsky.social (no @). (2) Use an App password from Bluesky Settings → App passwords, not your account password." >&2
31
+ exit 1
32
+ fi
33
+ ACCESS_JWT=$(echo "$SESSION" | jq -r '.accessJwt')
34
+
35
+ curl -sS -G "$PDS/xrpc/app.bsky.feed.getTimeline" \
36
+ --data-urlencode "limit=$LIMIT" \
37
+ -H "Authorization: Bearer $ACCESS_JWT"
@@ -0,0 +1,53 @@
1
+ ---
2
+ name: date
3
+ description: Get current date and time (optionally in a timezone). Use when the user asks "what time is it", "current date", "time in Tokyo", "what's the date today".
4
+ metadata:
5
+ clawdbot:
6
+ emoji: "🕐"
7
+ requires:
8
+ bins:
9
+ - date
10
+ ---
11
+
12
+ # Date and time
13
+
14
+ Use the **exec** tool to run `date` or fetch time from an API. No script required.
15
+
16
+ ## Local date and time
17
+
18
+ ```bash
19
+ date
20
+ # e.g. Sat Mar 15 10:30:00 GMT 2025
21
+ ```
22
+
23
+ Custom format (ISO-like):
24
+
25
+ ```bash
26
+ date +"%Y-%m-%d %H:%M:%S %Z"
27
+ ```
28
+
29
+ ## Time in another timezone
30
+
31
+ ```bash
32
+ TZ=Europe/Paris date
33
+ TZ=America/New_York date
34
+ TZ=Asia/Tokyo date +"%H:%M %Z"
35
+ ```
36
+
37
+ Common TZ values: `Europe/London`, `Europe/Paris`, `America/Los_Angeles`, `America/New_York`, `Asia/Tokyo`, `UTC`.
38
+
39
+ ## Unix timestamp
40
+
41
+ ```bash
42
+ date +%s
43
+ ```
44
+
45
+ ## World time (fallback via curl)
46
+
47
+ If the user asks for "time in City" and you need a source:
48
+
49
+ ```bash
50
+ curl -s "https://worldtimeapi.org/api/timezone/Europe/Paris" | head -c 500
51
+ ```
52
+
53
+ Returns JSON with `datetime`, `timezone`, etc. Other zones: `America/New_York`, `Asia/Tokyo`. Docs: https://worldtimeapi.org/
@@ -0,0 +1,42 @@
1
+ ---
2
+ name: fetch
3
+ description: Fetch content from a URL (GET). Use when the user says "fetch this URL", "read that page", "get content from …", or "what's at this link".
4
+ metadata:
5
+ clawdbot:
6
+ emoji: "🔗"
7
+ requires:
8
+ bins:
9
+ - curl
10
+ ---
11
+
12
+ # Fetch URL
13
+
14
+ Fetch the body of a URL via **curl**. Use the **exec** tool with the commands below. Only use **http** or **https** URLs.
15
+
16
+ ## GET body (plain)
17
+
18
+ ```bash
19
+ curl -sL "https://example.com/page"
20
+ ```
21
+
22
+ - `-s` silent (no progress)
23
+ - `-L` follow redirects
24
+
25
+ ## With a user-agent (some sites need it)
26
+
27
+ ```bash
28
+ curl -sL -A "Mozilla/5.0 (compatible; Agent/1.0)" "https://example.com/page"
29
+ ```
30
+
31
+ ## Limit size (avoid huge responses)
32
+
33
+ ```bash
34
+ curl -sL --max-size 1048576 "https://example.com/page"
35
+ # 1 MiB max
36
+ ```
37
+
38
+ ## Tips
39
+
40
+ - URL-encode the URL or quote it in the shell.
41
+ - For JSON APIs, pipe to `head -c 50000` or process with `jq` if needed.
42
+ - Do not POST or send secrets in the URL; use this for read-only GET.
@@ -0,0 +1,122 @@
1
+ ---
2
+ name: file-search
3
+ description: Search for files and text in the workspace or the user's computer (grep, find). Use when the user asks "find files containing X", "list all .md files", "search my computer", "find file named Y on my machine", "search in my Downloads".
4
+ metadata:
5
+ clawdbot:
6
+ emoji: "🔍"
7
+ requires:
8
+ bins:
9
+ - grep
10
+ - find
11
+ ---
12
+
13
+ # File search (workspace)
14
+
15
+ Use **grep** and **find** via the **exec** tool to search inside the **workspace**. Commands run in the agent workspace; restrict paths to the workspace (no `../` escape).
16
+
17
+ ## Find files by name or pattern
18
+
19
+ ```bash
20
+ find . -name "*.md"
21
+ find . -name "*.json" -type f
22
+ find . -iname "*config*"
23
+ ```
24
+
25
+ Limit depth (e.g. current dir + one level):
26
+
27
+ ```bash
28
+ find . -maxdepth 2 -name "*.ts"
29
+ ```
30
+
31
+ ## Search file contents (grep)
32
+
33
+ ```bash
34
+ grep -r "search term" .
35
+ grep -rn "function foo" .
36
+ # -n = line numbers
37
+ ```
38
+
39
+ Case-insensitive:
40
+
41
+ ```bash
42
+ grep -ri "TODO" .
43
+ ```
44
+
45
+ Only list matching files (no line content):
46
+
47
+ ```bash
48
+ grep -rl "import React" .
49
+ ```
50
+
51
+ ## Combine find + grep
52
+
53
+ ```bash
54
+ find . -name "*.py" -exec grep -l "def main" {} \;
55
+ ```
56
+
57
+ ## Search the user's computer (home directory)
58
+
59
+ When the user says "on my computer", "in my computer", "on my machine", "in my home", "find file named X" (and not in workspace), or "in my Downloads", search their **home directory** using `~` or `$HOME` so it works on **macOS** (/Users/username) and **Linux** (/home/username):
60
+
61
+ **Find a file by exact name:**
62
+
63
+ ```bash
64
+ find ~ -name "saiko_cv" -type f 2>/dev/null
65
+ find ~ -name "gggg.png" -type f 2>/dev/null
66
+ ```
67
+
68
+ **Find in a specific folder (e.g. Downloads, Desktop):**
69
+
70
+ ```bash
71
+ find ~/Downloads -name "*.png" -type f
72
+ find ~/Desktop -name "saiko_cv*" -type f 2>/dev/null
73
+ ```
74
+
75
+ **Find by name pattern (partial match):**
76
+
77
+ ```bash
78
+ find ~ -iname "*saiko_cv*" -type f 2>/dev/null
79
+ find ~ -iname "*gggg*" -type f 2>/dev/null
80
+ ```
81
+
82
+ Use `-iname` for case-insensitive match. Use `2>/dev/null` to hide permission errors.
83
+
84
+ ## Search entire system or a specific path
85
+
86
+ When the user asks for "whole system", "entire disk", or an explicit path:
87
+
88
+ **Portable (home):** use `~` or `$HOME` (works on macOS and Linux).
89
+
90
+ **Linux:** `/home` or `/home/$(whoami)`.
91
+
92
+ **macOS:** `/Users` or `~` (e.g. `/Users/saiko`).
93
+
94
+ ```bash
95
+ find ~ -name "*.md" -type f 2>/dev/null
96
+ find /home -name "*.conf" -type f 2>/dev/null
97
+ find / -name "*.conf" -type f 2>/dev/null
98
+ ```
99
+
100
+ **Grep in a path:**
101
+
102
+ ```bash
103
+ grep -r "pattern" ~ 2>/dev/null
104
+ grep -rln "TODO" ~/projects 2>/dev/null
105
+ ```
106
+
107
+ **Limit depth for large trees:**
108
+
109
+ ```bash
110
+ find ~ -maxdepth 5 -name "*.json" -type f
111
+ ```
112
+
113
+ **Tips:**
114
+
115
+ - **"My computer" or "find file X"** → use `find ~ -name "X"` (or `find ~/Downloads -name "X"` if they say "in Downloads"). Do not search only the workspace.
116
+ - Prefer `~` or `$HOME` so the same command works on macOS and Linux.
117
+ - Add `2>/dev/null` to hide "Permission denied" when searching outside the workspace.
118
+
119
+ ## Tips (workspace-only)
120
+
121
+ - Use `.` so search is limited to current directory (workspace root when exec runs there).
122
+ - For large trees, consider `-maxdepth` or file-type filters to keep output small.
@@ -0,0 +1,68 @@
1
+ ---
2
+ name: file-stats
3
+ description: Get line count, word count, or first/last lines of a file (wc, head, tail). Use when the user asks "how many lines in this file", "first 20 lines of …", "word count", "last 10 lines", "show the top of the file".
4
+ metadata:
5
+ clawdbot:
6
+ emoji: "📊"
7
+ requires:
8
+ bins:
9
+ - wc
10
+ - head
11
+ - tail
12
+ ---
13
+
14
+ # File stats (wc, head, tail)
15
+
16
+ Use **wc**, **head**, and **tail** via the **exec** tool. Path can be relative (workspace) or absolute (e.g. `~/file.txt`).
17
+
18
+ ## Line count
19
+
20
+ ```bash
21
+ wc -l path/to/file
22
+ wc -l < path/to/file
23
+ # Second form outputs only the number (no filename).
24
+ ```
25
+
26
+ ## Word count
27
+
28
+ ```bash
29
+ wc -w path/to/file
30
+ wc -w < path/to/file
31
+ ```
32
+
33
+ ## Line, word, and byte count
34
+
35
+ ```bash
36
+ wc path/to/file
37
+ # Output: lines words bytes filename
38
+ ```
39
+
40
+ ## First N lines (head)
41
+
42
+ ```bash
43
+ head -n 20 path/to/file
44
+ head -20 path/to/file
45
+ head path/to/file
46
+ # Default is 10 lines.
47
+ ```
48
+
49
+ ## Last N lines (tail)
50
+
51
+ ```bash
52
+ tail -n 10 path/to/file
53
+ tail -10 path/to/file
54
+ tail path/to/file
55
+ # Default is 10 lines.
56
+ ```
57
+
58
+ ## Skip first N lines (tail)
59
+
60
+ ```bash
61
+ tail -n +21 path/to/file
62
+ # Lines 21 to end (skip first 20).
63
+ ```
64
+
65
+ ## Tips
66
+
67
+ - Use `head -c 5000` or `tail -c 5000` for first/last N **bytes** if needed.
68
+ - For "preview" or "first part of file", use `head -n 50`.
@@ -0,0 +1,60 @@
1
+ ---
2
+ name: git
3
+ description: Run read-only git commands in the workspace (status, log, branch, diff). Use when the user asks "what's the git status", "recent commits", "current branch", "show me the diff".
4
+ metadata:
5
+ clawdbot:
6
+ emoji: "📂"
7
+ requires:
8
+ bins:
9
+ - git
10
+ ---
11
+
12
+ # Git (read-only)
13
+
14
+ Run **read-only** git commands in the workspace via the **exec** tool. Do **not** run `git commit`, `git push`, `git reset`, or any command that modifies history or remote. Restrict to status, log, branch, and diff.
15
+
16
+ ## Status
17
+
18
+ ```bash
19
+ git status
20
+ ```
21
+
22
+ Working tree state (clean, modified, untracked).
23
+
24
+ ## Recent commits
25
+
26
+ ```bash
27
+ git log -n 10 --oneline
28
+ git log -n 5 --pretty=format:"%h %s (%an, %ar)"
29
+ ```
30
+
31
+ ## Current branch and list branches
32
+
33
+ ```bash
34
+ git branch --show-current
35
+ git branch -a
36
+ ```
37
+
38
+ ## Diff (unstaged changes)
39
+
40
+ ```bash
41
+ git diff
42
+ git diff --stat
43
+ ```
44
+
45
+ For a specific file:
46
+
47
+ ```bash
48
+ git diff -- path/to/file
49
+ ```
50
+
51
+ ## Last commit message
52
+
53
+ ```bash
54
+ git log -1 --pretty=%B
55
+ ```
56
+
57
+ ## Tips
58
+
59
+ - Commands run in the **workspace** (agent workspace or repo root). Do not pass `skill_id` for git unless the skill dir is the repo; use exec with cwd in the workspace.
60
+ - If the user asks "what branch am I on" or "any uncommitted changes?", use the commands above and summarize the output.
@@ -0,0 +1,55 @@
1
+ ---
2
+ name: gmail
3
+ description: Send email via Gmail using your connected account. Uses Sulala Portal for the access token; includes a script to send email from the command line or automation. Requires the Sulala Portal skill for token. Use when the user wants to send email, compose mail, or automate Gmail sending.
4
+ metadata:
5
+ sulala:
6
+ requires:
7
+ skills:
8
+ - sulala-portal
9
+ ---
10
+
11
+ # Gmail (Sulala Portal)
12
+
13
+ Send email using your **Gmail account connected in the Sulala Portal**. This skill provides a **script**; use the **exec** tool to run it. No static send-email code in the loader; the skill is script + docs like YouTube Shorts automation.
14
+
15
+ ## Overview
16
+
17
+ 1. **Get an access token** from the Portal (list connections, then `POST connections/{connection_id}/use` for Gmail).
18
+ 2. **Send email** by running the script via **exec** (see below).
19
+
20
+ ## Getting the token (Portal)
21
+
22
+ - **Tool**: `sulala-portal_request`
23
+ - **List connections**: `GET` path `connections` (filter by `provider === "gmail"` in the response).
24
+ - **Get token**: `POST` path `connections/{id}/use`. Use the connection’s `connection_id` from the list (e.g. `conn_gmail_...`). If you get 404, use `connection_id` in the path instead of `id`. Response: `{ connectionId, provider, accessToken, scopes }`.
25
+
26
+ ## Sending email (use exec tool + script — preferred)
27
+
28
+ Use the **exec** tool to run the skill script. No need to build RFC 2822 or base64url by hand.
29
+
30
+ 1. Get **accessToken** from the Portal (`sulala-portal_request`: list connections, then `POST connections/{connection_id}/use` with the Gmail connection’s `connection_id`).
31
+ 2. Call **exec** with:
32
+ - **skill_id**: `"gmail"` (so the command runs in this skill’s directory).
33
+ - **command**: `python3 scripts/send_email.py --token "<accessToken>" --to "recipient@example.com" --subject "Subject line" --body "Email body text."`
34
+
35
+ Example exec call:
36
+
37
+ ```json
38
+ {
39
+ "skill_id": "gmail",
40
+ "command": "python3 scripts/send_email.py --token \"<paste accessToken from Portal>\" --to \"sai.ko@mothernode.com\" --subject \"test title\" --body \"test body\""
41
+ }
42
+ ```
43
+
44
+ - **Token**: from `POST connections/{connection_id}/use` (see above).
45
+ - **To**, **Subject**, **Body**: recipient email, subject line, and body text. Escape quotes inside the command string as needed.
46
+
47
+ Full script options: [references/send-email.md](references/send-email.md).
48
+
49
+ ## Skill layout (like YouTube Shorts automation)
50
+
51
+ - **scripts/send_email.py** — runnable script: `--token`, `--to`, `--subject`, `--body` or `--body-file`.
52
+ - **references/send-email.md** — how to run the script and get the token.
53
+ - **SKILL.md** — this file: overview, get token, send via exec + script.
54
+
55
+ No separate config: the Sulala Portal skill provides the gateway and token; this skill adds the script and docs.