clawtick 1.0.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Abdelhak Akermi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,172 @@
1
+ # ClawTick CLI 🦞
2
+
3
+ > Cloud-powered cron scheduling for [OpenClaw](https://github.com/nicepkg/openclaw). Reliable triggers, real-time monitoring, zero missed jobs.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/clawtick)](https://www.npmjs.com/package/clawtick)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ ## Why ClawTick?
9
+
10
+ OpenClaw's built-in scheduler has known reliability issues — jobs silently fail, timers wedge, and `schedule.kind: 'every'` never fires. ClawTick replaces all of that with cloud infrastructure that works.
11
+
12
+ - Rock-solid cron scheduling
13
+ - Dashboard + CLI to manage everything
14
+ - Multi-channel delivery (WhatsApp, Telegram, Slack, Discord)
15
+ - Execution history and failure tracking
16
+ - Works with your existing OpenClaw gateway
17
+
18
+ ## Install
19
+
20
+ ```bash
21
+ npm install -g clawtick
22
+ ```
23
+
24
+ ## Quick Start
25
+
26
+ ### 1. Get an API key
27
+
28
+ Sign up at [clawtick.com](https://clawtick.com) and generate a key from **Dashboard → API Keys**.
29
+
30
+ ### 2. Login
31
+
32
+ ```bash
33
+ clawtick login --key cp_your_api_key
34
+ ```
35
+
36
+ ### 3. Configure your gateway
37
+
38
+ ```bash
39
+ clawtick gateway set --url http://your-vps:80 --token your_gateway_token
40
+ ```
41
+
42
+ ### 4. Create your first job
43
+
44
+ ```bash
45
+ clawtick job create \
46
+ --cron "0 9 * * *" \
47
+ --message "Good morning! Check my emails" \
48
+ --name "Morning check"
49
+ ```
50
+
51
+ That's it. The job will fire daily at 9 AM UTC.
52
+
53
+ ## Commands
54
+
55
+ ### Authentication
56
+
57
+ ```bash
58
+ clawtick login --key <api-key> # Authenticate
59
+ clawtick logout # Remove credentials
60
+ clawtick whoami # Check connection status
61
+ ```
62
+
63
+ ### Jobs
64
+
65
+ ```bash
66
+ clawtick job list # List all jobs
67
+ clawtick job create [options] # Create a new job
68
+ clawtick job update <id> [options] # Update a job
69
+ clawtick job remove <id> # Delete a job
70
+ clawtick job trigger <id> # Run a job now
71
+ clawtick job enable <id> # Resume a paused job
72
+ clawtick job disable <id> # Pause a job
73
+ ```
74
+
75
+ ### Gateway
76
+
77
+ ```bash
78
+ clawtick gateway set --url <url> --token <token>
79
+ ```
80
+
81
+ ### Account
82
+
83
+ ```bash
84
+ clawtick status # View plan, usage, stats
85
+ ```
86
+
87
+ ## Job Options
88
+
89
+ | Option | Required | Default | Description |
90
+ |--------|----------|---------|-------------|
91
+ | `--cron` | Yes | — | Cron expression (5-field) |
92
+ | `--message` | Yes | — | Message sent to the agent |
93
+ | `--name` | No | Auto | Job display name |
94
+ | `--agent` | No | `main` | Target agent ID |
95
+ | `--channel` | No | — | Delivery channel |
96
+ | `--deliver` | No | `false` | Send agent response to channel |
97
+ | `--reply-to` | No | — | Channel-specific target |
98
+ | `--timezone` | No | `UTC` | IANA timezone |
99
+
100
+ ### Channels
101
+
102
+ | Channel | `--reply-to` value |
103
+ |---------|-------------------|
104
+ | `whatsapp` | Phone number (default chat) |
105
+ | `telegram` | Chat ID |
106
+ | `slack` | Channel name (`#general`) |
107
+ | `discord` | Channel ID |
108
+
109
+ ## Examples
110
+
111
+ ```bash
112
+ # Daily morning briefing to WhatsApp
113
+ clawtick job create \
114
+ --cron "0 9 * * *" \
115
+ --message "Summarize my calendar and top emails" \
116
+ --name "morning-briefing" \
117
+ --agent main \
118
+ --channel whatsapp \
119
+ --deliver
120
+
121
+ # Hourly status check to Telegram
122
+ clawtick job create \
123
+ --cron "0 * * * *" \
124
+ --message "System status check" \
125
+ --name "status-check" \
126
+ --channel telegram \
127
+ --deliver \
128
+ --reply-to 123456789
129
+
130
+ # Weekly report every Monday
131
+ clawtick job create \
132
+ --cron "0 10 * * 1" \
133
+ --message "Generate weekly activity report" \
134
+ --name "weekly-report" \
135
+ --channel slack \
136
+ --deliver \
137
+ --reply-to "#reports"
138
+
139
+ # Health check every 5 minutes (logs only, no delivery)
140
+ clawtick job create \
141
+ --cron "*/5 * * * *" \
142
+ --message "Health check ping" \
143
+ --name "health-check"
144
+ ```
145
+
146
+ ## Plans
147
+
148
+ | | Free | Starter ($9/mo) | Pro ($29/mo) |
149
+ |---|---|---|---|
150
+ | Jobs | 10 | 50 | Unlimited |
151
+ | Triggers/month | 500 | 5,000 | 50,000 |
152
+ | History | 14 days | 30 days | 90 days |
153
+
154
+ Sign up at [clawtick.com](https://clawtick.com) — free plan, no credit card.
155
+
156
+ ## Configuration
157
+
158
+ Config is stored in `~/.clawtick/config.json`. You can also use environment variables:
159
+
160
+ ```bash
161
+ export CLAWPULSE_API_KEY=cp_your_key # Skip login
162
+ ```
163
+
164
+ ## Links
165
+
166
+ - [Dashboard](https://clawtick.com/dashboard)
167
+ - [Documentation](https://clawtick.com/docs)
168
+ - [Issues](https://github.com/clawtick/cli/issues)
169
+
170
+ ## License
171
+
172
+ MIT — see [LICENSE](./LICENSE)
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Clawtick Cloud API Client
3
+ */
4
+ interface Config {
5
+ apiUrl: string;
6
+ apiKey: string;
7
+ }
8
+ export declare function loadConfig(): Config;
9
+ export declare function saveConfig(config: Partial<Config>): void;
10
+ export declare function getConfigPath(): string;
11
+ export declare class ApiClient {
12
+ private apiUrl;
13
+ private apiKey;
14
+ constructor();
15
+ isAuthenticated(): boolean;
16
+ private request;
17
+ listJobs(): Promise<any>;
18
+ createJob(data: {
19
+ name?: string;
20
+ cron: string;
21
+ message: string;
22
+ agent?: string;
23
+ channel?: string;
24
+ deliver?: boolean;
25
+ replyTo?: string;
26
+ timezone?: string;
27
+ }): Promise<any>;
28
+ deleteJob(jobId: string): Promise<any>;
29
+ updateJob(jobId: string, data: any): Promise<any>;
30
+ triggerJob(jobId: string): Promise<any>;
31
+ getStatus(): Promise<any>;
32
+ updateGateway(url: string, token: string): Promise<any>;
33
+ }
34
+ export {};
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Clawtick Cloud API Client
3
+ */
4
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "node:fs";
5
+ import { join } from "node:path";
6
+ import { homedir } from "node:os";
7
+ const CONFIG_DIR = join(homedir(), ".clawtick");
8
+ const CONFIG_FILE = join(CONFIG_DIR, "config.json");
9
+ const DEFAULT_API_URL = "https://api.clawtick.com";
10
+ function ensureConfigDir() {
11
+ if (!existsSync(CONFIG_DIR)) {
12
+ mkdirSync(CONFIG_DIR, { recursive: true });
13
+ }
14
+ }
15
+ export function loadConfig() {
16
+ ensureConfigDir();
17
+ if (!existsSync(CONFIG_FILE)) {
18
+ return { apiUrl: DEFAULT_API_URL, apiKey: "" };
19
+ }
20
+ try {
21
+ return JSON.parse(readFileSync(CONFIG_FILE, "utf-8"));
22
+ }
23
+ catch {
24
+ return { apiUrl: DEFAULT_API_URL, apiKey: "" };
25
+ }
26
+ }
27
+ export function saveConfig(config) {
28
+ ensureConfigDir();
29
+ const current = loadConfig();
30
+ const merged = { ...current, ...config };
31
+ writeFileSync(CONFIG_FILE, JSON.stringify(merged, null, 2));
32
+ }
33
+ export function getConfigPath() {
34
+ return CONFIG_FILE;
35
+ }
36
+ export class ApiClient {
37
+ apiUrl;
38
+ apiKey;
39
+ constructor() {
40
+ const config = loadConfig();
41
+ this.apiUrl = config.apiUrl;
42
+ this.apiKey = config.apiKey;
43
+ }
44
+ isAuthenticated() {
45
+ return !!this.apiKey;
46
+ }
47
+ async request(method, path, body) {
48
+ if (!this.apiKey) {
49
+ throw new Error("Not authenticated. Run: clawtick login");
50
+ }
51
+ const res = await fetch(`${this.apiUrl}${path}`, {
52
+ method,
53
+ headers: {
54
+ "Content-Type": "application/json",
55
+ "Authorization": `Bearer ${this.apiKey}`,
56
+ },
57
+ ...(body ? { body: JSON.stringify(body) } : {}),
58
+ });
59
+ const data = await res.json().catch(() => ({}));
60
+ if (!res.ok) {
61
+ throw new Error(data.error || `API error: ${res.status}`);
62
+ }
63
+ return data;
64
+ }
65
+ // Jobs
66
+ async listJobs() {
67
+ return this.request("GET", "/v1/jobs");
68
+ }
69
+ async createJob(data) {
70
+ return this.request("POST", "/v1/jobs", data);
71
+ }
72
+ async deleteJob(jobId) {
73
+ return this.request("DELETE", `/v1/jobs/${jobId}`);
74
+ }
75
+ async updateJob(jobId, data) {
76
+ return this.request("PUT", `/v1/jobs/${jobId}`, data);
77
+ }
78
+ async triggerJob(jobId) {
79
+ return this.request("POST", `/v1/jobs/${jobId}/trigger`);
80
+ }
81
+ // Status
82
+ async getStatus() {
83
+ return this.request("GET", "/v1/status");
84
+ }
85
+ // Gateway
86
+ async updateGateway(url, token) {
87
+ return this.request("PUT", "/v1/gateway", { url, token });
88
+ }
89
+ }
90
+ //# sourceMappingURL=api-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.js","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Clawtick CLI — Cloud-powered scheduling for OpenClaw
4
+ */
5
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,299 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Clawtick CLI — Cloud-powered scheduling for OpenClaw
4
+ */
5
+ import { Command } from "commander";
6
+ import chalk from "chalk";
7
+ import ora from "ora";
8
+ import { ApiClient, saveConfig, loadConfig, getConfigPath } from "./api-client.js";
9
+ import { validateCronExpression, validateJobName, validateMessage, validateAgentId, } from "./validation.js";
10
+ const program = new Command();
11
+ const api = new ApiClient();
12
+ program
13
+ .name("clawtick")
14
+ .description("🦞 Cloud-powered scheduling for OpenClaw")
15
+ .version("2.0.0");
16
+ // ── Login ──────────────────────────────────────────────
17
+ program
18
+ .command("login")
19
+ .description("Authenticate with your Clawtick API key")
20
+ .option("--key <apiKey>", "API key (or set CLAWPULSE_API_KEY env var)")
21
+ .option("--api-url <url>", "API URL (for self-hosted)")
22
+ .action(async (options) => {
23
+ const apiKey = options.key || process.env.CLAWPULSE_API_KEY;
24
+ if (!apiKey) {
25
+ console.log(chalk.blue("🦞 Clawtick Login\n"));
26
+ console.log("Get your API key from the Clawtick dashboard:");
27
+ console.log(chalk.cyan(" https://clawtick.com/dashboard/api-keys\n"));
28
+ console.log("Then run:");
29
+ console.log(chalk.gray(" clawtick login --key cp_your_api_key_here"));
30
+ console.log(chalk.gray("\nOr set the environment variable:"));
31
+ console.log(chalk.gray(" export CLAWPULSE_API_KEY=cp_your_api_key_here"));
32
+ return;
33
+ }
34
+ const spinner = ora("Authenticating...").start();
35
+ const config = { apiKey };
36
+ if (options.apiUrl)
37
+ config.apiUrl = options.apiUrl;
38
+ saveConfig(config);
39
+ spinner.succeed("Authenticated successfully");
40
+ console.log(chalk.gray(`Config saved to ${getConfigPath()}`));
41
+ });
42
+ // ── Logout ─────────────────────────────────────────────
43
+ program
44
+ .command("logout")
45
+ .description("Remove stored credentials")
46
+ .action(() => {
47
+ saveConfig({ apiKey: "" });
48
+ console.log(chalk.green("✅ Logged out"));
49
+ });
50
+ // ── Whoami ─────────────────────────────────────────────
51
+ program
52
+ .command("whoami")
53
+ .description("Show current authentication status")
54
+ .action(async () => {
55
+ const config = loadConfig();
56
+ if (!config.apiKey) {
57
+ console.log(chalk.yellow("Not authenticated. Run: clawtick login"));
58
+ return;
59
+ }
60
+ console.log(chalk.gray(`API URL: ${config.apiUrl}`));
61
+ console.log(chalk.gray(`API Key: ${config.apiKey.slice(0, 10)}...`));
62
+ const spinner = ora("Checking connection...").start();
63
+ try {
64
+ const status = await api.getStatus();
65
+ spinner.succeed(`Connected — Plan: ${status.plan}`);
66
+ console.log(chalk.gray(`Jobs: ${status.jobs.enabled}/${status.jobs.total}`));
67
+ }
68
+ catch (err) {
69
+ spinner.fail(`API error: ${err.message}`);
70
+ process.exit(1);
71
+ }
72
+ });
73
+ // ── Gateway ────────────────────────────────────────────
74
+ const gateway = program.command("gateway").description("Manage OpenClaw gateway connection");
75
+ gateway
76
+ .command("set")
77
+ .description("Configure your OpenClaw gateway")
78
+ .requiredOption("--url <url>", "Gateway URL (e.g., https://your-vps.com)")
79
+ .requiredOption("--token <token>", "Gateway authentication token")
80
+ .action(async (options) => {
81
+ const spinner = ora("Configuring gateway...").start();
82
+ try {
83
+ await api.updateGateway(options.url, options.token);
84
+ spinner.succeed("Gateway configured");
85
+ console.log(chalk.gray(`URL: ${options.url}`));
86
+ }
87
+ catch (err) {
88
+ spinner.fail(err.message);
89
+ process.exit(1);
90
+ }
91
+ });
92
+ // ── Jobs ───────────────────────────────────────────────
93
+ const job = program.command("job").description("Manage scheduled jobs");
94
+ job
95
+ .command("list")
96
+ .description("List all scheduled jobs")
97
+ .action(async () => {
98
+ const spinner = ora("Fetching jobs...").start();
99
+ try {
100
+ const data = await api.listJobs();
101
+ const jobs = data.jobs || [];
102
+ if (jobs.length === 0) {
103
+ spinner.info("No jobs found. Create one with: clawtick job create");
104
+ return;
105
+ }
106
+ spinner.succeed(`${jobs.length} job(s) found\n`);
107
+ for (const j of jobs) {
108
+ const status = j.enabled ? chalk.green("●") : chalk.gray("○");
109
+ console.log(`${status} ${chalk.bold(j.name)} ${chalk.gray(`(${j.id})`)}`);
110
+ console.log(chalk.gray(` Cron: ${j.cron}`));
111
+ console.log(chalk.gray(` Message: ${j.message}`));
112
+ console.log(chalk.gray(` Agent: ${j.agent || "main"}`));
113
+ console.log(chalk.gray(` Runs: ${j.runCount} success, ${j.failCount} failed`));
114
+ if (j.lastRunAt) {
115
+ console.log(chalk.gray(` Last: ${new Date(j.lastRunAt).toLocaleString()}`));
116
+ }
117
+ console.log();
118
+ }
119
+ }
120
+ catch (err) {
121
+ spinner.fail(err.message);
122
+ process.exit(1);
123
+ }
124
+ });
125
+ job
126
+ .command("create")
127
+ .description("Create a new scheduled job")
128
+ .requiredOption("--cron <expression>", 'Cron expression (e.g., "0 9 * * *")')
129
+ .requiredOption("--message <text>", "Message to send to the agent")
130
+ .option("--name <name>", "Job name")
131
+ .option("--agent <id>", "Agent ID (default: main)")
132
+ .option("--channel <channel>", "Target channel")
133
+ .option("--deliver", "Deliver agent response", false)
134
+ .option("--reply-to <target>", "Delivery target")
135
+ .option("--timezone <tz>", "Timezone (default: UTC)")
136
+ .action(async (options) => {
137
+ // Validate first (no spinner needed for local validation)
138
+ const cronCheck = validateCronExpression(options.cron);
139
+ if (!cronCheck.valid) {
140
+ console.error(chalk.red(`❌ ${cronCheck.error}`));
141
+ process.exit(1);
142
+ }
143
+ const msgCheck = validateMessage(options.message);
144
+ if (!msgCheck.valid) {
145
+ console.error(chalk.red(`❌ ${msgCheck.error}`));
146
+ process.exit(1);
147
+ }
148
+ if (options.name) {
149
+ const nameCheck = validateJobName(options.name);
150
+ if (!nameCheck.valid) {
151
+ console.error(chalk.red(`❌ ${nameCheck.error}`));
152
+ process.exit(1);
153
+ }
154
+ }
155
+ if (options.agent) {
156
+ const agentCheck = validateAgentId(options.agent);
157
+ if (!agentCheck.valid) {
158
+ console.error(chalk.red(`❌ ${agentCheck.error}`));
159
+ process.exit(1);
160
+ }
161
+ }
162
+ const spinner = ora("Creating job...").start();
163
+ try {
164
+ const data = await api.createJob({
165
+ name: options.name,
166
+ cron: options.cron,
167
+ message: options.message,
168
+ agent: options.agent,
169
+ channel: options.channel,
170
+ deliver: options.deliver,
171
+ replyTo: options.replyTo,
172
+ timezone: options.timezone,
173
+ });
174
+ const j = data.job;
175
+ spinner.succeed("Job created");
176
+ console.log(chalk.gray(`ID: ${j.id}`));
177
+ console.log(chalk.gray(`Name: ${j.name}`));
178
+ console.log(chalk.gray(`Cron: ${j.cron}`));
179
+ console.log(chalk.gray(`Message: ${j.message}`));
180
+ console.log(chalk.gray(`Agent: ${j.agent}`));
181
+ }
182
+ catch (err) {
183
+ spinner.fail(err.message);
184
+ process.exit(1);
185
+ }
186
+ });
187
+ job
188
+ .command("remove <jobId>")
189
+ .description("Delete a scheduled job")
190
+ .action(async (jobId) => {
191
+ const spinner = ora("Deleting job...").start();
192
+ try {
193
+ await api.deleteJob(jobId);
194
+ spinner.succeed(`Job deleted: ${jobId}`);
195
+ }
196
+ catch (err) {
197
+ spinner.fail(err.message);
198
+ process.exit(1);
199
+ }
200
+ });
201
+ job
202
+ .command("update <jobId>")
203
+ .description("Update a job")
204
+ .option("--name <name>", "New name")
205
+ .option("--cron <expression>", "New cron expression")
206
+ .option("--message <text>", "New message")
207
+ .option("--enable", "Enable the job")
208
+ .option("--disable", "Disable the job")
209
+ .action(async (jobId, options) => {
210
+ const updates = {};
211
+ if (options.name)
212
+ updates.name = options.name;
213
+ if (options.cron)
214
+ updates.cron = options.cron;
215
+ if (options.message)
216
+ updates.message = options.message;
217
+ if (options.enable)
218
+ updates.enabled = true;
219
+ if (options.disable)
220
+ updates.enabled = false;
221
+ if (Object.keys(updates).length === 0) {
222
+ console.error(chalk.yellow("No updates provided. Use --help for options."));
223
+ return;
224
+ }
225
+ const spinner = ora("Updating job...").start();
226
+ try {
227
+ await api.updateJob(jobId, updates);
228
+ spinner.succeed(`Job updated: ${jobId}`);
229
+ }
230
+ catch (err) {
231
+ spinner.fail(err.message);
232
+ process.exit(1);
233
+ }
234
+ });
235
+ job
236
+ .command("trigger <jobId>")
237
+ .description("Manually trigger a job now")
238
+ .action(async (jobId) => {
239
+ const spinner = ora("Triggering job...").start();
240
+ try {
241
+ await api.triggerJob(jobId);
242
+ spinner.succeed(`Job triggered: ${jobId}`);
243
+ }
244
+ catch (err) {
245
+ spinner.fail(err.message);
246
+ process.exit(1);
247
+ }
248
+ });
249
+ job
250
+ .command("enable <jobId>")
251
+ .description("Enable (resume) a paused job")
252
+ .action(async (jobId) => {
253
+ const spinner = ora("Enabling job...").start();
254
+ try {
255
+ await api.updateJob(jobId, { enabled: true });
256
+ spinner.succeed(`Job enabled: ${jobId}`);
257
+ }
258
+ catch (err) {
259
+ spinner.fail(err.message);
260
+ process.exit(1);
261
+ }
262
+ });
263
+ job
264
+ .command("disable <jobId>")
265
+ .description("Disable (pause) a job")
266
+ .action(async (jobId) => {
267
+ const spinner = ora("Disabling job...").start();
268
+ try {
269
+ await api.updateJob(jobId, { enabled: false });
270
+ spinner.succeed(`Job disabled: ${jobId}`);
271
+ }
272
+ catch (err) {
273
+ spinner.fail(err.message);
274
+ process.exit(1);
275
+ }
276
+ });
277
+ // ── Status ─────────────────────────────────────────────
278
+ program
279
+ .command("status")
280
+ .description("Show account status and stats")
281
+ .action(async () => {
282
+ const spinner = ora("Fetching status...").start();
283
+ try {
284
+ const s = await api.getStatus();
285
+ spinner.succeed("Status loaded\n");
286
+ console.log(chalk.gray(`Plan: ${s.plan}`));
287
+ console.log(chalk.gray(`Jobs: ${s.jobs.enabled} enabled / ${s.jobs.total} total`));
288
+ console.log(chalk.gray(`Total runs: ${s.runs.total}`));
289
+ console.log(chalk.gray(`Success rate: ${s.runs.successRate}%`));
290
+ console.log(chalk.gray(`Last 24h: ${s.last24h.total} runs (${s.last24h.failed} failed)`));
291
+ console.log();
292
+ }
293
+ catch (err) {
294
+ spinner.fail(err.message);
295
+ process.exit(1);
296
+ }
297
+ });
298
+ program.parse();
299
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Clawtick — Cloud-powered scheduling for OpenClaw
3
+ */
4
+ export { ApiClient, loadConfig, saveConfig } from "./api-client.js";
5
+ export { validateCronExpression, validateJobName, validateMessage, validateChannel, validateAgentId, } from "./validation.js";
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Clawtick — Cloud-powered scheduling for OpenClaw
3
+ */
4
+ export { ApiClient, loadConfig, saveConfig } from "./api-client.js";
5
+ export { validateCronExpression, validateJobName, validateMessage, validateChannel, validateAgentId, } from "./validation.js";
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACpE,OAAO,EACH,sBAAsB,EACtB,eAAe,EACf,eAAe,EACf,eAAe,EACf,eAAe,GAClB,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Input validation utilities
3
+ */
4
+ export declare class ValidationError extends Error {
5
+ constructor(message: string);
6
+ }
7
+ /**
8
+ * Validate cron expression (5-field standard format)
9
+ */
10
+ export declare function validateCronExpression(cron: string): {
11
+ valid: boolean;
12
+ error?: string;
13
+ };
14
+ /**
15
+ * Validate job name
16
+ */
17
+ export declare function validateJobName(name: string): {
18
+ valid: boolean;
19
+ error?: string;
20
+ };
21
+ /**
22
+ * Validate message
23
+ */
24
+ export declare function validateMessage(message: string): {
25
+ valid: boolean;
26
+ error?: string;
27
+ };
28
+ /**
29
+ * Validate channel name
30
+ */
31
+ export declare function validateChannel(channel: string): {
32
+ valid: boolean;
33
+ error?: string;
34
+ };
35
+ /**
36
+ * Validate Telegram chat ID
37
+ */
38
+ export declare function validateTelegramChatId(chatId: string): {
39
+ valid: boolean;
40
+ error?: string;
41
+ };
42
+ /**
43
+ * Validate phone number (E.164 format)
44
+ */
45
+ export declare function validatePhoneNumber(phone: string): {
46
+ valid: boolean;
47
+ error?: string;
48
+ };
49
+ /**
50
+ * Validate agent ID
51
+ */
52
+ export declare function validateAgentId(agentId: string): {
53
+ valid: boolean;
54
+ error?: string;
55
+ };
56
+ /**
57
+ * Validate job ID format
58
+ */
59
+ export declare function validateJobId(jobId: string): {
60
+ valid: boolean;
61
+ error?: string;
62
+ };
@@ -0,0 +1,174 @@
1
+ /**
2
+ * Input validation utilities
3
+ */
4
+ export class ValidationError extends Error {
5
+ constructor(message) {
6
+ super(message);
7
+ this.name = 'ValidationError';
8
+ }
9
+ }
10
+ /**
11
+ * Validate cron expression (5-field standard format)
12
+ */
13
+ export function validateCronExpression(cron) {
14
+ if (!cron || typeof cron !== 'string') {
15
+ return { valid: false, error: 'Cron expression is required' };
16
+ }
17
+ const trimmed = cron.trim();
18
+ if (trimmed.length === 0) {
19
+ return { valid: false, error: 'Cron expression cannot be empty' };
20
+ }
21
+ const parts = trimmed.split(/\s+/);
22
+ if (parts.length < 5 || parts.length > 6) {
23
+ return {
24
+ valid: false,
25
+ error: `Invalid cron expression: expected 5 fields, got ${parts.length}\n\nExamples:\n */5 * * * * - Every 5 minutes\n 0 9 * * * - Every day at 9 AM\n 0 9 * * 1-5 - Every weekday at 9 AM\n\nUse https://crontab.guru to build expressions.`
26
+ };
27
+ }
28
+ // Basic field validation
29
+ const fieldPattern = /^(\*|[0-9]+(-[0-9]+)?(\/[0-9]+)?)(,(\*|[0-9]+(-[0-9]+)?(\/[0-9]+)?))*$/;
30
+ for (const part of parts) {
31
+ if (part !== '?' && !fieldPattern.test(part)) {
32
+ return {
33
+ valid: false,
34
+ error: `Invalid cron field: "${part}"\n\nUse https://crontab.guru to build expressions.`
35
+ };
36
+ }
37
+ }
38
+ return { valid: true };
39
+ }
40
+ /**
41
+ * Validate job name
42
+ */
43
+ export function validateJobName(name) {
44
+ if (!name || typeof name !== 'string') {
45
+ return { valid: false, error: 'Job name is required' };
46
+ }
47
+ const trimmed = name.trim();
48
+ if (trimmed.length === 0) {
49
+ return { valid: false, error: 'Job name cannot be empty' };
50
+ }
51
+ if (trimmed.length > 100) {
52
+ return { valid: false, error: 'Job name must be 100 characters or less' };
53
+ }
54
+ // Check for invalid characters
55
+ if (!/^[a-zA-Z0-9\s\-_]+$/.test(trimmed)) {
56
+ return { valid: false, error: 'Job name can only contain letters, numbers, spaces, hyphens, and underscores' };
57
+ }
58
+ return { valid: true };
59
+ }
60
+ /**
61
+ * Validate message
62
+ */
63
+ export function validateMessage(message) {
64
+ if (!message || typeof message !== 'string') {
65
+ return { valid: false, error: 'Message is required' };
66
+ }
67
+ const trimmed = message.trim();
68
+ if (trimmed.length === 0) {
69
+ return { valid: false, error: 'Message cannot be empty' };
70
+ }
71
+ if (trimmed.length > 5000) {
72
+ return { valid: false, error: 'Message must be 5000 characters or less' };
73
+ }
74
+ return { valid: true };
75
+ }
76
+ /**
77
+ * Validate channel name
78
+ */
79
+ export function validateChannel(channel) {
80
+ const validChannels = [
81
+ 'whatsapp',
82
+ 'telegram',
83
+ 'slack',
84
+ 'discord',
85
+ 'signal',
86
+ 'imessage',
87
+ 'googlechat',
88
+ 'mattermost',
89
+ 'matrix',
90
+ 'nostr',
91
+ 'msteams',
92
+ 'line',
93
+ 'zalo',
94
+ 'bluebubbles',
95
+ 'nextcloud-talk'
96
+ ];
97
+ const trimmed = channel.trim().toLowerCase();
98
+ if (!validChannels.includes(trimmed)) {
99
+ return {
100
+ valid: false,
101
+ error: `Invalid channel: ${channel}\n\nValid channels:\n ${validChannels.join(', ')}`
102
+ };
103
+ }
104
+ return { valid: true };
105
+ }
106
+ /**
107
+ * Validate Telegram chat ID
108
+ */
109
+ export function validateTelegramChatId(chatId) {
110
+ if (!chatId || typeof chatId !== 'string') {
111
+ return { valid: false, error: 'Telegram chat ID is required when using Telegram channel' };
112
+ }
113
+ // Telegram chat IDs are numeric (positive or negative)
114
+ if (!/^-?\d+$/.test(chatId.trim())) {
115
+ return {
116
+ valid: false,
117
+ error: 'Invalid Telegram chat ID format. Must be a number.\n\nGet your chat ID from @userinfobot on Telegram.'
118
+ };
119
+ }
120
+ return { valid: true };
121
+ }
122
+ /**
123
+ * Validate phone number (E.164 format)
124
+ */
125
+ export function validatePhoneNumber(phone) {
126
+ if (!phone || typeof phone !== 'string') {
127
+ return { valid: false, error: 'Phone number is required' };
128
+ }
129
+ // E.164 format: +[country code][number] (e.g., +15555551234)
130
+ if (!/^\+[1-9]\d{1,14}$/.test(phone.trim())) {
131
+ return {
132
+ valid: false,
133
+ error: 'Invalid phone number format. Must be in E.164 format (e.g., +15555551234)'
134
+ };
135
+ }
136
+ return { valid: true };
137
+ }
138
+ /**
139
+ * Validate agent ID
140
+ */
141
+ export function validateAgentId(agentId) {
142
+ if (!agentId || typeof agentId !== 'string') {
143
+ return { valid: false, error: 'Agent ID is required' };
144
+ }
145
+ const trimmed = agentId.trim();
146
+ if (trimmed.length === 0) {
147
+ return { valid: false, error: 'Agent ID cannot be empty' };
148
+ }
149
+ if (trimmed.length > 50) {
150
+ return { valid: false, error: 'Agent ID must be 50 characters or less' };
151
+ }
152
+ return { valid: true };
153
+ }
154
+ /**
155
+ * Validate job ID format
156
+ */
157
+ export function validateJobId(jobId) {
158
+ if (!jobId || typeof jobId !== 'string') {
159
+ return { valid: false, error: 'Job ID is required' };
160
+ }
161
+ const trimmed = jobId.trim();
162
+ if (trimmed.length === 0) {
163
+ return { valid: false, error: 'Job ID cannot be empty' };
164
+ }
165
+ // Job IDs are in format: timestamp-randomstring
166
+ if (!/^\d+-[a-z0-9]+$/.test(trimmed)) {
167
+ return {
168
+ valid: false,
169
+ error: 'Invalid job ID format. Use "clawtick list" to see valid job IDs.'
170
+ };
171
+ }
172
+ return { valid: true };
173
+ }
174
+ //# sourceMappingURL=validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "clawtick",
3
+ "version": "1.0.0",
4
+ "description": "Cloud-powered scheduling for OpenClaw — reliable cron, real-time monitoring, zero missed triggers",
5
+ "keywords": [
6
+ "openclaw",
7
+ "cron",
8
+ "scheduler",
9
+ "automation",
10
+ "ai-agents",
11
+ "cloud"
12
+ ],
13
+ "license": "MIT",
14
+ "author": "Abdelhak Akermi",
15
+ "homepage": "https://clawtick.com/docs",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git+https://github.com/Clawtick/cli.git"
19
+ },
20
+ "bugs": {
21
+ "url": "https://github.com/Clawtick/cli/issues"
22
+ },
23
+ "bin": {
24
+ "clawtick": "./dist/cli.js"
25
+ },
26
+ "main": "./dist/index.js",
27
+ "type": "module",
28
+ "scripts": {
29
+ "dev": "tsx src/cli.ts",
30
+ "build": "tsc",
31
+ "test": "vitest --run",
32
+ "start": "node dist/cli.js"
33
+ },
34
+ "dependencies": {
35
+ "chalk": "^5.6.0",
36
+ "commander": "^12.0.0",
37
+ "ora": "^8.2.0"
38
+ },
39
+ "devDependencies": {
40
+ "@types/node": "^22.0.0",
41
+ "tsx": "^4.0.0",
42
+ "typescript": "^5.6.0",
43
+ "vitest": "^4.0.0"
44
+ },
45
+ "engines": {
46
+ "node": ">=18.0.0"
47
+ },
48
+ "files": [
49
+ "dist",
50
+ "LICENSE",
51
+ "README.md"
52
+ ]
53
+ }