nextclaw-core 0.4.0 โ 0.4.2
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/agent/skills/README.md +24 -0
- package/dist/agent/skills/cron/SKILL.md +40 -0
- package/dist/agent/skills/github/SKILL.md +48 -0
- package/dist/agent/skills/skill-creator/SKILL.md +371 -0
- package/dist/agent/skills/summarize/SKILL.md +67 -0
- package/dist/agent/skills/tmux/SKILL.md +121 -0
- package/dist/agent/skills/tmux/scripts/find-sessions.sh +112 -0
- package/dist/agent/skills/tmux/scripts/wait-for-text.sh +83 -0
- package/dist/agent/skills/weather/SKILL.md +49 -0
- package/dist/index.js +1 -2
- package/dist/skills/README.md +24 -0
- package/dist/skills/cron/SKILL.md +40 -0
- package/dist/skills/github/SKILL.md +48 -0
- package/dist/skills/skill-creator/SKILL.md +371 -0
- package/dist/skills/summarize/SKILL.md +67 -0
- package/dist/skills/tmux/SKILL.md +121 -0
- package/dist/skills/tmux/scripts/find-sessions.sh +112 -0
- package/dist/skills/tmux/scripts/wait-for-text.sh +83 -0
- package/dist/skills/weather/SKILL.md +49 -0
- package/package.json +2 -2
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
usage() {
|
|
5
|
+
cat <<'USAGE'
|
|
6
|
+
Usage: find-sessions.sh [-L socket-name|-S socket-path|-A] [-q pattern]
|
|
7
|
+
|
|
8
|
+
List tmux sessions on a socket (default tmux socket if none provided).
|
|
9
|
+
|
|
10
|
+
Options:
|
|
11
|
+
-L, --socket tmux socket name (passed to tmux -L)
|
|
12
|
+
-S, --socket-path tmux socket path (passed to tmux -S)
|
|
13
|
+
-A, --all scan all sockets under NEXTCLAW_TMUX_SOCKET_DIR
|
|
14
|
+
-q, --query case-insensitive substring to filter session names
|
|
15
|
+
-h, --help show this help
|
|
16
|
+
USAGE
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
socket_name=""
|
|
20
|
+
socket_path=""
|
|
21
|
+
query=""
|
|
22
|
+
scan_all=false
|
|
23
|
+
socket_dir="${NEXTCLAW_TMUX_SOCKET_DIR:-${TMPDIR:-/tmp}/nextclaw-tmux-sockets}"
|
|
24
|
+
|
|
25
|
+
while [[ $# -gt 0 ]]; do
|
|
26
|
+
case "$1" in
|
|
27
|
+
-L|--socket) socket_name="${2-}"; shift 2 ;;
|
|
28
|
+
-S|--socket-path) socket_path="${2-}"; shift 2 ;;
|
|
29
|
+
-A|--all) scan_all=true; shift ;;
|
|
30
|
+
-q|--query) query="${2-}"; shift 2 ;;
|
|
31
|
+
-h|--help) usage; exit 0 ;;
|
|
32
|
+
*) echo "Unknown option: $1" >&2; usage; exit 1 ;;
|
|
33
|
+
esac
|
|
34
|
+
done
|
|
35
|
+
|
|
36
|
+
if [[ "$scan_all" == true && ( -n "$socket_name" || -n "$socket_path" ) ]]; then
|
|
37
|
+
echo "Cannot combine --all with -L or -S" >&2
|
|
38
|
+
exit 1
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
if [[ -n "$socket_name" && -n "$socket_path" ]]; then
|
|
42
|
+
echo "Use either -L or -S, not both" >&2
|
|
43
|
+
exit 1
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
if ! command -v tmux >/dev/null 2>&1; then
|
|
47
|
+
echo "tmux not found in PATH" >&2
|
|
48
|
+
exit 1
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
list_sessions() {
|
|
52
|
+
local label="$1"; shift
|
|
53
|
+
local tmux_cmd=(tmux "$@")
|
|
54
|
+
|
|
55
|
+
if ! sessions="$("${tmux_cmd[@]}" list-sessions -F '#{session_name}\t#{session_attached}\t#{session_created_string}' 2>/dev/null)"; then
|
|
56
|
+
echo "No tmux server found on $label" >&2
|
|
57
|
+
return 1
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
if [[ -n "$query" ]]; then
|
|
61
|
+
sessions="$(printf '%s\n' "$sessions" | grep -i -- "$query" || true)"
|
|
62
|
+
fi
|
|
63
|
+
|
|
64
|
+
if [[ -z "$sessions" ]]; then
|
|
65
|
+
echo "No sessions found on $label"
|
|
66
|
+
return 0
|
|
67
|
+
fi
|
|
68
|
+
|
|
69
|
+
echo "Sessions on $label:"
|
|
70
|
+
printf '%s\n' "$sessions" | while IFS=$'\t' read -r name attached created; do
|
|
71
|
+
attached_label=$([[ "$attached" == "1" ]] && echo "attached" || echo "detached")
|
|
72
|
+
printf ' - %s (%s, started %s)\n' "$name" "$attached_label" "$created"
|
|
73
|
+
done
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if [[ "$scan_all" == true ]]; then
|
|
77
|
+
if [[ ! -d "$socket_dir" ]]; then
|
|
78
|
+
echo "Socket directory not found: $socket_dir" >&2
|
|
79
|
+
exit 1
|
|
80
|
+
fi
|
|
81
|
+
|
|
82
|
+
shopt -s nullglob
|
|
83
|
+
sockets=("$socket_dir"/*)
|
|
84
|
+
shopt -u nullglob
|
|
85
|
+
|
|
86
|
+
if [[ "${#sockets[@]}" -eq 0 ]]; then
|
|
87
|
+
echo "No sockets found under $socket_dir" >&2
|
|
88
|
+
exit 1
|
|
89
|
+
fi
|
|
90
|
+
|
|
91
|
+
exit_code=0
|
|
92
|
+
for sock in "${sockets[@]}"; do
|
|
93
|
+
if [[ ! -S "$sock" ]]; then
|
|
94
|
+
continue
|
|
95
|
+
fi
|
|
96
|
+
list_sessions "socket path '$sock'" -S "$sock" || exit_code=$?
|
|
97
|
+
done
|
|
98
|
+
exit "$exit_code"
|
|
99
|
+
fi
|
|
100
|
+
|
|
101
|
+
tmux_cmd=(tmux)
|
|
102
|
+
socket_label="default socket"
|
|
103
|
+
|
|
104
|
+
if [[ -n "$socket_name" ]]; then
|
|
105
|
+
tmux_cmd+=(-L "$socket_name")
|
|
106
|
+
socket_label="socket name '$socket_name'"
|
|
107
|
+
elif [[ -n "$socket_path" ]]; then
|
|
108
|
+
tmux_cmd+=(-S "$socket_path")
|
|
109
|
+
socket_label="socket path '$socket_path'"
|
|
110
|
+
fi
|
|
111
|
+
|
|
112
|
+
list_sessions "$socket_label" "${tmux_cmd[@]:1}"
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
usage() {
|
|
5
|
+
cat <<'USAGE'
|
|
6
|
+
Usage: wait-for-text.sh -t target -p pattern [options]
|
|
7
|
+
|
|
8
|
+
Poll a tmux pane for text and exit when found.
|
|
9
|
+
|
|
10
|
+
Options:
|
|
11
|
+
-t, --target tmux target (session:window.pane), required
|
|
12
|
+
-p, --pattern regex pattern to look for, required
|
|
13
|
+
-F, --fixed treat pattern as a fixed string (grep -F)
|
|
14
|
+
-T, --timeout seconds to wait (integer, default: 15)
|
|
15
|
+
-i, --interval poll interval in seconds (default: 0.5)
|
|
16
|
+
-l, --lines number of history lines to inspect (integer, default: 1000)
|
|
17
|
+
-h, --help show this help
|
|
18
|
+
USAGE
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
target=""
|
|
22
|
+
pattern=""
|
|
23
|
+
grep_flag="-E"
|
|
24
|
+
timeout=15
|
|
25
|
+
interval=0.5
|
|
26
|
+
lines=1000
|
|
27
|
+
|
|
28
|
+
while [[ $# -gt 0 ]]; do
|
|
29
|
+
case "$1" in
|
|
30
|
+
-t|--target) target="${2-}"; shift 2 ;;
|
|
31
|
+
-p|--pattern) pattern="${2-}"; shift 2 ;;
|
|
32
|
+
-F|--fixed) grep_flag="-F"; shift ;;
|
|
33
|
+
-T|--timeout) timeout="${2-}"; shift 2 ;;
|
|
34
|
+
-i|--interval) interval="${2-}"; shift 2 ;;
|
|
35
|
+
-l|--lines) lines="${2-}"; shift 2 ;;
|
|
36
|
+
-h|--help) usage; exit 0 ;;
|
|
37
|
+
*) echo "Unknown option: $1" >&2; usage; exit 1 ;;
|
|
38
|
+
esac
|
|
39
|
+
done
|
|
40
|
+
|
|
41
|
+
if [[ -z "$target" || -z "$pattern" ]]; then
|
|
42
|
+
echo "target and pattern are required" >&2
|
|
43
|
+
usage
|
|
44
|
+
exit 1
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
if ! [[ "$timeout" =~ ^[0-9]+$ ]]; then
|
|
48
|
+
echo "timeout must be an integer number of seconds" >&2
|
|
49
|
+
exit 1
|
|
50
|
+
fi
|
|
51
|
+
|
|
52
|
+
if ! [[ "$lines" =~ ^[0-9]+$ ]]; then
|
|
53
|
+
echo "lines must be an integer" >&2
|
|
54
|
+
exit 1
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
if ! command -v tmux >/dev/null 2>&1; then
|
|
58
|
+
echo "tmux not found in PATH" >&2
|
|
59
|
+
exit 1
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
# End time in epoch seconds (integer, good enough for polling)
|
|
63
|
+
start_epoch=$(date +%s)
|
|
64
|
+
deadline=$((start_epoch + timeout))
|
|
65
|
+
|
|
66
|
+
while true; do
|
|
67
|
+
# -J joins wrapped lines, -S uses negative index to read last N lines
|
|
68
|
+
pane_text="$(tmux capture-pane -p -J -t "$target" -S "-${lines}" 2>/dev/null || true)"
|
|
69
|
+
|
|
70
|
+
if printf '%s\n' "$pane_text" | grep $grep_flag -- "$pattern" >/dev/null 2>&1; then
|
|
71
|
+
exit 0
|
|
72
|
+
fi
|
|
73
|
+
|
|
74
|
+
now=$(date +%s)
|
|
75
|
+
if (( now >= deadline )); then
|
|
76
|
+
echo "Timed out after ${timeout}s waiting for pattern: $pattern" >&2
|
|
77
|
+
echo "Last ${lines} lines from $target:" >&2
|
|
78
|
+
printf '%s\n' "$pane_text" >&2
|
|
79
|
+
exit 1
|
|
80
|
+
fi
|
|
81
|
+
|
|
82
|
+
sleep "$interval"
|
|
83
|
+
done
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: weather
|
|
3
|
+
description: Get current weather and forecasts (no API key required).
|
|
4
|
+
homepage: https://wttr.in/:help
|
|
5
|
+
metadata: {"nextclaw":{"emoji":"๐ค๏ธ","requires":{"bins":["curl"]}}}
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Weather
|
|
9
|
+
|
|
10
|
+
Two free services, no API keys needed.
|
|
11
|
+
|
|
12
|
+
## wttr.in (primary)
|
|
13
|
+
|
|
14
|
+
Quick one-liner:
|
|
15
|
+
```bash
|
|
16
|
+
curl -s "wttr.in/London?format=3"
|
|
17
|
+
# Output: London: โ
๏ธ +8ยฐC
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Compact format:
|
|
21
|
+
```bash
|
|
22
|
+
curl -s "wttr.in/London?format=%l:+%c+%t+%h+%w"
|
|
23
|
+
# Output: London: โ
๏ธ +8ยฐC 71% โ5km/h
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Full forecast:
|
|
27
|
+
```bash
|
|
28
|
+
curl -s "wttr.in/London?T"
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Format codes: `%c` condition ยท `%t` temp ยท `%h` humidity ยท `%w` wind ยท `%l` location ยท `%m` moon
|
|
32
|
+
|
|
33
|
+
Tips:
|
|
34
|
+
- URL-encode spaces: `wttr.in/New+York`
|
|
35
|
+
- Airport codes: `wttr.in/JFK`
|
|
36
|
+
- Units: `?m` (metric) `?u` (USCS)
|
|
37
|
+
- Today only: `?1` ยท Current only: `?0`
|
|
38
|
+
- PNG: `curl -s "wttr.in/Berlin.png" -o /tmp/weather.png`
|
|
39
|
+
|
|
40
|
+
## Open-Meteo (fallback, JSON)
|
|
41
|
+
|
|
42
|
+
Free, no key, good for programmatic use:
|
|
43
|
+
```bash
|
|
44
|
+
curl -s "https://api.open-meteo.com/v1/forecast?latitude=51.5&longitude=-0.12¤t_weather=true"
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Find coordinates for a city, then query. Returns JSON with temp, windspeed, weathercode.
|
|
48
|
+
|
|
49
|
+
Docs: https://open-meteo.com/en/docs
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// src/agent/context.ts
|
|
2
2
|
import { readFileSync as readFileSync3, existsSync as existsSync4 } from "fs";
|
|
3
3
|
import { join as join3, extname } from "path";
|
|
4
|
-
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
5
4
|
|
|
6
5
|
// src/agent/memory.ts
|
|
7
6
|
import { readFileSync, writeFileSync, existsSync as existsSync2, readdirSync } from "fs";
|
|
@@ -402,7 +401,7 @@ var ContextBuilder = class {
|
|
|
402
401
|
constructor(workspace, contextConfig) {
|
|
403
402
|
this.workspace = workspace;
|
|
404
403
|
this.memory = new MemoryStore(workspace);
|
|
405
|
-
this.skills = new SkillsLoader(workspace
|
|
404
|
+
this.skills = new SkillsLoader(workspace);
|
|
406
405
|
this.contextConfig = {
|
|
407
406
|
bootstrap: {
|
|
408
407
|
...DEFAULT_CONTEXT_CONFIG.bootstrap,
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# nextclaw Skills
|
|
2
|
+
|
|
3
|
+
This directory contains built-in skills that extend nextclaw's capabilities.
|
|
4
|
+
|
|
5
|
+
## Skill Format
|
|
6
|
+
|
|
7
|
+
Each skill is a directory containing a `SKILL.md` file with:
|
|
8
|
+
- YAML frontmatter (name, description, metadata)
|
|
9
|
+
- Markdown instructions for the agent
|
|
10
|
+
|
|
11
|
+
## Attribution
|
|
12
|
+
|
|
13
|
+
These skills are adapted from [OpenClaw](https://github.com/openclaw/openclaw)'s skill system.
|
|
14
|
+
The skill format and metadata structure follow OpenClaw's conventions to maintain compatibility.
|
|
15
|
+
|
|
16
|
+
## Available Skills
|
|
17
|
+
|
|
18
|
+
| Skill | Description |
|
|
19
|
+
|-------|-------------|
|
|
20
|
+
| `github` | Interact with GitHub using the `gh` CLI |
|
|
21
|
+
| `weather` | Get weather info using wttr.in and Open-Meteo |
|
|
22
|
+
| `summarize` | Summarize URLs, files, and YouTube videos |
|
|
23
|
+
| `tmux` | Remote-control tmux sessions |
|
|
24
|
+
| `skill-creator` | Create new skills |
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cron
|
|
3
|
+
description: Schedule reminders and recurring tasks.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Cron
|
|
7
|
+
|
|
8
|
+
Use the `cron` tool to schedule reminders or recurring tasks.
|
|
9
|
+
|
|
10
|
+
## Two Modes
|
|
11
|
+
|
|
12
|
+
1. **Reminder** - message is sent directly to user
|
|
13
|
+
2. **Task** - message is a task description, agent executes and sends result
|
|
14
|
+
|
|
15
|
+
## Examples
|
|
16
|
+
|
|
17
|
+
Fixed reminder:
|
|
18
|
+
```
|
|
19
|
+
cron(action="add", message="Time to take a break!", every_seconds=1200)
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Dynamic task (agent executes each time):
|
|
23
|
+
```
|
|
24
|
+
cron(action="add", message="Check Peiiii/nextclaw GitHub stars and report", every_seconds=600)
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
List/remove:
|
|
28
|
+
```
|
|
29
|
+
cron(action="list")
|
|
30
|
+
cron(action="remove", job_id="abc123")
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Time Expressions
|
|
34
|
+
|
|
35
|
+
| User says | Parameters |
|
|
36
|
+
|-----------|------------|
|
|
37
|
+
| every 20 minutes | every_seconds: 1200 |
|
|
38
|
+
| every hour | every_seconds: 3600 |
|
|
39
|
+
| every day at 8am | cron_expr: "0 8 * * *" |
|
|
40
|
+
| weekdays at 5pm | cron_expr: "0 17 * * 1-5" |
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: github
|
|
3
|
+
description: "Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries."
|
|
4
|
+
metadata: {"nextclaw":{"emoji":"๐","requires":{"bins":["gh"]},"install":[{"id":"brew","kind":"brew","formula":"gh","bins":["gh"],"label":"Install GitHub CLI (brew)"},{"id":"apt","kind":"apt","package":"gh","bins":["gh"],"label":"Install GitHub CLI (apt)"}]}}
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# GitHub Skill
|
|
8
|
+
|
|
9
|
+
Use the `gh` CLI to interact with GitHub. Always specify `--repo owner/repo` when not in a git directory, or use URLs directly.
|
|
10
|
+
|
|
11
|
+
## Pull Requests
|
|
12
|
+
|
|
13
|
+
Check CI status on a PR:
|
|
14
|
+
```bash
|
|
15
|
+
gh pr checks 55 --repo owner/repo
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
List recent workflow runs:
|
|
19
|
+
```bash
|
|
20
|
+
gh run list --repo owner/repo --limit 10
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
View a run and see which steps failed:
|
|
24
|
+
```bash
|
|
25
|
+
gh run view <run-id> --repo owner/repo
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
View logs for failed steps only:
|
|
29
|
+
```bash
|
|
30
|
+
gh run view <run-id> --repo owner/repo --log-failed
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## API for Advanced Queries
|
|
34
|
+
|
|
35
|
+
The `gh api` command is useful for accessing data not available through other subcommands.
|
|
36
|
+
|
|
37
|
+
Get PR with specific fields:
|
|
38
|
+
```bash
|
|
39
|
+
gh api repos/owner/repo/pulls/55 --jq '.title, .state, .user.login'
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## JSON Output
|
|
43
|
+
|
|
44
|
+
Most commands support `--json` for structured output. You can use `--jq` to filter:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
gh issue list --repo owner/repo --json number,title --jq '.[] | "\(.number): \(.title)"'
|
|
48
|
+
```
|