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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +32 -0
- data/LICENSE.txt +21 -0
- data/README.md +456 -0
- data/exe/pocketrb +6 -0
- data/lib/pocketrb/agent/compaction.rb +187 -0
- data/lib/pocketrb/agent/context.rb +171 -0
- data/lib/pocketrb/agent/loop.rb +276 -0
- data/lib/pocketrb/agent/spawn_tool.rb +72 -0
- data/lib/pocketrb/agent/subagent_manager.rb +196 -0
- data/lib/pocketrb/bus/events.rb +99 -0
- data/lib/pocketrb/bus/message_bus.rb +148 -0
- data/lib/pocketrb/channels/base.rb +69 -0
- data/lib/pocketrb/channels/cli.rb +109 -0
- data/lib/pocketrb/channels/telegram.rb +607 -0
- data/lib/pocketrb/channels/whatsapp.rb +242 -0
- data/lib/pocketrb/cli/base.rb +119 -0
- data/lib/pocketrb/cli/chat.rb +67 -0
- data/lib/pocketrb/cli/config.rb +52 -0
- data/lib/pocketrb/cli/cron.rb +144 -0
- data/lib/pocketrb/cli/gateway.rb +132 -0
- data/lib/pocketrb/cli/init.rb +39 -0
- data/lib/pocketrb/cli/plans.rb +28 -0
- data/lib/pocketrb/cli/skills.rb +34 -0
- data/lib/pocketrb/cli/start.rb +55 -0
- data/lib/pocketrb/cli/telegram.rb +93 -0
- data/lib/pocketrb/cli/version.rb +18 -0
- data/lib/pocketrb/cli/whatsapp.rb +60 -0
- data/lib/pocketrb/cli.rb +124 -0
- data/lib/pocketrb/config.rb +190 -0
- data/lib/pocketrb/cron/job.rb +155 -0
- data/lib/pocketrb/cron/service.rb +395 -0
- data/lib/pocketrb/heartbeat/service.rb +175 -0
- data/lib/pocketrb/mcp/client.rb +172 -0
- data/lib/pocketrb/mcp/memory_tool.rb +133 -0
- data/lib/pocketrb/media/processor.rb +258 -0
- data/lib/pocketrb/memory.rb +283 -0
- data/lib/pocketrb/planning/manager.rb +159 -0
- data/lib/pocketrb/planning/plan.rb +223 -0
- data/lib/pocketrb/planning/tool.rb +176 -0
- data/lib/pocketrb/providers/anthropic.rb +333 -0
- data/lib/pocketrb/providers/base.rb +98 -0
- data/lib/pocketrb/providers/claude_cli.rb +412 -0
- data/lib/pocketrb/providers/claude_max_proxy.rb +347 -0
- data/lib/pocketrb/providers/openrouter.rb +205 -0
- data/lib/pocketrb/providers/registry.rb +59 -0
- data/lib/pocketrb/providers/ruby_llm_provider.rb +136 -0
- data/lib/pocketrb/providers/types.rb +111 -0
- data/lib/pocketrb/session/manager.rb +192 -0
- data/lib/pocketrb/session/session.rb +204 -0
- data/lib/pocketrb/skills/builtin/github/SKILL.md +113 -0
- data/lib/pocketrb/skills/builtin/proactive/SKILL.md +101 -0
- data/lib/pocketrb/skills/builtin/reflection/SKILL.md +109 -0
- data/lib/pocketrb/skills/builtin/tmux/SKILL.md +130 -0
- data/lib/pocketrb/skills/builtin/weather/SKILL.md +130 -0
- data/lib/pocketrb/skills/create_tool.rb +115 -0
- data/lib/pocketrb/skills/loader.rb +164 -0
- data/lib/pocketrb/skills/modify_tool.rb +123 -0
- data/lib/pocketrb/skills/skill.rb +75 -0
- data/lib/pocketrb/tools/background_job_manager.rb +261 -0
- data/lib/pocketrb/tools/base.rb +118 -0
- data/lib/pocketrb/tools/browser.rb +152 -0
- data/lib/pocketrb/tools/browser_advanced.rb +470 -0
- data/lib/pocketrb/tools/browser_session.rb +167 -0
- data/lib/pocketrb/tools/cron.rb +222 -0
- data/lib/pocketrb/tools/edit_file.rb +101 -0
- data/lib/pocketrb/tools/exec.rb +194 -0
- data/lib/pocketrb/tools/jobs.rb +127 -0
- data/lib/pocketrb/tools/list_dir.rb +102 -0
- data/lib/pocketrb/tools/memory.rb +167 -0
- data/lib/pocketrb/tools/message.rb +70 -0
- data/lib/pocketrb/tools/para_memory.rb +264 -0
- data/lib/pocketrb/tools/read_file.rb +65 -0
- data/lib/pocketrb/tools/registry.rb +160 -0
- data/lib/pocketrb/tools/send_file.rb +158 -0
- data/lib/pocketrb/tools/think.rb +35 -0
- data/lib/pocketrb/tools/web_fetch.rb +150 -0
- data/lib/pocketrb/tools/web_search.rb +102 -0
- data/lib/pocketrb/tools/write_file.rb +55 -0
- data/lib/pocketrb/version.rb +5 -0
- data/lib/pocketrb.rb +75 -0
- data/pocketrb.gemspec +60 -0
- 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
|