@wonsukchoi/crondex 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.
- package/LICENSE +21 -0
- package/README.md +130 -0
- package/bin/crondex.js +103 -0
- package/catalog.json +263 -0
- package/jobs/devops/backup-reminder.yaml +26 -0
- package/jobs/devops/cost-alert.yaml +46 -0
- package/jobs/devops/dependency-audit.yaml +39 -0
- package/jobs/devops/log-cleanup.yaml +26 -0
- package/jobs/devops/repo-health-check.yaml +42 -0
- package/jobs/devops/ssl-cert-expiry-check.yaml +33 -0
- package/jobs/devops/uptime-ping-check.yaml +26 -0
- package/jobs/productivity/daily-standup-summary.yaml +38 -0
- package/jobs/productivity/inbox-triage.yaml +32 -0
- package/jobs/productivity/weekly-report.yaml +39 -0
- package/package.json +41 -0
- package/schema/job.schema.json +86 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 wonsukchoi
|
|
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,130 @@
|
|
|
1
|
+
# crondex
|
|
2
|
+
|
|
3
|
+
A public, growing directory of pre-made cron jobs — built so any AI agent
|
|
4
|
+
(Claude, Codex, Hermes, OpenClaw, or a plain LLM with shell access) can pull
|
|
5
|
+
one, tweak it, and schedule it. Clone it, grab a job, adjust the knobs, run it.
|
|
6
|
+
|
|
7
|
+
## Quick start
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
git clone https://github.com/wonsukchoi/crondex.git
|
|
11
|
+
cat crondex/catalog.json # browse what's available
|
|
12
|
+
cat crondex/jobs/devops/dependency-audit.yaml # read one job
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Give an agent the repo and a goal ("set up something that checks my repo
|
|
16
|
+
health every morning") — it reads `catalog.json`, finds the closest match,
|
|
17
|
+
adjusts `schedule`/`variables`, and wires it into whatever scheduler it has.
|
|
18
|
+
|
|
19
|
+
## CLI
|
|
20
|
+
|
|
21
|
+
Not yet published to the npm registry, so `npx crondex` doesn't resolve
|
|
22
|
+
publicly yet — for now, run it from a clone:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
git clone https://github.com/wonsukchoi/crondex.git && cd crondex
|
|
26
|
+
node bin/crondex.js list # browse everything
|
|
27
|
+
node bin/crondex.js list --category devops # filter by category or --tag
|
|
28
|
+
node bin/crondex.js show backup-reminder # print one job's YAML
|
|
29
|
+
node bin/crondex.js add backup-reminder --dest ./cron/backup-reminder.yaml
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
`add` copies the job's YAML as-is into your project — it's yours to edit
|
|
33
|
+
from there, same as a `git clone` + copy, just one command. Once this is
|
|
34
|
+
published, the same commands work via `npx crondex ...` with no clone
|
|
35
|
+
needed.
|
|
36
|
+
|
|
37
|
+
## Layout
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
crondex/
|
|
41
|
+
├── bin/crondex.js CLI: list / show / add
|
|
42
|
+
├── catalog.json generated index of every job — read this first
|
|
43
|
+
├── schema/job.schema.json spec every job file follows
|
|
44
|
+
├── jobs/
|
|
45
|
+
│ ├── devops/
|
|
46
|
+
│ └── productivity/
|
|
47
|
+
└── scripts/
|
|
48
|
+
├── build-catalog.js regenerates catalog.json from jobs/**/*.yaml
|
|
49
|
+
└── validate-jobs.js validates every job against the schema
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Available jobs
|
|
53
|
+
|
|
54
|
+
| id | category | schedule | modes |
|
|
55
|
+
|---|---|---|---|
|
|
56
|
+
| `dependency-audit` | devops | `0 8 * * 1` | script + agent-prompt |
|
|
57
|
+
| `log-cleanup` | devops | `30 3 * * *` | script |
|
|
58
|
+
| `repo-health-check` | devops | `0 9 * * 1-5` | script + agent-prompt |
|
|
59
|
+
| `backup-reminder` | devops | `0 9 * * *` | script |
|
|
60
|
+
| `ssl-cert-expiry-check` | devops | `0 6 * * *` | script |
|
|
61
|
+
| `uptime-ping-check` | devops | `*/15 * * * *` | script |
|
|
62
|
+
| `cost-alert` | devops | `0 7 * * *` | script + agent-prompt |
|
|
63
|
+
| `daily-standup-summary` | productivity | `0 8 * * 1-5` | script + agent-prompt |
|
|
64
|
+
| `inbox-triage` | productivity | `0 7,13 * * 1-5` | agent-prompt only |
|
|
65
|
+
| `weekly-report` | productivity | `0 16 * * 5` | script + agent-prompt |
|
|
66
|
+
|
|
67
|
+
Full details (description, tags, variables) live in `catalog.json` and each
|
|
68
|
+
job's YAML file.
|
|
69
|
+
|
|
70
|
+
## How a job works
|
|
71
|
+
|
|
72
|
+
Every job is one YAML file with a `runner`:
|
|
73
|
+
|
|
74
|
+
- **`shell`** — run `command` directly. Zero LLM tokens, deterministic, no
|
|
75
|
+
judgment calls.
|
|
76
|
+
- **`agent-prompt`** — hand the `prompt` field to an LLM agent each run.
|
|
77
|
+
Costs tokens, but can synthesize, prioritize, and draft prose.
|
|
78
|
+
- **`hybrid`** — ships both. You (or your agent) pick per run: `command` to
|
|
79
|
+
save tokens and get raw data, or `prompt` when you want the LLM to
|
|
80
|
+
interpret it. `script_note` on the job explains exactly what you trade
|
|
81
|
+
away by choosing the script.
|
|
82
|
+
|
|
83
|
+
`{{placeholders}}` in `command`/`prompt` resolve from `variables`. Each job
|
|
84
|
+
also carries a `version` — bumped whenever `prompt`/`command` behavior
|
|
85
|
+
changes, so if you've already scheduled a job elsewhere you can tell when
|
|
86
|
+
the upstream copy has moved on without you.
|
|
87
|
+
|
|
88
|
+
```yaml
|
|
89
|
+
id: dependency-audit
|
|
90
|
+
version: 1
|
|
91
|
+
name: Dependency Vulnerability Audit
|
|
92
|
+
description: ...
|
|
93
|
+
category: devops
|
|
94
|
+
tags: [security, dependencies]
|
|
95
|
+
schedule: "0 8 * * 1" # standard 5-field cron
|
|
96
|
+
timezone: "UTC"
|
|
97
|
+
runner: hybrid
|
|
98
|
+
command: |
|
|
99
|
+
...raw shell audit, zero tokens...
|
|
100
|
+
prompt: |
|
|
101
|
+
...instructions with {{repo_path}}, LLM synthesizes+prioritizes...
|
|
102
|
+
script_note: what you lose by using `command` instead of `prompt`
|
|
103
|
+
variables:
|
|
104
|
+
repo_path:
|
|
105
|
+
default: "."
|
|
106
|
+
description: ...
|
|
107
|
+
compatible_agents: [claude, codex, hermes, openclaw, generic]
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Full spec: [`schema/job.schema.json`](schema/job.schema.json).
|
|
111
|
+
|
|
112
|
+
## Using a job
|
|
113
|
+
|
|
114
|
+
1. Pick a job from `catalog.json` — check `modes` to see if it's script-only,
|
|
115
|
+
agent-prompt-only, or both.
|
|
116
|
+
2. Decide script vs. agent-prompt if the job is `hybrid`: script saves
|
|
117
|
+
tokens, agent-prompt gives you more detail/judgment (see `script_note`).
|
|
118
|
+
3. Override any `variables` and `schedule` for your case.
|
|
119
|
+
4. Hand `command` or `prompt` plus `schedule` to your scheduler — system
|
|
120
|
+
crontab, a hosted cron, or your agent's own scheduling mechanism. This
|
|
121
|
+
repo defines *what* to run and *when*, not the executor.
|
|
122
|
+
|
|
123
|
+
## Contributing a job
|
|
124
|
+
|
|
125
|
+
See [`CONTRIBUTING.md`](CONTRIBUTING.md) — copy `templates/job.template.yaml`,
|
|
126
|
+
fill it in, `npm run validate && npm run build-catalog`, open a PR.
|
|
127
|
+
|
|
128
|
+
## License
|
|
129
|
+
|
|
130
|
+
[MIT](LICENSE)
|
package/bin/crondex.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// CLI over catalog.json — browse jobs, read one, or pull one into your project.
|
|
3
|
+
import { readFileSync, writeFileSync, existsSync } from "node:fs";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
|
|
6
|
+
const ROOT = new URL("..", import.meta.url).pathname;
|
|
7
|
+
const CATALOG = JSON.parse(readFileSync(join(ROOT, "catalog.json"), "utf8"));
|
|
8
|
+
const PKG = JSON.parse(readFileSync(join(ROOT, "package.json"), "utf8"));
|
|
9
|
+
|
|
10
|
+
const [, , cmd, ...args] = process.argv;
|
|
11
|
+
|
|
12
|
+
function flag(name) {
|
|
13
|
+
const i = args.indexOf(`--${name}`);
|
|
14
|
+
return i === -1 ? undefined : args[i + 1];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function findJob(id) {
|
|
18
|
+
const meta = CATALOG.jobs.find((j) => j.id === id);
|
|
19
|
+
if (!meta) {
|
|
20
|
+
console.error(`no job named "${id}". Run "crondex list" to see options.`);
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
return meta;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function printHelp() {
|
|
27
|
+
console.log(`crondex — browse and pull pre-made cron jobs
|
|
28
|
+
|
|
29
|
+
Usage:
|
|
30
|
+
crondex list [--category <name>] [--tag <name>]
|
|
31
|
+
crondex show <id>
|
|
32
|
+
crondex add <id> [--dest <path>]
|
|
33
|
+
|
|
34
|
+
Examples:
|
|
35
|
+
crondex list --category devops
|
|
36
|
+
crondex show dependency-audit
|
|
37
|
+
crondex add backup-reminder --dest ./cron/backup-reminder.yaml
|
|
38
|
+
`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function catalogInfoLine() {
|
|
42
|
+
const viaNpx = process.env.npm_command === "exec";
|
|
43
|
+
const freshness = viaNpx
|
|
44
|
+
? "running via npx — you're always on the latest catalog."
|
|
45
|
+
: "running from a local/global install — run `npm update -g crondex` (or re-pull) if new jobs seem missing.";
|
|
46
|
+
return `crondex v${PKG.version} — ${CATALOG.count} jobs. ${freshness}`;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function list() {
|
|
50
|
+
const category = flag("category");
|
|
51
|
+
const tag = flag("tag");
|
|
52
|
+
const jobs = CATALOG.jobs.filter(
|
|
53
|
+
(j) => (!category || j.category === category) && (!tag || j.tags.includes(tag))
|
|
54
|
+
);
|
|
55
|
+
console.log(catalogInfoLine());
|
|
56
|
+
console.log();
|
|
57
|
+
if (!jobs.length) {
|
|
58
|
+
console.log("no jobs matched.");
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
for (const j of jobs) {
|
|
62
|
+
console.log(`${j.id} [${j.category}] (${j.modes.join(", ")})`);
|
|
63
|
+
console.log(` ${j.description}`);
|
|
64
|
+
console.log();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function show(id) {
|
|
69
|
+
console.log(readFileSync(join(ROOT, findJob(id).path), "utf8"));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function add(id) {
|
|
73
|
+
const meta = findJob(id);
|
|
74
|
+
const dest = flag("dest") ?? `./${id}.yaml`;
|
|
75
|
+
if (existsSync(dest)) {
|
|
76
|
+
console.error(`${dest} already exists — refusing to overwrite. Pass --dest to choose another path.`);
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
79
|
+
writeFileSync(dest, readFileSync(join(ROOT, meta.path), "utf8"));
|
|
80
|
+
console.log(`wrote ${dest}`);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
switch (cmd) {
|
|
84
|
+
case "list":
|
|
85
|
+
list();
|
|
86
|
+
break;
|
|
87
|
+
case "show":
|
|
88
|
+
if (!args[0]) {
|
|
89
|
+
console.error("usage: crondex show <id>");
|
|
90
|
+
process.exit(1);
|
|
91
|
+
}
|
|
92
|
+
show(args[0]);
|
|
93
|
+
break;
|
|
94
|
+
case "add":
|
|
95
|
+
if (!args[0]) {
|
|
96
|
+
console.error("usage: crondex add <id> [--dest <path>]");
|
|
97
|
+
process.exit(1);
|
|
98
|
+
}
|
|
99
|
+
add(args[0]);
|
|
100
|
+
break;
|
|
101
|
+
default:
|
|
102
|
+
printHelp();
|
|
103
|
+
}
|
package/catalog.json
ADDED
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
{
|
|
2
|
+
"generated_by": "scripts/build-catalog.js",
|
|
3
|
+
"schema": "schema/job.schema.json",
|
|
4
|
+
"count": 10,
|
|
5
|
+
"jobs": [
|
|
6
|
+
{
|
|
7
|
+
"id": "backup-reminder",
|
|
8
|
+
"version": 1,
|
|
9
|
+
"name": "Backup Freshness Check",
|
|
10
|
+
"description": "Checks that your backup file actually got updated recently, and warns you if it's missing or stale. Use this if you have a backup process running somewhere and want to catch it silently failing before you need it.",
|
|
11
|
+
"category": "devops",
|
|
12
|
+
"tags": [
|
|
13
|
+
"backup",
|
|
14
|
+
"reliability",
|
|
15
|
+
"maintenance"
|
|
16
|
+
],
|
|
17
|
+
"schedule": "0 9 * * *",
|
|
18
|
+
"timezone": "UTC",
|
|
19
|
+
"runner": "shell",
|
|
20
|
+
"modes": [
|
|
21
|
+
"script"
|
|
22
|
+
],
|
|
23
|
+
"compatible_agents": [
|
|
24
|
+
"generic",
|
|
25
|
+
"claude",
|
|
26
|
+
"codex"
|
|
27
|
+
],
|
|
28
|
+
"path": "jobs/devops/backup-reminder.yaml"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"id": "cost-alert",
|
|
32
|
+
"version": 1,
|
|
33
|
+
"name": "Cloud/API Cost Alert",
|
|
34
|
+
"description": "Checks your recent cloud or API spend against a budget and warns you if you're over or on pace to go over. Use this if you've ever been surprised by a bill.",
|
|
35
|
+
"category": "devops",
|
|
36
|
+
"tags": [
|
|
37
|
+
"cost",
|
|
38
|
+
"billing",
|
|
39
|
+
"budget"
|
|
40
|
+
],
|
|
41
|
+
"schedule": "0 7 * * *",
|
|
42
|
+
"timezone": "UTC",
|
|
43
|
+
"runner": "hybrid",
|
|
44
|
+
"modes": [
|
|
45
|
+
"script",
|
|
46
|
+
"agent-prompt"
|
|
47
|
+
],
|
|
48
|
+
"compatible_agents": [
|
|
49
|
+
"claude",
|
|
50
|
+
"codex",
|
|
51
|
+
"hermes",
|
|
52
|
+
"openclaw",
|
|
53
|
+
"generic"
|
|
54
|
+
],
|
|
55
|
+
"path": "jobs/devops/cost-alert.yaml"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"id": "daily-standup-summary",
|
|
59
|
+
"version": 1,
|
|
60
|
+
"name": "Daily Standup Summary",
|
|
61
|
+
"description": "Pulls together what you did yesterday (commits, closed tasks) plus today's calendar, and drafts a quick 3-line standup update. Use this if you're tired of writing the same \"yesterday / today / blockers\" recap every morning.",
|
|
62
|
+
"category": "productivity",
|
|
63
|
+
"tags": [
|
|
64
|
+
"standup",
|
|
65
|
+
"reporting",
|
|
66
|
+
"daily"
|
|
67
|
+
],
|
|
68
|
+
"schedule": "0 8 * * 1-5",
|
|
69
|
+
"timezone": "America/Los_Angeles",
|
|
70
|
+
"runner": "hybrid",
|
|
71
|
+
"modes": [
|
|
72
|
+
"script",
|
|
73
|
+
"agent-prompt"
|
|
74
|
+
],
|
|
75
|
+
"compatible_agents": [
|
|
76
|
+
"claude",
|
|
77
|
+
"codex",
|
|
78
|
+
"hermes",
|
|
79
|
+
"openclaw",
|
|
80
|
+
"generic"
|
|
81
|
+
],
|
|
82
|
+
"path": "jobs/productivity/daily-standup-summary.yaml"
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"id": "dependency-audit",
|
|
86
|
+
"version": 1,
|
|
87
|
+
"name": "Dependency Vulnerability Audit",
|
|
88
|
+
"description": "Checks your project's dependencies for known security vulnerabilities and packages that are way out of date, then summarizes what to fix first. Use this if you want a heads-up before something exploitable slips into production.",
|
|
89
|
+
"category": "devops",
|
|
90
|
+
"tags": [
|
|
91
|
+
"security",
|
|
92
|
+
"dependencies",
|
|
93
|
+
"maintenance"
|
|
94
|
+
],
|
|
95
|
+
"schedule": "0 8 * * 1",
|
|
96
|
+
"timezone": "UTC",
|
|
97
|
+
"runner": "hybrid",
|
|
98
|
+
"modes": [
|
|
99
|
+
"script",
|
|
100
|
+
"agent-prompt"
|
|
101
|
+
],
|
|
102
|
+
"compatible_agents": [
|
|
103
|
+
"claude",
|
|
104
|
+
"codex",
|
|
105
|
+
"hermes",
|
|
106
|
+
"openclaw",
|
|
107
|
+
"generic"
|
|
108
|
+
],
|
|
109
|
+
"path": "jobs/devops/dependency-audit.yaml"
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"id": "inbox-triage",
|
|
113
|
+
"version": 1,
|
|
114
|
+
"name": "Inbox Triage",
|
|
115
|
+
"description": "Sorts your unread messages into \"needs a reply today\" vs. \"just FYI\" vs. \"spam,\" and drafts quick replies for the easy ones — it never sends anything without you approving it first. Use this if your inbox piles up and you want a head start each morning.",
|
|
116
|
+
"category": "productivity",
|
|
117
|
+
"tags": [
|
|
118
|
+
"email",
|
|
119
|
+
"triage",
|
|
120
|
+
"daily"
|
|
121
|
+
],
|
|
122
|
+
"schedule": "0 7,13 * * 1-5",
|
|
123
|
+
"timezone": "America/Los_Angeles",
|
|
124
|
+
"runner": "agent-prompt",
|
|
125
|
+
"modes": [
|
|
126
|
+
"agent-prompt"
|
|
127
|
+
],
|
|
128
|
+
"compatible_agents": [
|
|
129
|
+
"claude",
|
|
130
|
+
"codex",
|
|
131
|
+
"hermes",
|
|
132
|
+
"openclaw",
|
|
133
|
+
"generic"
|
|
134
|
+
],
|
|
135
|
+
"path": "jobs/productivity/inbox-triage.yaml"
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
"id": "log-cleanup",
|
|
139
|
+
"version": 1,
|
|
140
|
+
"name": "Old Log File Cleanup",
|
|
141
|
+
"description": "Deletes old log files so they don't quietly fill up your disk. Use this if your app or server writes logs to a folder and nobody's manually clearing them out.",
|
|
142
|
+
"category": "devops",
|
|
143
|
+
"tags": [
|
|
144
|
+
"housekeeping",
|
|
145
|
+
"disk-space"
|
|
146
|
+
],
|
|
147
|
+
"schedule": "30 3 * * *",
|
|
148
|
+
"timezone": "UTC",
|
|
149
|
+
"runner": "shell",
|
|
150
|
+
"modes": [
|
|
151
|
+
"script"
|
|
152
|
+
],
|
|
153
|
+
"compatible_agents": [
|
|
154
|
+
"generic",
|
|
155
|
+
"claude",
|
|
156
|
+
"codex"
|
|
157
|
+
],
|
|
158
|
+
"path": "jobs/devops/log-cleanup.yaml"
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
"id": "repo-health-check",
|
|
162
|
+
"version": 1,
|
|
163
|
+
"name": "Git Repo Health Check",
|
|
164
|
+
"description": "Checks a git repo for branches nobody's touched in a while, uncommitted changes sitting around, and pull requests waiting on review, then reports a short digest. Use this if you want a daily nudge on repo hygiene without checking everything by hand.",
|
|
165
|
+
"category": "devops",
|
|
166
|
+
"tags": [
|
|
167
|
+
"git",
|
|
168
|
+
"ci",
|
|
169
|
+
"maintenance"
|
|
170
|
+
],
|
|
171
|
+
"schedule": "0 9 * * 1-5",
|
|
172
|
+
"timezone": "UTC",
|
|
173
|
+
"runner": "hybrid",
|
|
174
|
+
"modes": [
|
|
175
|
+
"script",
|
|
176
|
+
"agent-prompt"
|
|
177
|
+
],
|
|
178
|
+
"compatible_agents": [
|
|
179
|
+
"claude",
|
|
180
|
+
"codex",
|
|
181
|
+
"hermes",
|
|
182
|
+
"openclaw",
|
|
183
|
+
"generic"
|
|
184
|
+
],
|
|
185
|
+
"path": "jobs/devops/repo-health-check.yaml"
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
"id": "ssl-cert-expiry-check",
|
|
189
|
+
"version": 1,
|
|
190
|
+
"name": "SSL Certificate Expiry Check",
|
|
191
|
+
"description": "Checks how many days are left before a website's SSL certificate expires. Use this if you run a site and want a warning before the padlock breaks and visitors start seeing browser security errors.",
|
|
192
|
+
"category": "devops",
|
|
193
|
+
"tags": [
|
|
194
|
+
"ssl",
|
|
195
|
+
"tls",
|
|
196
|
+
"security",
|
|
197
|
+
"uptime"
|
|
198
|
+
],
|
|
199
|
+
"schedule": "0 6 * * *",
|
|
200
|
+
"timezone": "UTC",
|
|
201
|
+
"runner": "shell",
|
|
202
|
+
"modes": [
|
|
203
|
+
"script"
|
|
204
|
+
],
|
|
205
|
+
"compatible_agents": [
|
|
206
|
+
"generic",
|
|
207
|
+
"claude",
|
|
208
|
+
"codex"
|
|
209
|
+
],
|
|
210
|
+
"path": "jobs/devops/ssl-cert-expiry-check.yaml"
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
"id": "uptime-ping-check",
|
|
214
|
+
"version": 1,
|
|
215
|
+
"name": "Uptime Ping Check",
|
|
216
|
+
"description": "Pings a URL on a schedule and flags it if it stops responding. Use this if you want a basic \"is my site down\" alert without paying for a monitoring service.",
|
|
217
|
+
"category": "devops",
|
|
218
|
+
"tags": [
|
|
219
|
+
"uptime",
|
|
220
|
+
"monitoring",
|
|
221
|
+
"reliability"
|
|
222
|
+
],
|
|
223
|
+
"schedule": "*/15 * * * *",
|
|
224
|
+
"timezone": "UTC",
|
|
225
|
+
"runner": "shell",
|
|
226
|
+
"modes": [
|
|
227
|
+
"script"
|
|
228
|
+
],
|
|
229
|
+
"compatible_agents": [
|
|
230
|
+
"generic",
|
|
231
|
+
"claude",
|
|
232
|
+
"codex"
|
|
233
|
+
],
|
|
234
|
+
"path": "jobs/devops/uptime-ping-check.yaml"
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
"id": "weekly-report",
|
|
238
|
+
"version": 1,
|
|
239
|
+
"name": "Weekly Progress Report",
|
|
240
|
+
"description": "Rolls up a week's worth of commits and progress into a short report you can hand to your team. Use this if you dread writing the Friday status update from scratch every week.",
|
|
241
|
+
"category": "productivity",
|
|
242
|
+
"tags": [
|
|
243
|
+
"reporting",
|
|
244
|
+
"weekly"
|
|
245
|
+
],
|
|
246
|
+
"schedule": "0 16 * * 5",
|
|
247
|
+
"timezone": "America/Los_Angeles",
|
|
248
|
+
"runner": "hybrid",
|
|
249
|
+
"modes": [
|
|
250
|
+
"script",
|
|
251
|
+
"agent-prompt"
|
|
252
|
+
],
|
|
253
|
+
"compatible_agents": [
|
|
254
|
+
"claude",
|
|
255
|
+
"codex",
|
|
256
|
+
"hermes",
|
|
257
|
+
"openclaw",
|
|
258
|
+
"generic"
|
|
259
|
+
],
|
|
260
|
+
"path": "jobs/productivity/weekly-report.yaml"
|
|
261
|
+
}
|
|
262
|
+
]
|
|
263
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
id: backup-reminder
|
|
2
|
+
version: 1
|
|
3
|
+
name: Backup Freshness Check
|
|
4
|
+
description: >
|
|
5
|
+
Checks that your backup file actually got updated recently, and warns you
|
|
6
|
+
if it's missing or stale. Use this if you have a backup process running
|
|
7
|
+
somewhere and want to catch it silently failing before you need it.
|
|
8
|
+
category: devops
|
|
9
|
+
tags: [backup, reliability, maintenance]
|
|
10
|
+
schedule: "0 9 * * *"
|
|
11
|
+
timezone: "UTC"
|
|
12
|
+
runner: shell
|
|
13
|
+
command: >
|
|
14
|
+
f={{backup_path}}; [ -e "$f" ] || { echo "MISSING: $f not found"; exit 1; };
|
|
15
|
+
age=$(( ( $(date +%s) - $(stat -f %m "$f" 2>/dev/null || stat -c %Y "$f") ) / 86400 ));
|
|
16
|
+
if [ "$age" -gt {{max_age_days}} ]; then echo "STALE: $f last updated $age days ago"; exit 1;
|
|
17
|
+
else echo "OK: $f last updated $age days ago"; fi
|
|
18
|
+
variables:
|
|
19
|
+
backup_path:
|
|
20
|
+
default: "./backups/latest.tar.gz"
|
|
21
|
+
description: File or directory to check the mtime of.
|
|
22
|
+
max_age_days:
|
|
23
|
+
default: 1
|
|
24
|
+
description: Alert if the backup is older than this many days.
|
|
25
|
+
compatible_agents: [generic, claude, codex]
|
|
26
|
+
notes: Exits non-zero on missing/stale so a scheduler can alert on failure. Adjust stat flag for Linux vs macOS if running raw (command above handles both).
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
id: cost-alert
|
|
2
|
+
version: 1
|
|
3
|
+
name: Cloud/API Cost Alert
|
|
4
|
+
description: >
|
|
5
|
+
Checks your recent cloud or API spend against a budget and warns you if
|
|
6
|
+
you're over or on pace to go over. Use this if you've ever been
|
|
7
|
+
surprised by a bill.
|
|
8
|
+
category: devops
|
|
9
|
+
tags: [cost, billing, budget]
|
|
10
|
+
schedule: "0 7 * * *"
|
|
11
|
+
timezone: "UTC"
|
|
12
|
+
runner: hybrid
|
|
13
|
+
command: >
|
|
14
|
+
if command -v aws >/dev/null 2>&1; then
|
|
15
|
+
start=$(date -d "-{{lookback_days}} days" +%Y-%m-%d 2>/dev/null || date -v-{{lookback_days}}d +%Y-%m-%d);
|
|
16
|
+
end=$(date +%Y-%m-%d);
|
|
17
|
+
aws ce get-cost-and-usage --time-period Start=$start,End=$end --granularity DAILY --metrics UnblendedCost 2>/dev/null || echo "aws cost explorer call failed (check credentials/permissions)";
|
|
18
|
+
elif command -v vercel >/dev/null 2>&1; then
|
|
19
|
+
vercel billing 2>/dev/null || echo "vercel CLI present but no billing subcommand available";
|
|
20
|
+
else
|
|
21
|
+
echo "no supported billing CLI found (aws/vercel) — use agent-prompt mode instead";
|
|
22
|
+
fi
|
|
23
|
+
prompt: |
|
|
24
|
+
Check current spend for {{provider_hint}} covering the last {{lookback_days}} days.
|
|
25
|
+
1. Use whatever billing/cost API, CLI, or dashboard you have access to for this account.
|
|
26
|
+
2. Compare total spend to the {{budget_usd}} budget.
|
|
27
|
+
3. If over budget, or on pace to exceed it before the period ends, alert
|
|
28
|
+
with the overage amount and the top 3 cost drivers.
|
|
29
|
+
4. If under budget, report spend vs. budget in one line.
|
|
30
|
+
script_note: >
|
|
31
|
+
`command` dumps raw provider CLI output (AWS/Vercel only) with no budget
|
|
32
|
+
comparison — parsing arbitrary billing JSON reliably in shell isn't
|
|
33
|
+
practical. `prompt` works with any provider your agent has access to and
|
|
34
|
+
does the budget comparison and driver breakdown.
|
|
35
|
+
variables:
|
|
36
|
+
provider_hint:
|
|
37
|
+
default: "cloud provider"
|
|
38
|
+
description: Name the provider/account to check (e.g. "AWS", "Vercel", "OpenAI API").
|
|
39
|
+
budget_usd:
|
|
40
|
+
default: 100
|
|
41
|
+
description: Budget threshold in USD for the lookback window.
|
|
42
|
+
lookback_days:
|
|
43
|
+
default: 30
|
|
44
|
+
description: Rolling window of spend to evaluate.
|
|
45
|
+
compatible_agents: [claude, codex, hermes, openclaw, generic]
|
|
46
|
+
notes: Script mode only covers AWS/Vercel CLIs out of the box; extend `command` for other providers as needed.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
id: dependency-audit
|
|
2
|
+
version: 1
|
|
3
|
+
name: Dependency Vulnerability Audit
|
|
4
|
+
description: >
|
|
5
|
+
Checks your project's dependencies for known security vulnerabilities and
|
|
6
|
+
packages that are way out of date, then summarizes what to fix first.
|
|
7
|
+
Use this if you want a heads-up before something exploitable slips into
|
|
8
|
+
production.
|
|
9
|
+
category: devops
|
|
10
|
+
tags: [security, dependencies, maintenance]
|
|
11
|
+
schedule: "0 8 * * 1"
|
|
12
|
+
timezone: "UTC"
|
|
13
|
+
runner: hybrid
|
|
14
|
+
command: >
|
|
15
|
+
cd {{repo_path}} &&
|
|
16
|
+
if [ -f package.json ]; then npm audit;
|
|
17
|
+
elif [ -f requirements.txt ]; then pip-audit -r requirements.txt;
|
|
18
|
+
elif [ -f Cargo.toml ]; then cargo audit;
|
|
19
|
+
else echo "no supported manifest (package.json/requirements.txt/Cargo.toml) found"; fi
|
|
20
|
+
prompt: |
|
|
21
|
+
Run a dependency audit on the repo at {{repo_path}}.
|
|
22
|
+
1. Detect the package manager(s) in use (npm/pnpm/yarn/pip/cargo/etc).
|
|
23
|
+
2. Run each manager's native audit command (e.g. `npm audit`, `pip-audit`).
|
|
24
|
+
3. List vulnerabilities by severity, and packages more than {{staleness_days}}
|
|
25
|
+
days behind latest.
|
|
26
|
+
4. Summarize findings in under 200 words with a prioritized action list.
|
|
27
|
+
Do not modify any files — report only.
|
|
28
|
+
script_note: >
|
|
29
|
+
`command` prints the raw audit tool output, zero tokens. `prompt` additionally
|
|
30
|
+
flags stale-but-not-vulnerable packages and ranks/prioritizes the findings for you.
|
|
31
|
+
variables:
|
|
32
|
+
repo_path:
|
|
33
|
+
default: "."
|
|
34
|
+
description: Path to the repo to audit.
|
|
35
|
+
staleness_days:
|
|
36
|
+
default: 180
|
|
37
|
+
description: Flag packages whose latest release is older than this many days behind current.
|
|
38
|
+
compatible_agents: [claude, codex, hermes, openclaw, generic]
|
|
39
|
+
notes: Read-only job. Safe to run unattended.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
id: log-cleanup
|
|
2
|
+
version: 1
|
|
3
|
+
name: Old Log File Cleanup
|
|
4
|
+
description: >
|
|
5
|
+
Deletes old log files so they don't quietly fill up your disk.
|
|
6
|
+
Use this if your app or server writes logs to a folder and nobody's
|
|
7
|
+
manually clearing them out.
|
|
8
|
+
category: devops
|
|
9
|
+
tags: [housekeeping, disk-space]
|
|
10
|
+
schedule: "30 3 * * *"
|
|
11
|
+
timezone: "UTC"
|
|
12
|
+
runner: shell
|
|
13
|
+
command: >
|
|
14
|
+
find {{log_dir}} -type f -name "{{log_pattern}}" -mtime +{{retention_days}} -delete
|
|
15
|
+
variables:
|
|
16
|
+
log_dir:
|
|
17
|
+
default: "./logs"
|
|
18
|
+
description: Directory to clean.
|
|
19
|
+
log_pattern:
|
|
20
|
+
default: "*.log"
|
|
21
|
+
description: Glob pattern for files to consider.
|
|
22
|
+
retention_days:
|
|
23
|
+
default: 14
|
|
24
|
+
description: Delete files last modified more than this many days ago.
|
|
25
|
+
compatible_agents: [generic, claude, codex]
|
|
26
|
+
notes: Destructive job — dry-run with `find ... -print` instead of `-delete` before first use.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
id: repo-health-check
|
|
2
|
+
version: 1
|
|
3
|
+
name: Git Repo Health Check
|
|
4
|
+
description: >
|
|
5
|
+
Checks a git repo for branches nobody's touched in a while, uncommitted
|
|
6
|
+
changes sitting around, and pull requests waiting on review, then reports
|
|
7
|
+
a short digest. Use this if you want a daily nudge on repo hygiene
|
|
8
|
+
without checking everything by hand.
|
|
9
|
+
category: devops
|
|
10
|
+
tags: [git, ci, maintenance]
|
|
11
|
+
schedule: "0 9 * * 1-5"
|
|
12
|
+
timezone: "UTC"
|
|
13
|
+
runner: hybrid
|
|
14
|
+
command: >
|
|
15
|
+
cd {{repo_path}} && now=$(date +%s) &&
|
|
16
|
+
echo "--- branches stale >{{stale_branch_days}}d ---" &&
|
|
17
|
+
git for-each-ref --format='%(committerdate:unix) %(refname:short)' refs/heads/ |
|
|
18
|
+
while read ts name; do age=$(( (now-ts)/86400 )); [ "$age" -gt {{stale_branch_days}} ] && echo "$name: ${age}d"; done;
|
|
19
|
+
echo "--- uncommitted changes ---"; git status --short;
|
|
20
|
+
command -v gh >/dev/null && { echo "--- open PRs ---"; gh pr list --state open; } || echo "(gh not installed, skipping PR check)"
|
|
21
|
+
prompt: |
|
|
22
|
+
Check the health of the repo at {{repo_path}}.
|
|
23
|
+
1. List local/remote branches not touched in over {{stale_branch_days}} days.
|
|
24
|
+
2. Flag any uncommitted changes sitting for more than a day.
|
|
25
|
+
3. If a CI config exists, report the status of the last run on the default branch.
|
|
26
|
+
4. List open PRs older than {{stale_pr_days}} days with no recent activity.
|
|
27
|
+
Summarize as a short digest, most actionable item first.
|
|
28
|
+
script_note: >
|
|
29
|
+
`command` prints raw stale-branch/status/PR-list data, zero tokens. `prompt`
|
|
30
|
+
additionally checks CI status and turns it into a prioritized digest.
|
|
31
|
+
variables:
|
|
32
|
+
repo_path:
|
|
33
|
+
default: "."
|
|
34
|
+
description: Path to the repo to check.
|
|
35
|
+
stale_branch_days:
|
|
36
|
+
default: 30
|
|
37
|
+
description: Branches with no commits in this many days are flagged stale.
|
|
38
|
+
stale_pr_days:
|
|
39
|
+
default: 7
|
|
40
|
+
description: Open PRs with no activity in this many days are flagged.
|
|
41
|
+
compatible_agents: [claude, codex, hermes, openclaw, generic]
|
|
42
|
+
notes: Read-only job. Needs `gh` CLI or equivalent for PR/CI data if available.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
id: ssl-cert-expiry-check
|
|
2
|
+
version: 1
|
|
3
|
+
name: SSL Certificate Expiry Check
|
|
4
|
+
description: >
|
|
5
|
+
Checks how many days are left before a website's SSL certificate expires.
|
|
6
|
+
Use this if you run a site and want a warning before the padlock breaks
|
|
7
|
+
and visitors start seeing browser security errors.
|
|
8
|
+
category: devops
|
|
9
|
+
tags: [ssl, tls, security, uptime]
|
|
10
|
+
schedule: "0 6 * * *"
|
|
11
|
+
timezone: "UTC"
|
|
12
|
+
runner: shell
|
|
13
|
+
command: >
|
|
14
|
+
host={{host}}; port={{port}};
|
|
15
|
+
exp=$(echo | openssl s_client -servername "$host" -connect "$host:$port" 2>/dev/null | openssl x509 -noout -enddate | cut -d= -f2);
|
|
16
|
+
[ -z "$exp" ] && { echo "ERROR: could not fetch certificate for $host:$port"; exit 1; };
|
|
17
|
+
exp_epoch=$(date -d "$exp" +%s 2>/dev/null || date -j -f "%b %d %T %Y %Z" "$exp" +%s);
|
|
18
|
+
now=$(date +%s);
|
|
19
|
+
days=$(( (exp_epoch-now)/86400 ));
|
|
20
|
+
if [ "$days" -lt {{warn_days}} ]; then echo "WARNING: $host cert expires in $days days ($exp)"; exit 1;
|
|
21
|
+
else echo "OK: $host cert expires in $days days ($exp)"; fi
|
|
22
|
+
variables:
|
|
23
|
+
host:
|
|
24
|
+
default: "example.com"
|
|
25
|
+
description: Hostname to check.
|
|
26
|
+
port:
|
|
27
|
+
default: 443
|
|
28
|
+
description: Port the TLS service listens on.
|
|
29
|
+
warn_days:
|
|
30
|
+
default: 14
|
|
31
|
+
description: Alert if the cert expires within this many days.
|
|
32
|
+
compatible_agents: [generic, claude, codex]
|
|
33
|
+
notes: Zero-token, deterministic — no LLM mode needed for a plain expiry check.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
id: uptime-ping-check
|
|
2
|
+
version: 1
|
|
3
|
+
name: Uptime Ping Check
|
|
4
|
+
description: >
|
|
5
|
+
Pings a URL on a schedule and flags it if it stops responding.
|
|
6
|
+
Use this if you want a basic "is my site down" alert without paying for
|
|
7
|
+
a monitoring service.
|
|
8
|
+
category: devops
|
|
9
|
+
tags: [uptime, monitoring, reliability]
|
|
10
|
+
schedule: "*/15 * * * *"
|
|
11
|
+
timezone: "UTC"
|
|
12
|
+
runner: shell
|
|
13
|
+
command: >
|
|
14
|
+
url={{url}}; timeout={{timeout_seconds}};
|
|
15
|
+
code=$(curl -o /dev/null -s -w '%{http_code}' --max-time "$timeout" "$url");
|
|
16
|
+
if [ "$code" -ge 200 ] && [ "$code" -lt 400 ]; then echo "OK: $url returned $code";
|
|
17
|
+
else echo "DOWN: $url returned $code"; exit 1; fi
|
|
18
|
+
variables:
|
|
19
|
+
url:
|
|
20
|
+
default: "https://example.com"
|
|
21
|
+
description: URL to check.
|
|
22
|
+
timeout_seconds:
|
|
23
|
+
default: 10
|
|
24
|
+
description: Max seconds to wait for a response before treating it as down.
|
|
25
|
+
compatible_agents: [generic, claude, codex]
|
|
26
|
+
notes: Zero-token, deterministic. Run at a tighter interval (e.g. every 5-15 min) for real monitoring.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
id: daily-standup-summary
|
|
2
|
+
version: 1
|
|
3
|
+
name: Daily Standup Summary
|
|
4
|
+
description: >
|
|
5
|
+
Pulls together what you did yesterday (commits, closed tasks) plus
|
|
6
|
+
today's calendar, and drafts a quick 3-line standup update. Use this if
|
|
7
|
+
you're tired of writing the same "yesterday / today / blockers" recap
|
|
8
|
+
every morning.
|
|
9
|
+
category: productivity
|
|
10
|
+
tags: [standup, reporting, daily]
|
|
11
|
+
schedule: "0 8 * * 1-5"
|
|
12
|
+
timezone: "America/Los_Angeles"
|
|
13
|
+
runner: hybrid
|
|
14
|
+
command: >
|
|
15
|
+
cd {{repo_path}} && echo "--- commits last {{lookback_hours}}h ---" &&
|
|
16
|
+
git log --since="{{lookback_hours}} hours ago" --pretty=format:'%h %s'
|
|
17
|
+
prompt: |
|
|
18
|
+
Draft a standup update for {{person_name}}.
|
|
19
|
+
1. Summarize commits and merged PRs from the last {{lookback_hours}} hours in
|
|
20
|
+
{{repo_path}}.
|
|
21
|
+
2. List today's calendar events if a calendar source is connected.
|
|
22
|
+
3. Ask the user (or infer from open tasks) what blockers to mention.
|
|
23
|
+
Output exactly 3 lines: Yesterday / Today / Blockers.
|
|
24
|
+
script_note: >
|
|
25
|
+
`command` dumps the raw commit log, zero tokens. `prompt` additionally pulls
|
|
26
|
+
calendar events, infers blockers, and writes the 3-line Yesterday/Today/Blockers format.
|
|
27
|
+
variables:
|
|
28
|
+
person_name:
|
|
29
|
+
default: "me"
|
|
30
|
+
description: Name to use in the summary.
|
|
31
|
+
repo_path:
|
|
32
|
+
default: "."
|
|
33
|
+
description: Repo to pull commit history from.
|
|
34
|
+
lookback_hours:
|
|
35
|
+
default: 24
|
|
36
|
+
description: Window of history to summarize.
|
|
37
|
+
compatible_agents: [claude, codex, hermes, openclaw, generic]
|
|
38
|
+
notes: Pairs well with a Slack/email delivery step if the agent has that integration.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
id: inbox-triage
|
|
2
|
+
version: 1
|
|
3
|
+
name: Inbox Triage
|
|
4
|
+
description: >
|
|
5
|
+
Sorts your unread messages into "needs a reply today" vs. "just FYI" vs.
|
|
6
|
+
"spam," and drafts quick replies for the easy ones — it never sends
|
|
7
|
+
anything without you approving it first. Use this if your inbox piles up
|
|
8
|
+
and you want a head start each morning.
|
|
9
|
+
category: productivity
|
|
10
|
+
tags: [email, triage, daily]
|
|
11
|
+
schedule: "0 7,13 * * 1-5"
|
|
12
|
+
timezone: "America/Los_Angeles"
|
|
13
|
+
runner: agent-prompt
|
|
14
|
+
prompt: |
|
|
15
|
+
Triage unread messages in {{inbox_source}} from the last {{lookback_hours}} hours.
|
|
16
|
+
1. Bucket each into: needs-reply-today, fyi-only, spam/newsletter.
|
|
17
|
+
2. For anything in needs-reply-today that looks routine (scheduling, simple
|
|
18
|
+
confirmations), draft a short reply but do NOT send — save as a draft.
|
|
19
|
+
3. Report counts per bucket and list the needs-reply-today items with a
|
|
20
|
+
one-line reason each.
|
|
21
|
+
variables:
|
|
22
|
+
inbox_source:
|
|
23
|
+
default: "primary inbox"
|
|
24
|
+
description: Which inbox/connector to read from.
|
|
25
|
+
lookback_hours:
|
|
26
|
+
default: 18
|
|
27
|
+
description: Window of unread messages to consider.
|
|
28
|
+
compatible_agents: [claude, codex, hermes, openclaw, generic]
|
|
29
|
+
notes: >
|
|
30
|
+
Never auto-send. Draft-only by design — review before sending.
|
|
31
|
+
No script mode: categorization and reply drafting require judgment, and
|
|
32
|
+
inbox access varies too much by connector for a generic shell equivalent.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
id: weekly-report
|
|
2
|
+
version: 1
|
|
3
|
+
name: Weekly Progress Report
|
|
4
|
+
description: >
|
|
5
|
+
Rolls up a week's worth of commits and progress into a short report you
|
|
6
|
+
can hand to your team. Use this if you dread writing the Friday status
|
|
7
|
+
update from scratch every week.
|
|
8
|
+
category: productivity
|
|
9
|
+
tags: [reporting, weekly]
|
|
10
|
+
schedule: "0 16 * * 5"
|
|
11
|
+
timezone: "America/Los_Angeles"
|
|
12
|
+
runner: hybrid
|
|
13
|
+
command: >
|
|
14
|
+
cd {{repo_path}} && echo "--- shortlog last {{lookback_days}}d ---" &&
|
|
15
|
+
git shortlog -sn --since="{{lookback_days}} days ago" &&
|
|
16
|
+
echo "--- commits ---" && git log --since="{{lookback_days}} days ago" --pretty=format:'%h %an %s'
|
|
17
|
+
prompt: |
|
|
18
|
+
Build a weekly report for {{project_name}} covering the last {{lookback_days}} days.
|
|
19
|
+
1. Summarize merged PRs / commits in {{repo_path}}.
|
|
20
|
+
2. Summarize closed tasks/issues if a tracker is connected.
|
|
21
|
+
3. Note any metrics worth flagging (e.g. errors, usage) if a source is
|
|
22
|
+
connected.
|
|
23
|
+
4. Write it as 4 sections: Shipped, In Progress, Blocked, Next Week.
|
|
24
|
+
Keep the whole report under 300 words.
|
|
25
|
+
script_note: >
|
|
26
|
+
`command` dumps raw commit/shortlog stats, zero tokens. `prompt` additionally
|
|
27
|
+
pulls tracker/metrics data and writes the narrative Shipped/In Progress/Blocked/Next Week report.
|
|
28
|
+
variables:
|
|
29
|
+
project_name:
|
|
30
|
+
default: "this project"
|
|
31
|
+
description: Name to use in the report header.
|
|
32
|
+
repo_path:
|
|
33
|
+
default: "."
|
|
34
|
+
description: Repo to pull history from.
|
|
35
|
+
lookback_days:
|
|
36
|
+
default: 7
|
|
37
|
+
description: Rolling window the report covers.
|
|
38
|
+
compatible_agents: [claude, codex, hermes, openclaw, generic]
|
|
39
|
+
notes: Schedule for Friday afternoon by default; adjust `schedule` for your team's cadence.
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@wonsukchoi/crondex",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A public directory of pre-made, agent-editable cron jobs.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/wonsukchoi/crondex.git"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/wonsukchoi/crondex",
|
|
12
|
+
"keywords": [
|
|
13
|
+
"cron",
|
|
14
|
+
"cron-jobs",
|
|
15
|
+
"ai-agent",
|
|
16
|
+
"claude",
|
|
17
|
+
"codex",
|
|
18
|
+
"automation",
|
|
19
|
+
"scheduler"
|
|
20
|
+
],
|
|
21
|
+
"bin": {
|
|
22
|
+
"crondex": "bin/crondex.js"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"bin",
|
|
26
|
+
"jobs",
|
|
27
|
+
"schema",
|
|
28
|
+
"catalog.json"
|
|
29
|
+
],
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=18"
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"build-catalog": "node scripts/build-catalog.js",
|
|
35
|
+
"validate": "node scripts/validate-jobs.js"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"ajv": "^8.17.1",
|
|
39
|
+
"js-yaml": "^4.1.0"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://github.com/wonsukchoi/crondex/schema/job.schema.json",
|
|
4
|
+
"title": "Crondex Job",
|
|
5
|
+
"description": "One pre-made cron job any AI agent (Claude, Codex, Hermes, OpenClaw, etc.) can pull, adjust, and schedule.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["id", "version", "name", "description", "schedule", "runner", "compatible_agents"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"id": {
|
|
10
|
+
"type": "string",
|
|
11
|
+
"pattern": "^[a-z0-9]+(-[a-z0-9]+)*$",
|
|
12
|
+
"description": "Unique slug, matches filename without extension."
|
|
13
|
+
},
|
|
14
|
+
"version": {
|
|
15
|
+
"type": "integer",
|
|
16
|
+
"minimum": 1,
|
|
17
|
+
"description": "Bump when `prompt` or `command` behavior changes meaningfully, so agents that already scheduled this job know to re-check it. Do not bump for wording-only edits."
|
|
18
|
+
},
|
|
19
|
+
"name": { "type": "string" },
|
|
20
|
+
"description": { "type": "string" },
|
|
21
|
+
"category": { "type": "string" },
|
|
22
|
+
"tags": {
|
|
23
|
+
"type": "array",
|
|
24
|
+
"items": { "type": "string" }
|
|
25
|
+
},
|
|
26
|
+
"schedule": {
|
|
27
|
+
"type": "string",
|
|
28
|
+
"description": "Standard 5-field cron expression, e.g. '0 9 * * 1-5'."
|
|
29
|
+
},
|
|
30
|
+
"timezone": {
|
|
31
|
+
"type": "string",
|
|
32
|
+
"description": "IANA timezone, e.g. 'America/Los_Angeles'. Defaults to system local time if omitted."
|
|
33
|
+
},
|
|
34
|
+
"runner": {
|
|
35
|
+
"type": "string",
|
|
36
|
+
"enum": ["agent-prompt", "shell", "hybrid"],
|
|
37
|
+
"description": "'agent-prompt' hands `prompt` to an LLM agent each run (uses tokens, richer output). 'shell' executes `command` directly (zero tokens). 'hybrid' ships both — pick `command` to save tokens or `prompt` for more detail/judgment."
|
|
38
|
+
},
|
|
39
|
+
"prompt": {
|
|
40
|
+
"type": "string",
|
|
41
|
+
"description": "Task text given to the agent. Supports {{variable}} placeholders resolved from `variables`."
|
|
42
|
+
},
|
|
43
|
+
"command": {
|
|
44
|
+
"type": "string",
|
|
45
|
+
"description": "Shell command to run, for runner: shell or hybrid. Supports {{variable}} placeholders."
|
|
46
|
+
},
|
|
47
|
+
"script_note": {
|
|
48
|
+
"type": "string",
|
|
49
|
+
"description": "For hybrid jobs: what the zero-token `command` gives you vs. what only the LLM `prompt` mode adds (e.g. no narrative synthesis, no judgment calls)."
|
|
50
|
+
},
|
|
51
|
+
"variables": {
|
|
52
|
+
"type": "object",
|
|
53
|
+
"additionalProperties": {
|
|
54
|
+
"type": "object",
|
|
55
|
+
"required": ["default"],
|
|
56
|
+
"properties": {
|
|
57
|
+
"default": {},
|
|
58
|
+
"description": { "type": "string" }
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
"description": "User-adjustable knobs, keyed by placeholder name."
|
|
62
|
+
},
|
|
63
|
+
"compatible_agents": {
|
|
64
|
+
"type": "array",
|
|
65
|
+
"items": {
|
|
66
|
+
"type": "string",
|
|
67
|
+
"enum": ["claude", "codex", "hermes", "openclaw", "generic"]
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
"notes": { "type": "string" }
|
|
71
|
+
},
|
|
72
|
+
"allOf": [
|
|
73
|
+
{
|
|
74
|
+
"if": { "properties": { "runner": { "const": "agent-prompt" } } },
|
|
75
|
+
"then": { "required": ["prompt"] }
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"if": { "properties": { "runner": { "const": "shell" } } },
|
|
79
|
+
"then": { "required": ["command"] }
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"if": { "properties": { "runner": { "const": "hybrid" } } },
|
|
83
|
+
"then": { "required": ["prompt", "command"] }
|
|
84
|
+
}
|
|
85
|
+
]
|
|
86
|
+
}
|