openclacky 0.9.18 → 0.9.20
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 +4 -4
- data/.clacky/skills/oss-upload/SKILL.md +47 -0
- data/CHANGELOG.md +34 -0
- data/docs/c-end-user-positioning.md +64 -0
- data/lib/clacky/agent/llm_caller.rb +1 -1
- data/lib/clacky/agent/message_compressor_helper.rb +8 -0
- data/lib/clacky/default_parsers/docx_parser.rb +43 -27
- data/lib/clacky/default_skills/cron-task-creator/SKILL.md +65 -58
- data/lib/clacky/server/channel/adapters/weixin/adapter.rb +112 -13
- data/lib/clacky/server/channel/adapters/weixin/api_client.rb +28 -2
- data/lib/clacky/server/channel/channel_manager.rb +15 -4
- data/lib/clacky/server/http_server.rb +189 -119
- data/lib/clacky/server/scheduler.rb +55 -0
- data/lib/clacky/tools/browser.rb +2 -2
- data/lib/clacky/tools/web_search.rb +206 -63
- data/lib/clacky/ui2/layout_manager.rb +26 -11
- data/lib/clacky/ui2/ui_controller.rb +4 -2
- data/lib/clacky/utils/encoding.rb +21 -0
- data/lib/clacky/utils/environment_detector.rb +9 -6
- data/lib/clacky/utils/file_processor.rb +6 -4
- data/lib/clacky/utils/parser_manager.rb +6 -1
- data/lib/clacky/version.rb +1 -1
- data/lib/clacky/web/app.css +1 -1
- data/lib/clacky/web/tasks.js +10 -26
- data/lib/clacky.rb +10 -0
- data/scripts/install.ps1 +395 -136
- data/scripts/install.sh +13 -12
- data/scripts/install_simple.sh +37 -19
- metadata +3 -5
- data/lib/clacky/default_skills/cron-task-creator/scripts/list_tasks.rb +0 -121
- data/lib/clacky/default_skills/cron-task-creator/scripts/manage_schedule.rb +0 -149
- data/lib/clacky/default_skills/cron-task-creator/scripts/manage_task.rb +0 -81
- data/lib/clacky/default_skills/cron-task-creator/scripts/task_history.rb +0 -137
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 803023a686f9005d8bbed56fa2604d6cb4a426ba2ff1c24ddf6e297242c7faed
|
|
4
|
+
data.tar.gz: ee8738600a36146e4f56b8605a917066746b31e370a41c3e245066ec4e4e961c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b5b27887365a698d193fee92d0672315c48963a9748509cae8a6b5426d0169f16b9fad709afa2232d80542999fc931ee48e09f2cee35100b39273b33c324b558
|
|
7
|
+
data.tar.gz: 5c5572d8a7b34af4eb03220dbf0e566ed0d2ab7b7278a89d8801f0c9ca58b100c90dd27fd17d1548016b21c20e1e458889a97a54983309c409479b863fc8b6ca
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: oss-upload
|
|
3
|
+
description: Upload local files to Tencent COS (oss.1024code.com CDN) using coscli. Use when user wants to upload a file to CDN/OSS, or deploy static assets.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# OSS Upload Skill
|
|
7
|
+
|
|
8
|
+
Upload files to Tencent COS bucket `clackyai-1258723534`, served via `https://oss.1024code.com`.
|
|
9
|
+
|
|
10
|
+
## Tool
|
|
11
|
+
`coscli` — config at `~/.cos.yaml`
|
|
12
|
+
|
|
13
|
+
## Bucket Info
|
|
14
|
+
- Bucket: `clackyai-1258723534`
|
|
15
|
+
- Region: `ap-guangzhou`
|
|
16
|
+
- Endpoint: `cos.ap-guangzhou.myqcloud.com`
|
|
17
|
+
- Public CDN: `https://oss.1024code.com/<path>`
|
|
18
|
+
|
|
19
|
+
## Upload Command
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
coscli cp <local-file> cos://clackyai-1258723534/<remote-path>
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Examples
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# Upload a single file to bucket root
|
|
29
|
+
coscli cp /tmp/wsl.2.6.3.0.arm64.msi cos://clackyai-1258723534/wsl.2.6.3.0.arm64.msi
|
|
30
|
+
|
|
31
|
+
# Upload to a subdirectory
|
|
32
|
+
coscli cp /tmp/install.ps1 cos://clackyai-1258723534/clacky-ai/openclacky/main/scripts/install.ps1
|
|
33
|
+
|
|
34
|
+
# Upload entire directory recursively
|
|
35
|
+
coscli cp /tmp/dist/ cos://clackyai-1258723534/dist/ -r
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Public URL
|
|
39
|
+
After upload, the file is accessible at:
|
|
40
|
+
```
|
|
41
|
+
https://oss.1024code.com/<remote-path>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Steps
|
|
45
|
+
1. Confirm local file exists
|
|
46
|
+
2. Run `coscli cp <local> cos://clackyai-1258723534/<path>`
|
|
47
|
+
3. Return the public URL: `https://oss.1024code.com/<path>`
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,40 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.9.20] - 2026-03-30
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- **SSL error retry**: LLM API calls now automatically retry on SSL errors (same as other network failures — up to 10 retries with 5s delay)
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
- **Brand wrapper not found under root**: the install script now places the brand command wrapper in the same directory as the `openclacky` binary, so it is always on PATH regardless of whether running as root or a normal user
|
|
17
|
+
|
|
18
|
+
### Improved
|
|
19
|
+
- **Cron task management refactored to API**: cron task CRUD operations now go through the HTTP API instead of running ad-hoc Ruby scripts, making the scheduler more reliable and easier to maintain
|
|
20
|
+
- **UTF-8 encoding fix for browser tool on Windows**: browser command output with non-ASCII characters no longer causes encoding errors
|
|
21
|
+
|
|
22
|
+
### More
|
|
23
|
+
- Installer no longer adds `~/.local/bin` to PATH (wrapper now colocated with gem binary, making the extra PATH entry unnecessary)
|
|
24
|
+
- Brand install tips in Windows PowerShell installer
|
|
25
|
+
|
|
26
|
+
## [0.9.19] - 2026-03-29
|
|
27
|
+
|
|
28
|
+
### Added
|
|
29
|
+
- **Bing search engine support**: the web search tool now supports Bing in addition to DuckDuckGo and Baidu — improves search coverage and fallback reliability
|
|
30
|
+
- **WSL1 fallback for Windows installer**: the PowerShell installer now automatically falls back to WSL1 when WSL2/Hyper-V is unavailable, ensuring installation succeeds on older or constrained Windows machines
|
|
31
|
+
- **Upgrade via OSS (CN mirror)**: the upgrade flow now downloads new gem versions from Tencent OSS, making upgrades faster and more reliable for users in China
|
|
32
|
+
|
|
33
|
+
### Fixed
|
|
34
|
+
- **WeChat (Weixin) context token refresh**: the WeChat channel adapter now correctly refreshes the access token when it expires, preventing message delivery failures
|
|
35
|
+
- **DOCX parser UTF-8 encoding bug**: parsing `.docx` files with non-ASCII content no longer causes encoding errors
|
|
36
|
+
- **WSL version detection broadened**: installer now correctly handles old inbox `wsl.exe` (exit code -1) in addition to "feature not enabled" (exit code 1)
|
|
37
|
+
- **Ctrl+C handling in UI**: Ctrl+C now correctly interrupts the current operation without leaving the UI in a broken state
|
|
38
|
+
- **Layout scrollback double-render**: fixed a UI rendering issue that caused the scrollback buffer to render twice
|
|
39
|
+
|
|
40
|
+
### More
|
|
41
|
+
- Support custom brand name in Windows PowerShell installer
|
|
42
|
+
- Redesigned Windows registration flow; removed Win10 MSI dependency
|
|
43
|
+
|
|
10
44
|
## [0.9.18] - 2026-03-28
|
|
11
45
|
|
|
12
46
|
### Fixed
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# C-End User Positioning
|
|
2
|
+
|
|
3
|
+
> Date: 2026-03-30
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Market Context
|
|
8
|
+
|
|
9
|
+
The "OpenClaw ecosystem" has exploded in 2026. Key players:
|
|
10
|
+
|
|
11
|
+
- **OpenClaw** — open-source, self-hosted, community Skills. Designed for technical users who configure everything themselves.
|
|
12
|
+
- **QClaw** — Tencent's fork. Bundled Kimi model, WeChat binding. Mass-market but Tencent-ecosystem only.
|
|
13
|
+
- **Others** (Wukong, etc.) — same lane.
|
|
14
|
+
|
|
15
|
+
OpenClaw has 5,700+ Skills, but almost all are open-source, free, and easily copied. The ecosystem lacks **expertise-backed, production-grade Skills worth paying for**.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Who openclacky Is For
|
|
20
|
+
|
|
21
|
+
**Ordinary users, not technical geeks.**
|
|
22
|
+
|
|
23
|
+
The target user knows OpenClaw exists, has heard about "raising a lobster", but can't or doesn't want to:
|
|
24
|
+
- configure Docker / environment / webhooks
|
|
25
|
+
- manage their own API keys without knowing what they'll spend
|
|
26
|
+
- troubleshoot when a long task breaks halfway
|
|
27
|
+
|
|
28
|
+
They want to use a lobster built by an expert (a lawyer, a trader, an SEO specialist) — not build one themselves.
|
|
29
|
+
|
|
30
|
+
> Core insight: **OpenClaw is built for people who create Skills. openclacky is built for people who use them.**
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Why openclacky Over OpenClaw: 3 Core Reasons
|
|
35
|
+
|
|
36
|
+
### 1. Zero-friction IM setup — the strongest differentiator
|
|
37
|
+
|
|
38
|
+
OpenClaw requires users to manually configure webhooks, tokens, and config files to connect WeChat / Feishu / WeCom. High technical barrier, most ordinary users give up.
|
|
39
|
+
|
|
40
|
+
openclacky uses **AI-automated channel setup**: one sentence, and the AI configures the IM connection for you — no plugins, no docs, no engineering knowledge required. This is a genuine technical moat.
|
|
41
|
+
|
|
42
|
+
### 2. Built for China, natively
|
|
43
|
+
|
|
44
|
+
- No VPN required, no overseas credit card
|
|
45
|
+
- WeChat / Feishu / WeCom are the primary daily tools for Chinese users — openclacky treats them as first-class citizens
|
|
46
|
+
- Supports domestic models (DeepSeek, Kimi, etc.) out of the box
|
|
47
|
+
- QClaw is domestic too, but locked to Tencent's ecosystem and model choices
|
|
48
|
+
|
|
49
|
+
### 3. Cost transparency and long-task reliability
|
|
50
|
+
|
|
51
|
+
- Real-time token cost tracking — users always know what they're spending
|
|
52
|
+
- Automatic compression (up to 90% savings via Insert-then-Compress + Prompt Caching)
|
|
53
|
+
- Long tasks don't break: sub-agent isolation + Time Machine architecture keeps context intact
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## The User Progression
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
Can use it → Dare to use it → Keep using it
|
|
61
|
+
(zero setup) (cost clarity) (tasks don't break)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Each of the 3 reasons maps directly to one stage of this progression.
|
|
@@ -34,7 +34,7 @@ module Clacky
|
|
|
34
34
|
max_tokens: @config.max_tokens,
|
|
35
35
|
enable_caching: @config.enable_prompt_caching
|
|
36
36
|
)
|
|
37
|
-
rescue Faraday::ConnectionFailed, Faraday::TimeoutError, Errno::ECONNREFUSED, Errno::ETIMEDOUT => e
|
|
37
|
+
rescue Faraday::ConnectionFailed, Faraday::TimeoutError, Faraday::SSLError, Errno::ECONNREFUSED, Errno::ETIMEDOUT => e
|
|
38
38
|
@ui&.clear_progress
|
|
39
39
|
retries += 1
|
|
40
40
|
if retries <= max_retries
|
|
@@ -20,6 +20,14 @@ module Clacky
|
|
|
20
20
|
@ui&.show_idle_status(phase: :start, message: "Idle detected. Compressing conversation to optimize costs...")
|
|
21
21
|
if compression_context.nil?
|
|
22
22
|
@ui&.show_idle_status(phase: :end, message: "Idle skipped.")
|
|
23
|
+
Clacky::Logger.info(
|
|
24
|
+
"Idle compression skipped",
|
|
25
|
+
enable_compression: @config.enable_compression,
|
|
26
|
+
previous_total_tokens: @previous_total_tokens,
|
|
27
|
+
history_size: @history.size,
|
|
28
|
+
idle_threshold: IDLE_COMPRESSION_THRESHOLD,
|
|
29
|
+
max_recent_messages: MAX_RECENT_MESSAGES
|
|
30
|
+
)
|
|
23
31
|
return false
|
|
24
32
|
end
|
|
25
33
|
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
2
|
# frozen_string_literal: true
|
|
3
|
+
# encoding: utf-8
|
|
4
|
+
|
|
5
|
+
Encoding.default_external = Encoding::UTF_8
|
|
6
|
+
Encoding.default_internal = Encoding::UTF_8
|
|
7
|
+
|
|
3
8
|
#
|
|
4
9
|
# Clacky DOCX Parser — CLI interface
|
|
5
10
|
#
|
|
@@ -22,30 +27,43 @@ require "zip"
|
|
|
22
27
|
require "rexml/document"
|
|
23
28
|
require "stringio"
|
|
24
29
|
|
|
25
|
-
def
|
|
30
|
+
def safe_utf8(str)
|
|
31
|
+
# First try force_encoding (lossless, for content that IS valid UTF-8)
|
|
32
|
+
utf8 = str.dup.force_encoding("UTF-8")
|
|
33
|
+
return utf8 if utf8.valid_encoding?
|
|
34
|
+
# Fallback: transcode with replacement for genuinely invalid bytes
|
|
35
|
+
str.encode("UTF-8", "binary", invalid: :replace, undef: :replace, replace: "")
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def read_zip_entry(body, name)
|
|
39
|
+
xml = nil
|
|
26
40
|
Zip::File.open_buffer(StringIO.new(body)) do |zip|
|
|
27
|
-
entry = zip.find_entry(
|
|
28
|
-
|
|
29
|
-
entry.get_input_stream.read
|
|
41
|
+
entry = zip.find_entry(name)
|
|
42
|
+
xml = safe_utf8(entry.get_input_stream.read) if entry
|
|
30
43
|
end
|
|
44
|
+
xml
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def read_document_xml(body)
|
|
48
|
+
xml = read_zip_entry(body, "word/document.xml")
|
|
49
|
+
raise "Could not extract content — possibly encrypted or invalid format" unless xml
|
|
50
|
+
xml
|
|
31
51
|
end
|
|
32
52
|
|
|
33
53
|
def read_numbering(body)
|
|
34
54
|
result = {}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
levels[ilvl] = { fmt: fmt || "bullet" }
|
|
46
|
-
end
|
|
47
|
-
result[id] = levels
|
|
55
|
+
xml = read_zip_entry(body, "word/numbering.xml")
|
|
56
|
+
return result unless xml
|
|
57
|
+
doc = REXML::Document.new(xml)
|
|
58
|
+
REXML::XPath.each(doc, "//w:abstractNum") do |an|
|
|
59
|
+
id = an.attributes["w:abstractNumId"]
|
|
60
|
+
levels = {}
|
|
61
|
+
REXML::XPath.each(an, "w:lvl") do |lvl|
|
|
62
|
+
ilvl = lvl.attributes["w:ilvl"].to_i
|
|
63
|
+
fmt = REXML::XPath.first(lvl, "w:numFmt")&.attributes&.[]("w:val")
|
|
64
|
+
levels[ilvl] = { fmt: fmt || "bullet" }
|
|
48
65
|
end
|
|
66
|
+
result[id] = levels
|
|
49
67
|
end
|
|
50
68
|
result
|
|
51
69
|
rescue
|
|
@@ -54,16 +72,14 @@ end
|
|
|
54
72
|
|
|
55
73
|
def read_styles(body)
|
|
56
74
|
result = {}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
result[sid] = { heading: $1.to_i }
|
|
66
|
-
end
|
|
75
|
+
xml = read_zip_entry(body, "word/styles.xml")
|
|
76
|
+
return result unless xml
|
|
77
|
+
doc = REXML::Document.new(xml)
|
|
78
|
+
REXML::XPath.each(doc, "//w:style") do |s|
|
|
79
|
+
sid = s.attributes["w:styleId"]
|
|
80
|
+
name = REXML::XPath.first(s, "w:name")&.attributes&.[]("w:val").to_s
|
|
81
|
+
if name =~ /^heading (\d)/i
|
|
82
|
+
result[sid] = { heading: $1.to_i }
|
|
67
83
|
end
|
|
68
84
|
end
|
|
69
85
|
result
|
|
@@ -17,21 +17,14 @@ Storage:
|
|
|
17
17
|
~/.clacky/schedules.yml # All scheduled plans (YAML list)
|
|
18
18
|
~/.clacky/logger/clacky-*.log # Execution logs (daily rotation)
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
POST /api/tasks → create task {name, content}
|
|
29
|
-
GET /api/tasks/:name → get task content
|
|
30
|
-
DELETE /api/tasks/:name → delete task
|
|
31
|
-
POST /api/tasks/run → run immediately {name}
|
|
32
|
-
GET /api/schedules → list all schedules
|
|
33
|
-
POST /api/schedules → create schedule {name, task, cron}
|
|
34
|
-
DELETE /api/schedules/:name → delete schedule
|
|
20
|
+
API Base: http://${CLACKY_SERVER_HOST}:${CLACKY_SERVER_PORT}
|
|
21
|
+
|
|
22
|
+
Cron-Tasks API (unified — manages task file + schedule together):
|
|
23
|
+
GET /api/cron-tasks → list all cron tasks with schedule info
|
|
24
|
+
POST /api/cron-tasks → create task + schedule {name, content, cron, enabled?}
|
|
25
|
+
PATCH /api/cron-tasks/:name → update {content?, cron?, enabled?}
|
|
26
|
+
DELETE /api/cron-tasks/:name → delete task file + schedule
|
|
27
|
+
POST /api/cron-tasks/:name/run → execute immediately (creates a new session)
|
|
35
28
|
```
|
|
36
29
|
|
|
37
30
|
## Cron Expression Quick Reference
|
|
@@ -54,10 +47,11 @@ Field order: `minute hour day-of-month month day-of-week`
|
|
|
54
47
|
|
|
55
48
|
### 1. LIST — Show all tasks
|
|
56
49
|
|
|
57
|
-
|
|
50
|
+
```bash
|
|
51
|
+
curl -s http://${CLACKY_SERVER_HOST}:${CLACKY_SERVER_PORT}/api/cron-tasks
|
|
52
|
+
```
|
|
58
53
|
|
|
59
|
-
|
|
60
|
-
2. Display results: task name, cron schedule, enabled status, last run status
|
|
54
|
+
Display each task: name, cron schedule, enabled status, content preview.
|
|
61
55
|
|
|
62
56
|
If no tasks exist, inform the user and offer to create one or show templates.
|
|
63
57
|
|
|
@@ -69,15 +63,14 @@ If no tasks exist, inform the user and offer to create one or show templates.
|
|
|
69
63
|
|
|
70
64
|
**Step 1: Gather required info** (only ask for what's missing)
|
|
71
65
|
- What should the task DO? (goal, behavior, output format)
|
|
72
|
-
- How often should it run? (or is it manual-only?)
|
|
66
|
+
- How often should it run? (or is it manual-only without a schedule?)
|
|
73
67
|
- Any specific parameters? (URLs, file paths, output location, language)
|
|
74
68
|
|
|
75
69
|
**Step 2: Generate task name**
|
|
76
70
|
- Rule: only `[a-z0-9_-]`, lowercase, no spaces
|
|
77
71
|
- Examples: `daily_report`, `price_monitor`, `weekly_summary`
|
|
78
72
|
|
|
79
|
-
**Step 3: Write the task prompt
|
|
80
|
-
Path: `~/.clacky/tasks/<name>.md`
|
|
73
|
+
**Step 3: Write the task prompt**
|
|
81
74
|
|
|
82
75
|
The prompt must be:
|
|
83
76
|
- **Self-contained**: the agent running it has zero prior context — include everything needed
|
|
@@ -85,7 +78,7 @@ The prompt must be:
|
|
|
85
78
|
- **Detailed**: include URLs, file paths, output format, language, expected output location
|
|
86
79
|
|
|
87
80
|
Good task prompt example:
|
|
88
|
-
```
|
|
81
|
+
```
|
|
89
82
|
You are a price monitoring assistant. Complete the following task:
|
|
90
83
|
|
|
91
84
|
## Goal
|
|
@@ -100,14 +93,17 @@ Check the current BTC price on CoinGecko, compare with yesterday's price, and lo
|
|
|
100
93
|
Execute immediately.
|
|
101
94
|
```
|
|
102
95
|
|
|
103
|
-
**Step 4:
|
|
96
|
+
**Step 4: Create via API**
|
|
104
97
|
|
|
105
98
|
```bash
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
99
|
+
curl -s -X POST http://${CLACKY_SERVER_HOST}:${CLACKY_SERVER_PORT}/api/cron-tasks \
|
|
100
|
+
-H "Content-Type: application/json" \
|
|
101
|
+
-d '{
|
|
102
|
+
"name": "task_name",
|
|
103
|
+
"content": "task prompt content...",
|
|
104
|
+
"cron": "0 9 * * *",
|
|
105
|
+
"enabled": true
|
|
106
|
+
}'
|
|
111
107
|
```
|
|
112
108
|
|
|
113
109
|
**Step 5: Confirm creation**
|
|
@@ -116,7 +112,6 @@ ruby ~/.clacky/skills/cron-task-creator/scripts/manage_schedule.rb add "<name>"
|
|
|
116
112
|
✅ Task created successfully!
|
|
117
113
|
|
|
118
114
|
📋 Task name: daily_standup
|
|
119
|
-
📄 File: ~/.clacky/tasks/daily_standup.md
|
|
120
115
|
⏰ Schedule: Weekdays at 09:00 (cron: 0 9 * * 1-5)
|
|
121
116
|
|
|
122
117
|
View and manage this task in the Clacky WebUI → Tasks panel. Click ▶ Run to execute immediately.
|
|
@@ -126,24 +121,27 @@ View and manage this task in the Clacky WebUI → Tasks panel. Click ▶ Run to
|
|
|
126
121
|
|
|
127
122
|
### 3. EDIT — Modify an existing task
|
|
128
123
|
|
|
129
|
-
|
|
124
|
+
**Step 1**: Identify the task (if unclear, LIST first and ask)
|
|
130
125
|
|
|
131
|
-
**Step
|
|
126
|
+
**Step 2**: Show current state via LIST or ask user to confirm
|
|
132
127
|
|
|
133
|
-
**Step
|
|
134
|
-
|
|
135
|
-
**Step 3**: Determine what to change
|
|
136
|
-
- Prompt only → rewrite `~/.clacky/tasks/<name>.md`
|
|
137
|
-
- Schedule only → update `cron` field in `schedules.yml`
|
|
138
|
-
- Both → do both
|
|
139
|
-
- Rename → rename .md file + update schedules.yml
|
|
128
|
+
**Step 3**: Update via API
|
|
140
129
|
|
|
141
130
|
```bash
|
|
142
|
-
# Update
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
131
|
+
# Update content only
|
|
132
|
+
curl -s -X PATCH http://${CLACKY_SERVER_HOST}:${CLACKY_SERVER_PORT}/api/cron-tasks/task_name \
|
|
133
|
+
-H "Content-Type: application/json" \
|
|
134
|
+
-d '{"content": "new prompt content..."}'
|
|
135
|
+
|
|
136
|
+
# Update cron schedule only
|
|
137
|
+
curl -s -X PATCH http://${CLACKY_SERVER_HOST}:${CLACKY_SERVER_PORT}/api/cron-tasks/task_name \
|
|
138
|
+
-H "Content-Type: application/json" \
|
|
139
|
+
-d '{"cron": "0 8 * * 1-5"}'
|
|
140
|
+
|
|
141
|
+
# Update both
|
|
142
|
+
curl -s -X PATCH http://${CLACKY_SERVER_HOST}:${CLACKY_SERVER_PORT}/api/cron-tasks/task_name \
|
|
143
|
+
-H "Content-Type: application/json" \
|
|
144
|
+
-d '{"content": "...", "cron": "0 8 * * 1-5"}'
|
|
147
145
|
```
|
|
148
146
|
|
|
149
147
|
**Step 4**: Confirm changes
|
|
@@ -151,7 +149,6 @@ ruby ~/.clacky/skills/cron-task-creator/scripts/manage_schedule.rb update "<sche
|
|
|
151
149
|
```
|
|
152
150
|
✅ Task updated!
|
|
153
151
|
📋 daily_standup
|
|
154
|
-
Prompt: updated ✓
|
|
155
152
|
Schedule: 0 9 * * 1-5 → 0 8 * * 1-5 (now weekdays at 08:00)
|
|
156
153
|
```
|
|
157
154
|
|
|
@@ -160,7 +157,15 @@ ruby ~/.clacky/skills/cron-task-creator/scripts/manage_schedule.rb update "<sche
|
|
|
160
157
|
### 4. ENABLE / DISABLE — Toggle a task
|
|
161
158
|
|
|
162
159
|
```bash
|
|
163
|
-
|
|
160
|
+
# Disable
|
|
161
|
+
curl -s -X PATCH http://${CLACKY_SERVER_HOST}:${CLACKY_SERVER_PORT}/api/cron-tasks/task_name \
|
|
162
|
+
-H "Content-Type: application/json" \
|
|
163
|
+
-d '{"enabled": false}'
|
|
164
|
+
|
|
165
|
+
# Enable
|
|
166
|
+
curl -s -X PATCH http://${CLACKY_SERVER_HOST}:${CLACKY_SERVER_PORT}/api/cron-tasks/task_name \
|
|
167
|
+
-H "Content-Type: application/json" \
|
|
168
|
+
-d '{"enabled": true}'
|
|
164
169
|
```
|
|
165
170
|
|
|
166
171
|
Confirm:
|
|
@@ -180,15 +185,22 @@ Always confirm before deleting (unless the user has explicitly said to delete):
|
|
|
180
185
|
```
|
|
181
186
|
|
|
182
187
|
```bash
|
|
183
|
-
|
|
188
|
+
curl -s -X DELETE http://${CLACKY_SERVER_HOST}:${CLACKY_SERVER_PORT}/api/cron-tasks/task_name
|
|
184
189
|
```
|
|
185
190
|
|
|
186
191
|
---
|
|
187
192
|
|
|
188
193
|
### 6. HISTORY — View run history
|
|
189
194
|
|
|
195
|
+
Read the daily log files directly:
|
|
196
|
+
|
|
190
197
|
```bash
|
|
191
|
-
|
|
198
|
+
grep "task_name" ~/.clacky/logger/clacky-$(date +%Y-%m-%d).log | tail -20
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Or search across recent days:
|
|
202
|
+
```bash
|
|
203
|
+
grep -h "task_name" ~/.clacky/logger/clacky-*.log | tail -30
|
|
192
204
|
```
|
|
193
205
|
|
|
194
206
|
Display format:
|
|
@@ -198,24 +210,21 @@ Display format:
|
|
|
198
210
|
Mar 10 19:00 ❌ Failed — JSON::ParserError: unexpected end of input
|
|
199
211
|
Mar 09 19:00 ✅ Success — took 1m 42s
|
|
200
212
|
Mar 08 19:00 ✅ Success — took 2m 10s
|
|
201
|
-
Mar 07 19:00 ⚠️ Skipped — (task was disabled)
|
|
202
|
-
|
|
203
|
-
Recent error:
|
|
204
|
-
JSON::ParserError at line 226
|
|
205
|
-
Possible cause: API response was truncated or empty
|
|
206
213
|
```
|
|
207
214
|
|
|
208
215
|
---
|
|
209
216
|
|
|
210
217
|
### 7. RUN NOW — Execute immediately
|
|
211
218
|
|
|
219
|
+
```bash
|
|
220
|
+
curl -s -X POST http://${CLACKY_SERVER_HOST}:${CLACKY_SERVER_PORT}/api/cron-tasks/task_name/run
|
|
212
221
|
```
|
|
213
|
-
▶️ Go to the Clacky WebUI → Tasks panel, find the task, and click ▶ Run.
|
|
214
222
|
|
|
215
|
-
|
|
223
|
+
This creates a new session. Tell the user:
|
|
224
|
+
```
|
|
225
|
+
▶️ Task started in a new session.
|
|
226
|
+
View it in the Clacky WebUI → Sessions panel.
|
|
216
227
|
```
|
|
217
|
-
|
|
218
|
-
If the user wants to run the task in the current session, read the task file and execute the instructions directly.
|
|
219
228
|
|
|
220
229
|
---
|
|
221
230
|
|
|
@@ -243,8 +252,6 @@ Tell me which one interests you, or describe your own use case!
|
|
|
243
252
|
## Important Notes
|
|
244
253
|
|
|
245
254
|
- Task names: only `[a-z0-9_-]`, no spaces, no uppercase
|
|
246
|
-
- When modifying `schedules.yml`: always read → modify → write back the full file (never append directly)
|
|
247
255
|
- Task prompt files must be **self-contained** — the executing agent has no prior memory
|
|
248
256
|
- Clacky server must be running for cron to trigger automatically (checked every minute)
|
|
249
257
|
- The WebUI Task Panel is the preferred interface for managing tasks — always remind the user to check it after changes
|
|
250
|
-
- Path expansion: always use absolute paths, expand `~` to the actual home directory
|