pocketrb 0.1.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.
Files changed (83) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +32 -0
  3. data/LICENSE.txt +21 -0
  4. data/README.md +456 -0
  5. data/exe/pocketrb +6 -0
  6. data/lib/pocketrb/agent/compaction.rb +187 -0
  7. data/lib/pocketrb/agent/context.rb +171 -0
  8. data/lib/pocketrb/agent/loop.rb +276 -0
  9. data/lib/pocketrb/agent/spawn_tool.rb +72 -0
  10. data/lib/pocketrb/agent/subagent_manager.rb +196 -0
  11. data/lib/pocketrb/bus/events.rb +99 -0
  12. data/lib/pocketrb/bus/message_bus.rb +148 -0
  13. data/lib/pocketrb/channels/base.rb +69 -0
  14. data/lib/pocketrb/channels/cli.rb +109 -0
  15. data/lib/pocketrb/channels/telegram.rb +607 -0
  16. data/lib/pocketrb/channels/whatsapp.rb +242 -0
  17. data/lib/pocketrb/cli/base.rb +119 -0
  18. data/lib/pocketrb/cli/chat.rb +67 -0
  19. data/lib/pocketrb/cli/config.rb +52 -0
  20. data/lib/pocketrb/cli/cron.rb +144 -0
  21. data/lib/pocketrb/cli/gateway.rb +132 -0
  22. data/lib/pocketrb/cli/init.rb +39 -0
  23. data/lib/pocketrb/cli/plans.rb +28 -0
  24. data/lib/pocketrb/cli/skills.rb +34 -0
  25. data/lib/pocketrb/cli/start.rb +55 -0
  26. data/lib/pocketrb/cli/telegram.rb +93 -0
  27. data/lib/pocketrb/cli/version.rb +18 -0
  28. data/lib/pocketrb/cli/whatsapp.rb +60 -0
  29. data/lib/pocketrb/cli.rb +124 -0
  30. data/lib/pocketrb/config.rb +190 -0
  31. data/lib/pocketrb/cron/job.rb +155 -0
  32. data/lib/pocketrb/cron/service.rb +395 -0
  33. data/lib/pocketrb/heartbeat/service.rb +175 -0
  34. data/lib/pocketrb/mcp/client.rb +172 -0
  35. data/lib/pocketrb/mcp/memory_tool.rb +133 -0
  36. data/lib/pocketrb/media/processor.rb +258 -0
  37. data/lib/pocketrb/memory.rb +283 -0
  38. data/lib/pocketrb/planning/manager.rb +159 -0
  39. data/lib/pocketrb/planning/plan.rb +223 -0
  40. data/lib/pocketrb/planning/tool.rb +176 -0
  41. data/lib/pocketrb/providers/anthropic.rb +333 -0
  42. data/lib/pocketrb/providers/base.rb +98 -0
  43. data/lib/pocketrb/providers/claude_cli.rb +412 -0
  44. data/lib/pocketrb/providers/claude_max_proxy.rb +347 -0
  45. data/lib/pocketrb/providers/openrouter.rb +205 -0
  46. data/lib/pocketrb/providers/registry.rb +59 -0
  47. data/lib/pocketrb/providers/ruby_llm_provider.rb +136 -0
  48. data/lib/pocketrb/providers/types.rb +111 -0
  49. data/lib/pocketrb/session/manager.rb +192 -0
  50. data/lib/pocketrb/session/session.rb +204 -0
  51. data/lib/pocketrb/skills/builtin/github/SKILL.md +113 -0
  52. data/lib/pocketrb/skills/builtin/proactive/SKILL.md +101 -0
  53. data/lib/pocketrb/skills/builtin/reflection/SKILL.md +109 -0
  54. data/lib/pocketrb/skills/builtin/tmux/SKILL.md +130 -0
  55. data/lib/pocketrb/skills/builtin/weather/SKILL.md +130 -0
  56. data/lib/pocketrb/skills/create_tool.rb +115 -0
  57. data/lib/pocketrb/skills/loader.rb +164 -0
  58. data/lib/pocketrb/skills/modify_tool.rb +123 -0
  59. data/lib/pocketrb/skills/skill.rb +75 -0
  60. data/lib/pocketrb/tools/background_job_manager.rb +261 -0
  61. data/lib/pocketrb/tools/base.rb +118 -0
  62. data/lib/pocketrb/tools/browser.rb +152 -0
  63. data/lib/pocketrb/tools/browser_advanced.rb +470 -0
  64. data/lib/pocketrb/tools/browser_session.rb +167 -0
  65. data/lib/pocketrb/tools/cron.rb +222 -0
  66. data/lib/pocketrb/tools/edit_file.rb +101 -0
  67. data/lib/pocketrb/tools/exec.rb +194 -0
  68. data/lib/pocketrb/tools/jobs.rb +127 -0
  69. data/lib/pocketrb/tools/list_dir.rb +102 -0
  70. data/lib/pocketrb/tools/memory.rb +167 -0
  71. data/lib/pocketrb/tools/message.rb +70 -0
  72. data/lib/pocketrb/tools/para_memory.rb +264 -0
  73. data/lib/pocketrb/tools/read_file.rb +65 -0
  74. data/lib/pocketrb/tools/registry.rb +160 -0
  75. data/lib/pocketrb/tools/send_file.rb +158 -0
  76. data/lib/pocketrb/tools/think.rb +35 -0
  77. data/lib/pocketrb/tools/web_fetch.rb +150 -0
  78. data/lib/pocketrb/tools/web_search.rb +102 -0
  79. data/lib/pocketrb/tools/write_file.rb +55 -0
  80. data/lib/pocketrb/version.rb +5 -0
  81. data/lib/pocketrb.rb +75 -0
  82. data/pocketrb.gemspec +60 -0
  83. metadata +327 -0
@@ -0,0 +1,113 @@
1
+ ---
2
+ name: github
3
+ description: "Interact with GitHub using the `gh` CLI"
4
+ always: false
5
+ triggers:
6
+ - github
7
+ - gh
8
+ - pull request
9
+ - pr
10
+ - issue
11
+ - repo
12
+ - workflow
13
+ - actions
14
+ requires:
15
+ - bin:gh
16
+ metadata:
17
+ pocketrb:
18
+ emoji: "🐙"
19
+ ---
20
+
21
+ # GitHub Skill
22
+
23
+ Use the `gh` CLI for GitHub operations. This skill provides guidance on common GitHub workflows.
24
+
25
+ ## Prerequisites
26
+
27
+ The `gh` CLI must be installed and authenticated:
28
+ ```bash
29
+ # Install (macOS)
30
+ brew install gh
31
+
32
+ # Install (Linux)
33
+ # See https://github.com/cli/cli/blob/trunk/docs/install_linux.md
34
+
35
+ # Authenticate
36
+ gh auth login
37
+ ```
38
+
39
+ ## Common Commands
40
+
41
+ ### Pull Requests
42
+
43
+ ```bash
44
+ # List PRs
45
+ gh pr list --repo owner/repo
46
+
47
+ # View PR details
48
+ gh pr view 55 --repo owner/repo
49
+
50
+ # Check PR status/checks
51
+ gh pr checks 55 --repo owner/repo
52
+
53
+ # Create PR
54
+ gh pr create --title "Title" --body "Description"
55
+
56
+ # Merge PR
57
+ gh pr merge 55 --squash --delete-branch
58
+
59
+ # Review PR
60
+ gh pr diff 55 --repo owner/repo
61
+ ```
62
+
63
+ ### Issues
64
+
65
+ ```bash
66
+ # List issues
67
+ gh issue list --repo owner/repo
68
+
69
+ # View issue
70
+ gh issue view 123 --repo owner/repo
71
+
72
+ # Create issue
73
+ gh issue create --title "Bug" --body "Description"
74
+
75
+ # Close issue
76
+ gh issue close 123
77
+ ```
78
+
79
+ ### Workflows / Actions
80
+
81
+ ```bash
82
+ # List workflow runs
83
+ gh run list --repo owner/repo --limit 10
84
+
85
+ # View run details
86
+ gh run view 12345 --repo owner/repo
87
+
88
+ # Watch a run
89
+ gh run watch 12345 --repo owner/repo
90
+
91
+ # Rerun failed jobs
92
+ gh run rerun 12345 --failed
93
+ ```
94
+
95
+ ### API Access
96
+
97
+ ```bash
98
+ # Get PR info as JSON
99
+ gh api repos/owner/repo/pulls/55 --jq '.title'
100
+
101
+ # Get issue comments
102
+ gh api repos/owner/repo/issues/123/comments
103
+
104
+ # Create a comment
105
+ gh api repos/owner/repo/issues/123/comments -f body="Comment text"
106
+ ```
107
+
108
+ ## Tips
109
+
110
+ - Use `--repo owner/repo` or `-R owner/repo` to specify repository
111
+ - Use `--json field1,field2` to get specific fields as JSON
112
+ - Use `--jq '.field'` to filter JSON output
113
+ - Most commands support `--web` to open in browser
@@ -0,0 +1,101 @@
1
+ ---
2
+ name: proactive
3
+ description: "Be proactive - schedule follow-ups, reminders, and check-ins"
4
+ always: true
5
+ metadata:
6
+ emoji: "⏰"
7
+ ---
8
+
9
+ # Proactive Agent Skill
10
+
11
+ You have the ability to schedule tasks for yourself using the `cron` tool. Use this to be genuinely helpful and proactive.
12
+
13
+ ## When to Create Scheduled Tasks
14
+
15
+ **DO schedule tasks when:**
16
+
17
+ - User mentions a deadline or future event → offer to remind them
18
+ - User starts a project → offer daily/weekly check-ins
19
+ - You're waiting on external results → schedule a follow-up check
20
+ - User seems overwhelmed → offer to nudge about priorities
21
+ - A task has natural follow-up steps → schedule the next step
22
+ - User asks you to remind them about anything
23
+ - User says "remind me", "ping me", "follow up", "check back", etc.
24
+
25
+ **DON'T over-schedule:**
26
+
27
+ - Ask before creating recurring jobs (daily, weekly)
28
+ - One-time reminders are fine to create proactively
29
+ - Don't spam - consolidate related reminders
30
+
31
+ ## Cron Tool Parameters
32
+
33
+ The `cron` tool accepts these parameters:
34
+
35
+ - **action**: "add", "list", "remove", "enable", "disable"
36
+ - **name**: A short label for the job (required for add)
37
+ - **message**: What to send when job fires (required for add)
38
+ - **schedule_type**: "at" (one-time), "every" (interval), "cron" (expression)
39
+ - **schedule_value**: ISO datetime for "at", seconds for "every", cron expression for "cron"
40
+ - **deliver**: true to send message directly, false to wake agent with message
41
+ - **job_id**: Job ID for remove/enable/disable actions
42
+
43
+ ## Schedule Examples
44
+
45
+ ### One-time Reminder
46
+ Schedule a reminder for a specific time:
47
+ - schedule_type: "at"
48
+ - schedule_value: ISO datetime like "2026-02-04T09:00:00"
49
+
50
+ ### Interval-based (every N seconds)
51
+ Run every X seconds (minimum 60):
52
+ - schedule_type: "every"
53
+ - schedule_value: "3600" (every hour), "7200" (every 2 hours), "86400" (daily)
54
+
55
+ ### Cron Expression
56
+ Standard cron syntax (minute hour day month weekday):
57
+ - schedule_type: "cron"
58
+ - schedule_value: "0 9 * * *" (9am daily), "0 9 * * 1" (9am Mondays), "30 14 * * *" (2:30pm daily)
59
+
60
+ ## Proactive Patterns
61
+
62
+ ### User Asks for Reminder
63
+ When user says "remind me about X" or "ping me in Y":
64
+ 1. Parse the time/interval from their request
65
+ 2. Create the job immediately using the cron tool
66
+ 3. Confirm what you scheduled
67
+
68
+ ### Research Follow-up
69
+ When you start research that takes time:
70
+ > "I'll schedule a follow-up for tomorrow to continue the competitor analysis."
71
+
72
+ ### Deadline Tracking
73
+ When user mentions a deadline:
74
+ > "Your pitch is on Friday. Want me to check in Wednesday to review the deck?"
75
+
76
+ ### Project Momentum
77
+ For ongoing projects:
78
+ > "Should I do a weekly check-in on the Zakiya project? I can nudge you every Monday at 10am."
79
+
80
+ ### Waiting on External
81
+ When waiting for something:
82
+ > "The domain registration takes 24-48 hours. I'll check back tomorrow afternoon."
83
+
84
+ ## Message Format
85
+
86
+ When a scheduled job fires, your message will be delivered to the same channel. Write messages that:
87
+
88
+ - Provide context (what this is about)
89
+ - Are actionable (what should happen next)
90
+ - Feel natural, not robotic
91
+
92
+ **Good:** "Hey! Following up on the trademark search we discussed. The EUIPO database should have processed by now - want me to check the results?"
93
+
94
+ **Bad:** "SCHEDULED REMINDER: Trademark search follow-up [job_id: xyz]"
95
+
96
+ ## Transparency
97
+
98
+ Always tell the user when you create a scheduled task:
99
+ > "Got it! I've scheduled a reminder for tomorrow at 9am to follow up on this."
100
+
101
+ If they ask what's scheduled, use the cron tool with action "list" and summarize in natural language.
@@ -0,0 +1,109 @@
1
+ ---
2
+ name: reflection
3
+ description: "Periodic self-assessment, goal tracking, and proactive improvement"
4
+ always: true
5
+ metadata:
6
+ emoji: "🪞"
7
+ ---
8
+
9
+ # Reflection Skill
10
+
11
+ You have the ability to reflect, plan, and improve over time. Use heartbeat and scheduled tasks to maintain continuity between conversations.
12
+
13
+ ## When to Reflect
14
+
15
+ ### During Conversations
16
+ - At the end of complex tasks, note what worked and what didn't
17
+ - When user expresses frustration, consider what could be improved
18
+ - After completing a project milestone, summarize progress
19
+
20
+ ### During Heartbeats
21
+ When the heartbeat wakes you up, check:
22
+ 1. **HEARTBEAT.md** - Any pending tasks or instructions?
23
+ 2. **Recent activity** - What was accomplished recently?
24
+ 3. **Open loops** - Any unfinished work that needs follow-up?
25
+
26
+ If nothing needs attention, respond with: HEARTBEAT_OK
27
+
28
+ ### Scheduled Reflection
29
+ You can schedule periodic reflection sessions:
30
+ - Daily review: "What was accomplished? What's pending?"
31
+ - Weekly planning: "What are the goals for next week?"
32
+ - Monthly retrospective: "What patterns am I seeing?"
33
+
34
+ ## What to Reflect On
35
+
36
+ ### User Patterns
37
+ - How does the user prefer to communicate?
38
+ - What topics come up frequently?
39
+ - What frustrates them? What delights them?
40
+
41
+ ### Task Patterns
42
+ - What types of tasks are most common?
43
+ - Where do I tend to struggle or make mistakes?
44
+ - What could be automated or streamlined?
45
+
46
+ ### Knowledge Gaps
47
+ - What questions couldn't I answer well?
48
+ - What domains need more learning?
49
+ - What tools or skills would be useful to develop?
50
+
51
+ ## Storing Reflections
52
+
53
+ Use the memory tool to store durable insights:
54
+
55
+ ### Good candidates for memory:
56
+ - User preferences discovered through interaction
57
+ - Project milestones and decisions
58
+ - Recurring patterns or workflows
59
+ - Important context about people/companies
60
+ - Lessons learned from mistakes
61
+
62
+ ### Not worth storing:
63
+ - One-off transient information
64
+ - Things the user explicitly said are temporary
65
+ - Trivial details without lasting value
66
+
67
+ ## Proactive Improvement
68
+
69
+ When you identify an improvement opportunity:
70
+
71
+ 1. **Ask before implementing** - "I noticed X pattern. Should I Y?"
72
+ 2. **Suggest don't dictate** - User has final say on workflows
73
+ 3. **Start small** - One change at a time, evaluate results
74
+
75
+ ### Examples
76
+
77
+ **Good:** "I've noticed you often ask about project X status on Mondays. Should I schedule a Monday morning summary?"
78
+
79
+ **Good:** "The last three times we discussed Y, you mentioned Z constraint. Should I add that to my working memory?"
80
+
81
+ **Bad:** Silently changing behavior without user awareness
82
+
83
+ ## Heartbeat Response Format
84
+
85
+ When responding to heartbeat prompts:
86
+
87
+ ### If action needed:
88
+ ```
89
+ Checking HEARTBEAT.md...
90
+ Found pending task: [task description]
91
+ Taking action: [what you're doing]
92
+ ```
93
+
94
+ ### If nothing needed:
95
+ ```
96
+ HEARTBEAT_OK
97
+ ```
98
+
99
+ The HEARTBEAT_OK token tells the system no further action is needed.
100
+
101
+ ## Continuous Learning
102
+
103
+ Track what you learn in each conversation:
104
+ - New facts about the user's world
105
+ - Preferences and communication style
106
+ - Domain knowledge relevant to their work
107
+ - Tool usage patterns and shortcuts
108
+
109
+ Store significant learnings to memory so they persist across sessions.
@@ -0,0 +1,130 @@
1
+ ---
2
+ name: tmux
3
+ description: "Remote-control tmux sessions for interactive CLIs"
4
+ always: false
5
+ triggers:
6
+ - tmux
7
+ - terminal
8
+ - session
9
+ - multiplexer
10
+ requires:
11
+ - bin:tmux
12
+ metadata:
13
+ pocketrb:
14
+ emoji: "🧵"
15
+ os:
16
+ - darwin
17
+ - linux
18
+ ---
19
+
20
+ # Tmux Skill
21
+
22
+ Control tmux sessions via socket for isolated agent workspaces. This allows running and interacting with persistent terminal sessions.
23
+
24
+ ## Socket Setup
25
+
26
+ Use a dedicated socket directory to avoid conflicts:
27
+
28
+ ```bash
29
+ SOCKET_DIR="${POCKETRB_TMUX_SOCKET_DIR:-${TMPDIR:-/tmp}/pocketrb-tmux-sockets}"
30
+ mkdir -p "$SOCKET_DIR"
31
+ SOCKET="$SOCKET_DIR/pocketrb.sock"
32
+ ```
33
+
34
+ ## Basic Commands
35
+
36
+ ### Session Management
37
+
38
+ ```bash
39
+ # Create a new session
40
+ tmux -S "$SOCKET" new-session -d -s mysession
41
+
42
+ # Create session with initial command
43
+ tmux -S "$SOCKET" new-session -d -s mysession "python3"
44
+
45
+ # List sessions
46
+ tmux -S "$SOCKET" list-sessions
47
+
48
+ # Kill a session
49
+ tmux -S "$SOCKET" kill-session -t mysession
50
+
51
+ # Attach to session (interactive)
52
+ tmux -S "$SOCKET" attach -t mysession
53
+ ```
54
+
55
+ ### Sending Commands
56
+
57
+ ```bash
58
+ # Send keys (commands) to a session
59
+ tmux -S "$SOCKET" send-keys -t mysession "ls -la" Enter
60
+
61
+ # Send literal text (no Enter)
62
+ tmux -S "$SOCKET" send-keys -t mysession -l "some text"
63
+
64
+ # Send special keys
65
+ tmux -S "$SOCKET" send-keys -t mysession C-c # Ctrl+C
66
+ tmux -S "$SOCKET" send-keys -t mysession C-d # Ctrl+D
67
+ tmux -S "$SOCKET" send-keys -t mysession Up # Arrow up
68
+ ```
69
+
70
+ ### Capturing Output
71
+
72
+ ```bash
73
+ # Capture visible pane content
74
+ tmux -S "$SOCKET" capture-pane -p -t mysession
75
+
76
+ # Capture with history (last 200 lines)
77
+ tmux -S "$SOCKET" capture-pane -p -J -t mysession -S -200
78
+
79
+ # Capture to file
80
+ tmux -S "$SOCKET" capture-pane -p -t mysession > output.txt
81
+ ```
82
+
83
+ ## Common Patterns
84
+
85
+ ### Run Command and Get Output
86
+
87
+ ```bash
88
+ # Send command
89
+ tmux -S "$SOCKET" send-keys -t mysession "python3 script.py" Enter
90
+
91
+ # Wait for completion (simple approach)
92
+ sleep 2
93
+
94
+ # Capture output
95
+ tmux -S "$SOCKET" capture-pane -p -J -t mysession -S -50
96
+ ```
97
+
98
+ ### Interactive Python/REPL Session
99
+
100
+ ```bash
101
+ # Start Python session
102
+ tmux -S "$SOCKET" new-session -d -s python "python3"
103
+
104
+ # Send Python commands
105
+ tmux -S "$SOCKET" send-keys -t python "import os" Enter
106
+ tmux -S "$SOCKET" send-keys -t python "print(os.getcwd())" Enter
107
+
108
+ # Get output
109
+ sleep 1
110
+ tmux -S "$SOCKET" capture-pane -p -t python
111
+ ```
112
+
113
+ ### SSH Session
114
+
115
+ ```bash
116
+ # Start SSH session
117
+ tmux -S "$SOCKET" new-session -d -s remote "ssh user@host"
118
+
119
+ # Wait for connection, then send commands
120
+ sleep 3
121
+ tmux -S "$SOCKET" send-keys -t remote "ls -la" Enter
122
+ ```
123
+
124
+ ## Tips
125
+
126
+ - Use `-l` flag with `send-keys` for literal text to avoid interpretation
127
+ - The `-J` flag in `capture-pane` joins wrapped lines
128
+ - Use `-S -N` in `capture-pane` to capture last N lines of history
129
+ - Clean up sessions when done to avoid resource leaks
130
+ - Use unique session names to avoid conflicts
@@ -0,0 +1,130 @@
1
+ ---
2
+ name: weather
3
+ description: "Get weather forecasts using wttr.in (no API key required)"
4
+ always: false
5
+ triggers:
6
+ - weather
7
+ - forecast
8
+ - temperature
9
+ - rain
10
+ - snow
11
+ requires:
12
+ - bin:curl
13
+ metadata:
14
+ pocketrb:
15
+ emoji: "🌤️"
16
+ ---
17
+
18
+ # Weather Skill
19
+
20
+ Get weather data using wttr.in - a console-oriented weather service that requires no API key.
21
+
22
+ ## Quick Commands
23
+
24
+ ### Current Weather
25
+
26
+ ```bash
27
+ # Simple one-line format
28
+ curl -s "wttr.in/London?format=3"
29
+ # Output: London: ⛅️ +8°C
30
+
31
+ # With more details
32
+ curl -s "wttr.in/London?format=%l:+%c+%t+%h+%w"
33
+ # Output: London: ⛅️ +8°C 65% ↙15km/h
34
+
35
+ # Current conditions only
36
+ curl -s "wttr.in/London?0"
37
+ ```
38
+
39
+ ### Full Forecast
40
+
41
+ ```bash
42
+ # 3-day forecast (default)
43
+ curl -s "wttr.in/London"
44
+
45
+ # 1-day forecast
46
+ curl -s "wttr.in/London?1"
47
+
48
+ # 2-day forecast
49
+ curl -s "wttr.in/London?2"
50
+ ```
51
+
52
+ ### Format Options
53
+
54
+ ```bash
55
+ # Metric units (Celsius, km/h)
56
+ curl -s "wttr.in/London?m"
57
+
58
+ # Imperial units (Fahrenheit, mph)
59
+ curl -s "wttr.in/London?u"
60
+
61
+ # Compact format (no terminal colors)
62
+ curl -s "wttr.in/London?T"
63
+
64
+ # Plain text (no ANSI)
65
+ curl -s "wttr.in/London?T"
66
+ ```
67
+
68
+ ## Custom Format Strings
69
+
70
+ Use `format=` for custom output:
71
+
72
+ | Symbol | Meaning |
73
+ |--------|---------|
74
+ | %c | Weather condition icon |
75
+ | %C | Weather condition text |
76
+ | %t | Temperature |
77
+ | %f | "Feels like" temperature |
78
+ | %h | Humidity |
79
+ | %w | Wind |
80
+ | %l | Location |
81
+ | %m | Moon phase |
82
+ | %p | Precipitation (mm) |
83
+ | %P | Pressure |
84
+ | %S | Sunrise |
85
+ | %s | Sunset |
86
+
87
+ ### Examples
88
+
89
+ ```bash
90
+ # Minimal
91
+ curl -s "wttr.in/Tokyo?format=%c+%t"
92
+ # ☀️ +15°C
93
+
94
+ # Detailed
95
+ curl -s "wttr.in/Tokyo?format=%l:+%C,+%t+(%f),+%h+humidity,+wind+%w"
96
+ # Tokyo: Sunny, +15°C (+13°C), 45% humidity, wind ↗12km/h
97
+
98
+ # JSON format
99
+ curl -s "wttr.in/Tokyo?format=j1" | jq '.current_condition[0].temp_C'
100
+ ```
101
+
102
+ ## Location Formats
103
+
104
+ ```bash
105
+ # City name
106
+ curl -s "wttr.in/Paris"
107
+
108
+ # City, Country
109
+ curl -s "wttr.in/Paris,France"
110
+
111
+ # Airport code
112
+ curl -s "wttr.in/JFK"
113
+
114
+ # Coordinates
115
+ curl -s "wttr.in/51.5,-0.1"
116
+
117
+ # IP-based (auto-detect)
118
+ curl -s "wttr.in"
119
+
120
+ # Landmark
121
+ curl -s "wttr.in/Eiffel+Tower"
122
+ ```
123
+
124
+ ## Tips
125
+
126
+ - Add `?lang=XX` for different languages (e.g., `?lang=de` for German)
127
+ - Use `?n` to disable colors in narrow terminals
128
+ - Append `?Q` for quiet mode (no "Weather report" header)
129
+ - For scripts, use `?format=j1` for full JSON data
130
+ - Moon phase: `curl -s "wttr.in/Moon"`
@@ -0,0 +1,115 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pocketrb
4
+ module Skills
5
+ # Tool for creating new skills at runtime
6
+ class CreateTool < Tools::Base
7
+ def name
8
+ "skill_create"
9
+ end
10
+
11
+ def description
12
+ "Create a new skill. Skills are reusable prompts/instructions that can be loaded into context. Use this to teach yourself new capabilities."
13
+ end
14
+
15
+ def parameters
16
+ {
17
+ type: "object",
18
+ properties: {
19
+ skill_name: {
20
+ type: "string",
21
+ description: "Name of the skill (lowercase, hyphens allowed, e.g., 'code-review')"
22
+ },
23
+ skill_description: {
24
+ type: "string",
25
+ description: "Brief description of what the skill does"
26
+ },
27
+ content: {
28
+ type: "string",
29
+ description: "The skill content - instructions, prompts, or guidelines"
30
+ },
31
+ triggers: {
32
+ type: "array",
33
+ items: { type: "string" },
34
+ description: "Keywords that automatically trigger this skill"
35
+ },
36
+ always: {
37
+ type: "boolean",
38
+ description: "Whether this skill should always be loaded (default: false)"
39
+ }
40
+ },
41
+ required: %w[skill_name skill_description content]
42
+ }
43
+ end
44
+
45
+ def execute(skill_name:, skill_description:, content:, triggers: nil, always: false)
46
+ # Validate skill name
47
+ unless valid_skill_name?(skill_name)
48
+ return error("Invalid skill name. Use lowercase letters, numbers, and hyphens only.")
49
+ end
50
+
51
+ # Create skill directory
52
+ skill_dir = workspace.join("skills", skill_name)
53
+
54
+ return error("Skill '#{skill_name}' already exists. Use skill_modify to update it.") if skill_dir.exist?
55
+
56
+ FileUtils.mkdir_p(skill_dir)
57
+
58
+ # Build skill content with frontmatter
59
+ skill_content = build_skill_file(skill_name, skill_description, content, triggers, always)
60
+
61
+ # Write SKILL.md
62
+ skill_file = skill_dir.join("SKILL.md")
63
+ File.write(skill_file, skill_content)
64
+
65
+ # Update TOOLS.md if it exists
66
+ update_tools_documentation(skill_name, skill_description)
67
+
68
+ success("Created skill '#{skill_name}' at #{skill_file}")
69
+ end
70
+
71
+ private
72
+
73
+ def valid_skill_name?(name)
74
+ name.match?(/\A[a-z][a-z0-9-]*\z/)
75
+ end
76
+
77
+ def build_skill_file(name, description, content, triggers, always)
78
+ metadata = {
79
+ "name" => name,
80
+ "description" => description
81
+ }
82
+ metadata["triggers"] = triggers if triggers && !triggers.empty?
83
+ metadata["always"] = true if always
84
+
85
+ <<~MD
86
+ ---
87
+ #{metadata.to_yaml.lines[1..].join}---
88
+
89
+ #{content}
90
+ MD
91
+ end
92
+
93
+ def update_tools_documentation(skill_name, description)
94
+ tools_file = workspace.join("TOOLS.md")
95
+ return unless tools_file.exist?
96
+
97
+ content = File.read(tools_file)
98
+
99
+ # Find skills section and add new skill
100
+ if content.include?("## Skills")
101
+ # Add to existing skills section
102
+ skills_section_end = content.index(/\n##[^#]/, content.index("## Skills") + 1) || content.length
103
+ insert_point = skills_section_end
104
+
105
+ new_entry = "\n- **#{skill_name}**: #{description}"
106
+
107
+ new_content = content[0...insert_point] + new_entry + content[insert_point..]
108
+ File.write(tools_file, new_content)
109
+ end
110
+ rescue StandardError => e
111
+ Pocketrb.logger.warn("Failed to update TOOLS.md: #{e.message}")
112
+ end
113
+ end
114
+ end
115
+ end