@wonsukchoi/crondex 0.1.1 → 0.3.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/README.md +78 -19
- package/catalog.json +537 -1
- package/jobs/content/broken-link-check.yaml +33 -0
- package/jobs/content/changelog-digest.yaml +40 -0
- package/jobs/content/social-mentions-watch.yaml +32 -0
- package/jobs/devops/db-backup-verify.yaml +37 -0
- package/jobs/devops/disk-space-check.yaml +26 -0
- package/jobs/devops/docker-image-prune.yaml +24 -0
- package/jobs/devops/env-drift-check.yaml +34 -0
- package/jobs/devops/license-compliance-check.yaml +31 -0
- package/jobs/devops/orphaned-branch-cleanup.yaml +28 -0
- package/jobs/devops/stale-dependency-pr-nudge.yaml +25 -0
- package/jobs/finance/net-worth-snapshot.yaml +33 -0
- package/jobs/finance/saas-seat-audit.yaml +35 -0
- package/jobs/finance/subscription-audit.yaml +34 -0
- package/jobs/learning/course-progress-checkin.yaml +37 -0
- package/jobs/learning/daily-flashcard-review.yaml +29 -0
- package/jobs/learning/reading-list-nudge.yaml +25 -0
- package/jobs/personal/screen-time-check.yaml +27 -0
- package/jobs/personal/water-intake-reminder.yaml +20 -0
- package/jobs/productivity/focus-block-reminder.yaml +25 -0
- package/jobs/security/failed-login-watch.yaml +37 -0
- package/jobs/security/open-port-check.yaml +36 -0
- package/jobs/security/secrets-scan.yaml +28 -0
- package/package.json +1 -1
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
id: social-mentions-watch
|
|
2
|
+
version: 1
|
|
3
|
+
name: Social Mentions Watch
|
|
4
|
+
description: >
|
|
5
|
+
Scans for recent mentions of your brand, product, or repo and summarizes
|
|
6
|
+
them. Use this if you want to catch a complaint or bug report on social
|
|
7
|
+
media before it turns into a bigger problem.
|
|
8
|
+
category: content
|
|
9
|
+
tags: [social, mentions, monitoring]
|
|
10
|
+
schedule: "0 9 * * *"
|
|
11
|
+
timezone: "UTC"
|
|
12
|
+
runner: agent-prompt
|
|
13
|
+
prompt: |
|
|
14
|
+
Search for mentions of "{{brand_or_repo}}" from the last {{lookback_hours}}
|
|
15
|
+
hours across whatever sources you have access to (X/Twitter, Reddit,
|
|
16
|
+
Hacker News, web search).
|
|
17
|
+
1. List each mention with source, link, and a one-line sentiment read
|
|
18
|
+
(positive/neutral/negative).
|
|
19
|
+
2. Flag anything that looks like a bug report, complaint, or something
|
|
20
|
+
needing a response.
|
|
21
|
+
3. If nothing found, just say so.
|
|
22
|
+
variables:
|
|
23
|
+
brand_or_repo:
|
|
24
|
+
default: "your project"
|
|
25
|
+
description: Name, handle, or repo to search mentions of.
|
|
26
|
+
lookback_hours:
|
|
27
|
+
default: 24
|
|
28
|
+
description: Window of mentions to consider.
|
|
29
|
+
compatible_agents: [claude, codex, hermes, openclaw, generic]
|
|
30
|
+
notes: >
|
|
31
|
+
No generic script mode — needs whatever search/API access your agent has
|
|
32
|
+
(web search, X API, Reddit API, etc.); sources vary too much to script generically.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
id: db-backup-verify
|
|
2
|
+
version: 1
|
|
3
|
+
name: Database Backup Restore Verification
|
|
4
|
+
description: >
|
|
5
|
+
Actually restores your latest database backup to a throwaway database
|
|
6
|
+
and checks it's queryable. Use this if `backup-reminder` isn't enough —
|
|
7
|
+
a backup file existing doesn't mean it's actually restorable.
|
|
8
|
+
category: devops
|
|
9
|
+
tags: [database, backup, postgres]
|
|
10
|
+
schedule: "0 5 * * *"
|
|
11
|
+
timezone: "UTC"
|
|
12
|
+
runner: shell
|
|
13
|
+
command: >
|
|
14
|
+
dump={{dump_path}}; scratch_db={{scratch_db_name}};
|
|
15
|
+
[ -f "$dump" ] || { echo "ERROR: $dump not found"; exit 1; };
|
|
16
|
+
command -v pg_restore >/dev/null 2>&1 || { echo "ERROR: pg_restore not installed"; exit 1; };
|
|
17
|
+
dropdb --if-exists "$scratch_db" 2>/dev/null;
|
|
18
|
+
createdb "$scratch_db" || { echo "ERROR: could not create scratch db $scratch_db"; exit 1; };
|
|
19
|
+
pg_restore -d "$scratch_db" "$dump" >/dev/null 2>&1;
|
|
20
|
+
count=$(psql -d "$scratch_db" -tAc "SELECT count(*) FROM {{checkpoint_table}}" 2>/dev/null);
|
|
21
|
+
dropdb --if-exists "$scratch_db" 2>/dev/null;
|
|
22
|
+
if [ -z "$count" ]; then echo "FAILED: restore or query failed on $dump"; exit 1;
|
|
23
|
+
else echo "OK: restored $dump, $checkpoint_table has $count rows"; fi
|
|
24
|
+
variables:
|
|
25
|
+
dump_path:
|
|
26
|
+
default: "./backups/latest.dump"
|
|
27
|
+
description: Path to the pg_dump/pg_restore-format backup file.
|
|
28
|
+
scratch_db_name:
|
|
29
|
+
default: "backup_verify_scratch"
|
|
30
|
+
description: Throwaway database name used for the test restore (created and dropped each run).
|
|
31
|
+
checkpoint_table:
|
|
32
|
+
default: "users"
|
|
33
|
+
description: A table expected to have rows — used to confirm the restore actually worked.
|
|
34
|
+
compatible_agents: [generic, claude, codex]
|
|
35
|
+
notes: >
|
|
36
|
+
Postgres-specific (pg_restore/psql/createdb/dropdb) — adapt the command
|
|
37
|
+
for other database engines. Needs CREATE/DROP DATABASE privileges.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
id: disk-space-check
|
|
2
|
+
version: 1
|
|
3
|
+
name: Disk Space Check
|
|
4
|
+
description: >
|
|
5
|
+
Checks how full a disk/volume is and warns you before it fills up.
|
|
6
|
+
Use this if you've ever had a server or laptop grind to a halt because
|
|
7
|
+
disk usage crept up unnoticed.
|
|
8
|
+
category: devops
|
|
9
|
+
tags: [disk, monitoring, maintenance]
|
|
10
|
+
schedule: "0 */6 * * *"
|
|
11
|
+
timezone: "UTC"
|
|
12
|
+
runner: shell
|
|
13
|
+
command: >
|
|
14
|
+
path={{path}}; threshold={{threshold_pct}};
|
|
15
|
+
pct=$(df -P "$path" | awk 'NR==2 {gsub("%","",$5); print $5}');
|
|
16
|
+
if [ "$pct" -ge "$threshold" ]; then echo "WARNING: $path is ${pct}% full (threshold ${threshold}%)"; exit 1;
|
|
17
|
+
else echo "OK: $path is ${pct}% full"; fi
|
|
18
|
+
variables:
|
|
19
|
+
path:
|
|
20
|
+
default: "/"
|
|
21
|
+
description: Mount point or path to check.
|
|
22
|
+
threshold_pct:
|
|
23
|
+
default: 85
|
|
24
|
+
description: Warn when usage reaches this percentage.
|
|
25
|
+
compatible_agents: [generic, claude, codex]
|
|
26
|
+
notes: Zero-token, deterministic. Uses `df -P` for portable output across macOS/Linux.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
id: docker-image-prune
|
|
2
|
+
version: 1
|
|
3
|
+
name: Docker Image & Container Prune
|
|
4
|
+
description: >
|
|
5
|
+
Cleans up stopped containers and dangling Docker images so they don't
|
|
6
|
+
quietly eat your disk. Use this if you run Docker locally or on a server
|
|
7
|
+
and never remember to clean up after yourself.
|
|
8
|
+
category: devops
|
|
9
|
+
tags: [docker, cleanup, disk-space]
|
|
10
|
+
schedule: "0 4 * * *"
|
|
11
|
+
timezone: "UTC"
|
|
12
|
+
runner: shell
|
|
13
|
+
command: >
|
|
14
|
+
command -v docker >/dev/null 2>&1 || { echo "docker not installed, skipping"; exit 0; };
|
|
15
|
+
docker container prune -f --filter "until={{until}}";
|
|
16
|
+
docker image prune -f --filter "until={{until}}"
|
|
17
|
+
variables:
|
|
18
|
+
until:
|
|
19
|
+
default: "24h"
|
|
20
|
+
description: Only remove containers/images older than this (Docker duration syntax, e.g. "24h", "720h").
|
|
21
|
+
compatible_agents: [generic, claude, codex]
|
|
22
|
+
notes: >
|
|
23
|
+
Destructive by nature (removes stopped containers and dangling images) —
|
|
24
|
+
the `until` default of 24h protects anything recent. Widen with care.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
id: env-drift-check
|
|
2
|
+
version: 1
|
|
3
|
+
name: Env File Drift Check
|
|
4
|
+
description: >
|
|
5
|
+
Compares your .env against .env.example and flags keys that are missing
|
|
6
|
+
or extra. Use this if you've ever deployed and hit a crash because a new
|
|
7
|
+
required env var never got set.
|
|
8
|
+
category: devops
|
|
9
|
+
tags: [config, env, drift]
|
|
10
|
+
schedule: "0 8 * * *"
|
|
11
|
+
timezone: "UTC"
|
|
12
|
+
runner: shell
|
|
13
|
+
command: >
|
|
14
|
+
example={{example_path}}; actual={{env_path}};
|
|
15
|
+
[ -f "$example" ] || { echo "ERROR: $example not found"; exit 1; };
|
|
16
|
+
[ -f "$actual" ] || { echo "ERROR: $actual not found"; exit 1; };
|
|
17
|
+
ex_keys=$(grep -vE '^\s*#|^\s*$' "$example" | cut -d= -f1 | sort -u);
|
|
18
|
+
ac_keys=$(grep -vE '^\s*#|^\s*$' "$actual" | cut -d= -f1 | sort -u);
|
|
19
|
+
missing=$(comm -23 <(echo "$ex_keys") <(echo "$ac_keys"));
|
|
20
|
+
extra=$(comm -13 <(echo "$ex_keys") <(echo "$ac_keys"));
|
|
21
|
+
[ -n "$missing" ] && echo "MISSING (in $example, not in $actual): $missing";
|
|
22
|
+
[ -n "$extra" ] && echo "EXTRA (in $actual, not in $example): $extra";
|
|
23
|
+
[ -z "$missing" ] && [ -z "$extra" ] && echo "OK: env keys match example"; true
|
|
24
|
+
variables:
|
|
25
|
+
example_path:
|
|
26
|
+
default: ".env.example"
|
|
27
|
+
description: Path to the example/template env file.
|
|
28
|
+
env_path:
|
|
29
|
+
default: ".env"
|
|
30
|
+
description: Path to the actual env file to check.
|
|
31
|
+
compatible_agents: [generic, claude, codex]
|
|
32
|
+
notes: >
|
|
33
|
+
Zero-token, deterministic. Requires bash (uses process substitution) —
|
|
34
|
+
won't run under plain POSIX sh.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
id: license-compliance-check
|
|
2
|
+
version: 1
|
|
3
|
+
name: Dependency License Compliance Check
|
|
4
|
+
description: >
|
|
5
|
+
Scans your dependencies for licenses you've flagged as risky (like GPL
|
|
6
|
+
or AGPL). Use this if you've ever shipped something and only later
|
|
7
|
+
found out a dependency's license doesn't play well with your product.
|
|
8
|
+
category: devops
|
|
9
|
+
tags: [license, compliance, dependencies]
|
|
10
|
+
schedule: "0 8 * * 1"
|
|
11
|
+
timezone: "UTC"
|
|
12
|
+
runner: shell
|
|
13
|
+
command: >
|
|
14
|
+
cd {{repo_path}} &&
|
|
15
|
+
if [ -f package.json ]; then
|
|
16
|
+
npx --yes license-checker --summary --excludePrivatePackages 2>/dev/null | grep -iE "{{flagged_licenses}}" && echo "^ flagged licenses found above" || echo "OK: no flagged licenses found";
|
|
17
|
+
else
|
|
18
|
+
echo "no package.json found — this job only supports npm/Node projects currently";
|
|
19
|
+
fi
|
|
20
|
+
variables:
|
|
21
|
+
repo_path:
|
|
22
|
+
default: "."
|
|
23
|
+
description: Path to the repo to check.
|
|
24
|
+
flagged_licenses:
|
|
25
|
+
default: "GPL|AGPL"
|
|
26
|
+
description: Regex alternation of license names to flag.
|
|
27
|
+
compatible_agents: [generic, claude, codex]
|
|
28
|
+
notes: >
|
|
29
|
+
npm/Node projects only (uses `npx license-checker`, downloads on first
|
|
30
|
+
run). For other ecosystems, swap in the equivalent tool
|
|
31
|
+
(pip-licenses, cargo-license, etc.) and adjust the command.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
id: orphaned-branch-cleanup
|
|
2
|
+
version: 1
|
|
3
|
+
name: Orphaned Branch Cleanup
|
|
4
|
+
description: >
|
|
5
|
+
Lists remote branches already merged into main that nobody's deleted
|
|
6
|
+
yet. Use this if your branch list has become a graveyard nobody wants
|
|
7
|
+
to clean up.
|
|
8
|
+
category: devops
|
|
9
|
+
tags: [git, cleanup, branches]
|
|
10
|
+
schedule: "0 9 * * 1"
|
|
11
|
+
timezone: "UTC"
|
|
12
|
+
runner: shell
|
|
13
|
+
command: >
|
|
14
|
+
cd {{repo_path}} && git fetch --prune >/dev/null 2>&1;
|
|
15
|
+
merged=$(git branch -r --merged {{base_branch}} | grep -v -E "(\*|{{base_branch}}$)" | sed 's#origin/##');
|
|
16
|
+
if [ -z "$merged" ]; then echo "OK: no merged branches to clean up";
|
|
17
|
+
else echo "Merged into {{base_branch}}, safe to delete:"; echo "$merged"; fi
|
|
18
|
+
variables:
|
|
19
|
+
repo_path:
|
|
20
|
+
default: "."
|
|
21
|
+
description: Path to the repo to check.
|
|
22
|
+
base_branch:
|
|
23
|
+
default: "main"
|
|
24
|
+
description: Branch to check merges against.
|
|
25
|
+
compatible_agents: [generic, claude, codex]
|
|
26
|
+
notes: >
|
|
27
|
+
List-only by design — never deletes anything. Review the list, then
|
|
28
|
+
`git push origin --delete <branch>` yourself for ones you actually want gone.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
id: stale-dependency-pr-nudge
|
|
2
|
+
version: 1
|
|
3
|
+
name: Stale Dependency PR Nudge
|
|
4
|
+
description: >
|
|
5
|
+
Lists open dependency-bump pull requests (from Dependabot/Renovate) that
|
|
6
|
+
have been sitting for a while. Use this if automated PRs pile up and
|
|
7
|
+
quietly go stale instead of getting merged or closed.
|
|
8
|
+
category: devops
|
|
9
|
+
tags: [github, dependencies, pr]
|
|
10
|
+
schedule: "0 9 * * 1-5"
|
|
11
|
+
timezone: "UTC"
|
|
12
|
+
runner: shell
|
|
13
|
+
command: >
|
|
14
|
+
command -v gh >/dev/null 2>&1 || { echo "gh CLI not installed, skipping"; exit 0; };
|
|
15
|
+
cd {{repo_path}} && gh pr list --state open --json number,title,author,createdAt --jq \
|
|
16
|
+
'.[] | select(.author.login | test("dependabot|renovate"; "i")) | select((now - (.createdAt | fromdateiso8601)) > ({{stale_days}} * 86400)) | "#\(.number) \(.title) (opened \(.createdAt))"'
|
|
17
|
+
variables:
|
|
18
|
+
repo_path:
|
|
19
|
+
default: "."
|
|
20
|
+
description: Path to the repo to check.
|
|
21
|
+
stale_days:
|
|
22
|
+
default: 3
|
|
23
|
+
description: Flag dependency PRs open longer than this many days.
|
|
24
|
+
compatible_agents: [generic, claude, codex]
|
|
25
|
+
notes: Requires an authenticated `gh` CLI. Zero-token, read-only.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
id: net-worth-snapshot
|
|
2
|
+
version: 1
|
|
3
|
+
name: Net Worth Snapshot Reminder
|
|
4
|
+
description: >
|
|
5
|
+
Reminds you to log your net worth each month and shows the trend from
|
|
6
|
+
your last two entries. Use this if you want to track your finances over
|
|
7
|
+
time but keep forgetting to actually sit down and do it.
|
|
8
|
+
category: finance
|
|
9
|
+
tags: [finance, net-worth, tracking]
|
|
10
|
+
schedule: "0 9 1 * *"
|
|
11
|
+
timezone: "UTC"
|
|
12
|
+
runner: shell
|
|
13
|
+
command: >
|
|
14
|
+
file={{net_worth_csv}};
|
|
15
|
+
[ -f "$file" ] || echo "date,net_worth" > "$file";
|
|
16
|
+
today=$(date +%F);
|
|
17
|
+
if tail -n +2 "$file" | cut -d, -f1 | grep -qx "$today"; then
|
|
18
|
+
echo "Already logged today.";
|
|
19
|
+
else
|
|
20
|
+
echo "$today," >> "$file";
|
|
21
|
+
echo "REMINDER: fill in today's net worth in $file";
|
|
22
|
+
fi;
|
|
23
|
+
prev=$(tail -n 2 "$file" | head -n 1 | cut -d, -f2);
|
|
24
|
+
last=$(tail -n 1 "$file" | cut -d, -f2);
|
|
25
|
+
[ -n "$prev" ] && [ -n "$last" ] && echo "Last entry: $last (previous: $prev)"; true
|
|
26
|
+
variables:
|
|
27
|
+
net_worth_csv:
|
|
28
|
+
default: "./net-worth.csv"
|
|
29
|
+
description: CSV log file, one row per month (date,net_worth).
|
|
30
|
+
compatible_agents: [generic, claude, codex]
|
|
31
|
+
notes: >
|
|
32
|
+
Zero-token. Appends a blank row for you to fill in by hand — doesn't
|
|
33
|
+
pull balances from any bank automatically.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
id: saas-seat-audit
|
|
2
|
+
version: 1
|
|
3
|
+
name: Team SaaS Seat Audit
|
|
4
|
+
description: >
|
|
5
|
+
Flags team SaaS seats (Slack, Notion, GitHub, etc.) nobody's actually
|
|
6
|
+
used in a while. Use this if you suspect you're paying for seats of
|
|
7
|
+
people who left or tools nobody opens anymore.
|
|
8
|
+
category: finance
|
|
9
|
+
tags: [saas, seats, team, budget]
|
|
10
|
+
schedule: "0 9 1 * *"
|
|
11
|
+
timezone: "UTC"
|
|
12
|
+
runner: shell
|
|
13
|
+
command: >
|
|
14
|
+
file={{seats_file}}; unused_days={{unused_days}};
|
|
15
|
+
[ -f "$file" ] || { echo "ERROR: $file not found"; exit 1; };
|
|
16
|
+
today=$(date +%s);
|
|
17
|
+
tail -n +2 "$file" | while IFS=, read -r tool owner cost last_active; do
|
|
18
|
+
last_epoch=$(date -j -f %Y-%m-%d "$last_active" +%s 2>/dev/null || date -d "$last_active" +%s);
|
|
19
|
+
days=$(( (today-last_epoch)/86400 ));
|
|
20
|
+
if [ "$days" -gt "$unused_days" ]; then echo "UNUSED SEAT: $tool - $owner (\$$cost/mo) - inactive $days days"; fi
|
|
21
|
+
done
|
|
22
|
+
variables:
|
|
23
|
+
seats_file:
|
|
24
|
+
default: "./saas-seats.csv"
|
|
25
|
+
description: >
|
|
26
|
+
CSV with header "tool,seat_owner,monthly_cost,last_active_date"
|
|
27
|
+
(YYYY-MM-DD), one seat per row.
|
|
28
|
+
unused_days:
|
|
29
|
+
default: 30
|
|
30
|
+
description: Flag a seat if it hasn't been active in this many days.
|
|
31
|
+
compatible_agents: [generic, claude, codex]
|
|
32
|
+
notes: >
|
|
33
|
+
Zero-token, deterministic. You maintain saas-seats.csv yourself (or
|
|
34
|
+
export last-active data from your SSO/IdP if it tracks that) — this job
|
|
35
|
+
only reads what's in the file, doesn't pull from any SaaS API.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
id: subscription-audit
|
|
2
|
+
version: 1
|
|
3
|
+
name: Subscription Audit
|
|
4
|
+
description: >
|
|
5
|
+
Flags recurring subscriptions you haven't actually used in a while.
|
|
6
|
+
Use this if you suspect you're paying for things you forgot to cancel.
|
|
7
|
+
category: finance
|
|
8
|
+
tags: [subscriptions, budget, finance]
|
|
9
|
+
schedule: "0 9 1 * *"
|
|
10
|
+
timezone: "UTC"
|
|
11
|
+
runner: shell
|
|
12
|
+
command: >
|
|
13
|
+
file={{subs_file}}; unused_days={{unused_days}};
|
|
14
|
+
[ -f "$file" ] || { echo "ERROR: $file not found"; exit 1; };
|
|
15
|
+
today=$(date +%s);
|
|
16
|
+
tail -n +2 "$file" | while IFS=, read -r name cost last_used; do
|
|
17
|
+
last_epoch=$(date -j -f %Y-%m-%d "$last_used" +%s 2>/dev/null || date -d "$last_used" +%s);
|
|
18
|
+
days=$(( (today-last_epoch)/86400 ));
|
|
19
|
+
if [ "$days" -gt "$unused_days" ]; then echo "UNUSED: $name (\$$cost/mo) — not used in $days days"; fi
|
|
20
|
+
done
|
|
21
|
+
variables:
|
|
22
|
+
subs_file:
|
|
23
|
+
default: "./subscriptions.csv"
|
|
24
|
+
description: >
|
|
25
|
+
CSV with header "name,monthly_cost,last_used_date" (YYYY-MM-DD), one
|
|
26
|
+
subscription per row.
|
|
27
|
+
unused_days:
|
|
28
|
+
default: 30
|
|
29
|
+
description: Flag a subscription if it hasn't been used in this many days.
|
|
30
|
+
compatible_agents: [generic, claude, codex]
|
|
31
|
+
notes: >
|
|
32
|
+
Zero-token, deterministic. You maintain subs_file yourself (update
|
|
33
|
+
last_used_date when you actually use each service) — this job only
|
|
34
|
+
reads what's in the file, doesn't pull from any bank or card statement.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
id: course-progress-checkin
|
|
2
|
+
version: 1
|
|
3
|
+
name: Course Progress Check-in
|
|
4
|
+
description: >
|
|
5
|
+
Compares your current chapter/lesson against a target date and tells
|
|
6
|
+
you if you're on track or falling behind. Use this if you've ever
|
|
7
|
+
signed up for a course and quietly stopped halfway through.
|
|
8
|
+
category: learning
|
|
9
|
+
tags: [learning, goals, progress]
|
|
10
|
+
schedule: "0 9 * * 1"
|
|
11
|
+
timezone: "America/Los_Angeles"
|
|
12
|
+
runner: shell
|
|
13
|
+
command: >
|
|
14
|
+
current={{current_chapter}}; target={{target_chapter}}; target_date={{target_date}};
|
|
15
|
+
today_epoch=$(date +%s);
|
|
16
|
+
target_epoch=$(date -j -f %Y-%m-%d "$target_date" +%s 2>/dev/null || date -d "$target_date" +%s);
|
|
17
|
+
days_left=$(( (target_epoch-today_epoch)/86400 ));
|
|
18
|
+
chapters_left=$(( target - current ));
|
|
19
|
+
if [ "$chapters_left" -le 0 ]; then echo "OK: at or past target chapter $target already.";
|
|
20
|
+
elif [ "$days_left" -le 0 ]; then echo "OVERDUE: target date was $target_date, still $chapters_left chapter(s) to go.";
|
|
21
|
+
elif [ "$chapters_left" -gt "$days_left" ]; then echo "BEHIND: $chapters_left chapter(s) left, only $days_left day(s) until $target_date.";
|
|
22
|
+
else echo "ON TRACK: $chapters_left chapter(s) left, $days_left day(s) until $target_date."; fi
|
|
23
|
+
variables:
|
|
24
|
+
current_chapter:
|
|
25
|
+
default: 1
|
|
26
|
+
description: Chapter/lesson number you're currently on — update this yourself as you progress.
|
|
27
|
+
target_chapter:
|
|
28
|
+
default: 10
|
|
29
|
+
description: Chapter/lesson number you want to finish by target_date.
|
|
30
|
+
target_date:
|
|
31
|
+
default: "2026-12-31"
|
|
32
|
+
description: Date (YYYY-MM-DD) you want to hit target_chapter by.
|
|
33
|
+
compatible_agents: [generic, claude, codex]
|
|
34
|
+
notes: >
|
|
35
|
+
Zero-token. "Behind/on track" is a rough linear heuristic (chapters-left
|
|
36
|
+
vs. days-left), not a real study-pace model. You update current_chapter
|
|
37
|
+
yourself as you go.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
id: daily-flashcard-review
|
|
2
|
+
version: 1
|
|
3
|
+
name: Daily Flashcard Review
|
|
4
|
+
description: >
|
|
5
|
+
Lists which flashcards are due for review today from a simple deck
|
|
6
|
+
file. Use this if you're learning something with spaced repetition but
|
|
7
|
+
don't want a whole separate app for it.
|
|
8
|
+
category: learning
|
|
9
|
+
tags: [learning, flashcards, spaced-repetition]
|
|
10
|
+
schedule: "0 8 * * *"
|
|
11
|
+
timezone: "America/Los_Angeles"
|
|
12
|
+
runner: shell
|
|
13
|
+
command: >
|
|
14
|
+
deck={{deck_path}};
|
|
15
|
+
[ -f "$deck" ] || { echo "ERROR: $deck not found"; exit 1; };
|
|
16
|
+
today=$(date +%F);
|
|
17
|
+
due=$(awk -F, -v today="$today" 'NR>1 && $3<=today {print $1" -> "$2" (due "$3")"}' "$deck");
|
|
18
|
+
if [ -z "$due" ]; then echo "No cards due today.";
|
|
19
|
+
else echo "Cards due today:"; echo "$due"; fi
|
|
20
|
+
variables:
|
|
21
|
+
deck_path:
|
|
22
|
+
default: "./flashcards.csv"
|
|
23
|
+
description: CSV with header "front,back,next_review_date" (YYYY-MM-DD).
|
|
24
|
+
compatible_agents: [generic, claude, codex]
|
|
25
|
+
notes: >
|
|
26
|
+
Zero-token. You maintain flashcards.csv and update each card's
|
|
27
|
+
next_review_date yourself after reviewing — this is simple date-based
|
|
28
|
+
scheduling, not full SM-2 spaced repetition. This job only tells you
|
|
29
|
+
what's due, it doesn't reschedule cards for you.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
id: reading-list-nudge
|
|
2
|
+
version: 1
|
|
3
|
+
name: Reading List Nudge
|
|
4
|
+
description: >
|
|
5
|
+
Reminds you what's next on your reading list. Use this if you save
|
|
6
|
+
articles/books to "read later" and later never comes.
|
|
7
|
+
category: learning
|
|
8
|
+
tags: [learning, reading, reminder]
|
|
9
|
+
schedule: "0 9 * * 6"
|
|
10
|
+
timezone: "America/Los_Angeles"
|
|
11
|
+
runner: shell
|
|
12
|
+
command: >
|
|
13
|
+
file={{reading_list_path}};
|
|
14
|
+
[ -f "$file" ] || { echo "ERROR: $file not found"; exit 1; };
|
|
15
|
+
next=$(head -n 1 "$file");
|
|
16
|
+
if [ -z "$next" ]; then echo "Reading list is empty — nice work.";
|
|
17
|
+
else echo "Next up: $next"; fi
|
|
18
|
+
variables:
|
|
19
|
+
reading_list_path:
|
|
20
|
+
default: "./reading-list.txt"
|
|
21
|
+
description: Plain text file, one item per line — the top line is treated as "next."
|
|
22
|
+
compatible_agents: [generic, claude, codex]
|
|
23
|
+
notes: >
|
|
24
|
+
Zero-token. Suggests the top line only — remove an item from
|
|
25
|
+
reading-list.txt yourself once you've read it, or reorder to reprioritize.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
id: screen-time-check
|
|
2
|
+
version: 1
|
|
3
|
+
name: Screen Time Check
|
|
4
|
+
description: >
|
|
5
|
+
Checks today's screen time against a goal and tells you if you're over.
|
|
6
|
+
Use this if you're trying to cut down on screen time but never actually
|
|
7
|
+
look at the stats your phone/laptop already collects.
|
|
8
|
+
category: personal
|
|
9
|
+
tags: [health, screen-time, wellbeing]
|
|
10
|
+
schedule: "0 20 * * *"
|
|
11
|
+
timezone: "America/Los_Angeles"
|
|
12
|
+
runner: agent-prompt
|
|
13
|
+
prompt: |
|
|
14
|
+
Check today's screen time against a {{daily_limit_hours}} hour goal.
|
|
15
|
+
1. Use whatever screen-time source you have access to (macOS Screen
|
|
16
|
+
Time, iOS Screen Time via Shortcuts, Android Digital Wellbeing,
|
|
17
|
+
RescueTime, etc.).
|
|
18
|
+
2. Report total screen time so far today vs. the goal.
|
|
19
|
+
3. If over goal, note the top 3 apps/categories driving it.
|
|
20
|
+
variables:
|
|
21
|
+
daily_limit_hours:
|
|
22
|
+
default: 3
|
|
23
|
+
description: Daily screen time goal, in hours.
|
|
24
|
+
compatible_agents: [claude, codex, hermes, openclaw, generic]
|
|
25
|
+
notes: >
|
|
26
|
+
No generic script mode — screen-time data access is platform/tool
|
|
27
|
+
specific and usually needs OS-level permissions your agent may not have.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
id: water-intake-reminder
|
|
2
|
+
version: 1
|
|
3
|
+
name: Water Intake Reminder
|
|
4
|
+
description: >
|
|
5
|
+
Nudges you to drink water a few times a day toward a daily goal. Use
|
|
6
|
+
this if you sit at a desk all day and forget to drink water until
|
|
7
|
+
you've got a headache.
|
|
8
|
+
category: personal
|
|
9
|
+
tags: [health, hydration, reminder]
|
|
10
|
+
schedule: "0 9,12,15,18 * * *"
|
|
11
|
+
timezone: "America/Los_Angeles"
|
|
12
|
+
runner: shell
|
|
13
|
+
command: >
|
|
14
|
+
echo "Reminder: drink some water. Goal: {{daily_goal_oz}} oz today."
|
|
15
|
+
variables:
|
|
16
|
+
daily_goal_oz:
|
|
17
|
+
default: 64
|
|
18
|
+
description: Your daily water intake goal, in ounces.
|
|
19
|
+
compatible_agents: [generic, claude, codex]
|
|
20
|
+
notes: Zero-token. Purely a nudge — doesn't track actual intake.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
id: focus-block-reminder
|
|
2
|
+
version: 1
|
|
3
|
+
name: Focus Block Reminder
|
|
4
|
+
description: >
|
|
5
|
+
Nudges you to start a deep-work block at set times. Use this if your
|
|
6
|
+
day fills up with reactive work and real focus time only happens by
|
|
7
|
+
accident.
|
|
8
|
+
category: productivity
|
|
9
|
+
tags: [focus, productivity, deep-work]
|
|
10
|
+
schedule: "0 9,14 * * 1-5"
|
|
11
|
+
timezone: "America/Los_Angeles"
|
|
12
|
+
runner: shell
|
|
13
|
+
command: >
|
|
14
|
+
echo "Focus block: {{block_minutes}} minutes on \"{{focus_task}}\" starting now. Silence notifications."
|
|
15
|
+
variables:
|
|
16
|
+
focus_task:
|
|
17
|
+
default: "deep work"
|
|
18
|
+
description: What to focus on for this block.
|
|
19
|
+
block_minutes:
|
|
20
|
+
default: 50
|
|
21
|
+
description: Length of the focus block in minutes.
|
|
22
|
+
compatible_agents: [generic, claude, codex]
|
|
23
|
+
notes: >
|
|
24
|
+
Zero-token. Purely a nudge — doesn't block notifications/apps itself;
|
|
25
|
+
pair with your OS's focus/DND mode if you want it enforced.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
id: failed-login-watch
|
|
2
|
+
version: 1
|
|
3
|
+
name: Failed Login Watch
|
|
4
|
+
description: >
|
|
5
|
+
Watches an auth log for a burst of failed login attempts and alerts if
|
|
6
|
+
it crosses a threshold. Use this if you run a server exposed to SSH and
|
|
7
|
+
want an early warning for brute-force attempts.
|
|
8
|
+
category: security
|
|
9
|
+
tags: [security, auth, monitoring]
|
|
10
|
+
schedule: "*/15 * * * *"
|
|
11
|
+
timezone: "UTC"
|
|
12
|
+
runner: shell
|
|
13
|
+
command: >
|
|
14
|
+
log={{auth_log_path}}; state={{state_file}}; threshold={{fail_threshold}};
|
|
15
|
+
[ -f "$log" ] || { echo "ERROR: $log not found"; exit 1; };
|
|
16
|
+
total=$(grep -c "Failed password" "$log");
|
|
17
|
+
last=$(cat "$state" 2>/dev/null || echo 0);
|
|
18
|
+
new=$(( total - last ));
|
|
19
|
+
[ "$new" -lt 0 ] && new=0;
|
|
20
|
+
echo "$total" > "$state";
|
|
21
|
+
if [ "$new" -ge "$threshold" ]; then echo "WARNING: $new new failed login attempt(s) since last check (threshold $threshold)"; exit 1;
|
|
22
|
+
else echo "OK: $new new failed login attempt(s) since last check"; fi
|
|
23
|
+
variables:
|
|
24
|
+
auth_log_path:
|
|
25
|
+
default: "/var/log/auth.log"
|
|
26
|
+
description: Path to the auth log to watch (Linux-style).
|
|
27
|
+
state_file:
|
|
28
|
+
default: "./.failed-login-watch-state"
|
|
29
|
+
description: File this job uses to remember the last count seen, so it only alerts on new failures.
|
|
30
|
+
fail_threshold:
|
|
31
|
+
default: 5
|
|
32
|
+
description: Alert if this many new failed attempts appear since the last check.
|
|
33
|
+
compatible_agents: [generic, claude, codex]
|
|
34
|
+
notes: >
|
|
35
|
+
Linux-oriented (/var/log/auth.log). On macOS, use
|
|
36
|
+
`log show --predicate 'eventMessage contains "authentication failure"'`
|
|
37
|
+
instead and adapt the command — this one won't work there as-is.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
id: open-port-check
|
|
2
|
+
version: 1
|
|
3
|
+
name: Expected Open Ports Check
|
|
4
|
+
description: >
|
|
5
|
+
Checks that the ports you expect to be open on a host actually are, and
|
|
6
|
+
flags any that aren't. Use this if a service has ever silently stopped
|
|
7
|
+
listening and you found out from a user instead of a monitor.
|
|
8
|
+
category: security
|
|
9
|
+
tags: [security, network, ports]
|
|
10
|
+
schedule: "0 */4 * * *"
|
|
11
|
+
timezone: "UTC"
|
|
12
|
+
runner: shell
|
|
13
|
+
command: >
|
|
14
|
+
host={{host}}; fail=0;
|
|
15
|
+
for p in $(echo "{{expected_open_ports}}" | tr ',' ' '); do
|
|
16
|
+
if command -v nc >/dev/null 2>&1; then
|
|
17
|
+
nc -z -w2 "$host" "$p" 2>/dev/null && echo "OK: $host:$p open" || { echo "MISSING: $host:$p expected open but isn't"; fail=1; };
|
|
18
|
+
else
|
|
19
|
+
(echo > /dev/tcp/$host/$p) 2>/dev/null && echo "OK: $host:$p open" || { echo "MISSING: $host:$p expected open but isn't"; fail=1; };
|
|
20
|
+
fi
|
|
21
|
+
done;
|
|
22
|
+
exit $fail
|
|
23
|
+
variables:
|
|
24
|
+
host:
|
|
25
|
+
default: "localhost"
|
|
26
|
+
description: Host to check.
|
|
27
|
+
expected_open_ports:
|
|
28
|
+
default: "22,80,443"
|
|
29
|
+
description: Comma-separated list of ports that should be open.
|
|
30
|
+
compatible_agents: [generic, claude, codex]
|
|
31
|
+
notes: >
|
|
32
|
+
Zero-token. Checks only the ports you list — not a full port scan. Use
|
|
33
|
+
nmap for broader unexpected-open-port discovery. The nc branch (used on
|
|
34
|
+
virtually every system) is the tested path; the /dev/tcp fallback only
|
|
35
|
+
matters if nc is missing and requires bash specifically — it won't work
|
|
36
|
+
under dash/POSIX sh.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
id: secrets-scan
|
|
2
|
+
version: 1
|
|
3
|
+
name: Committed Secrets Scan
|
|
4
|
+
description: >
|
|
5
|
+
Scans a repo for accidentally committed API keys, tokens, and private
|
|
6
|
+
keys. Use this if you want a safety net for the "oops, committed a key"
|
|
7
|
+
mistake everyone makes eventually.
|
|
8
|
+
category: security
|
|
9
|
+
tags: [security, secrets, scanning]
|
|
10
|
+
schedule: "0 3 * * *"
|
|
11
|
+
timezone: "UTC"
|
|
12
|
+
runner: shell
|
|
13
|
+
command: >
|
|
14
|
+
cd {{repo_path}} &&
|
|
15
|
+
if command -v gitleaks >/dev/null 2>&1; then
|
|
16
|
+
gitleaks detect --source . --no-git -v;
|
|
17
|
+
else
|
|
18
|
+
echo "gitleaks not installed, falling back to basic pattern matching";
|
|
19
|
+
grep -rnE "(AKIA[0-9A-Z]{16}|-----BEGIN (RSA|EC|DSA|OPENSSH) PRIVATE KEY-----|api[_-]?key['\"]?[[:space:]]*[:=][[:space:]]*['\"][A-Za-z0-9_-]{16,})" --exclude-dir=.git --exclude-dir=node_modules . || echo "no matches found";
|
|
20
|
+
fi
|
|
21
|
+
variables:
|
|
22
|
+
repo_path:
|
|
23
|
+
default: "."
|
|
24
|
+
description: Path to the repo to scan.
|
|
25
|
+
compatible_agents: [generic, claude, codex]
|
|
26
|
+
notes: >
|
|
27
|
+
Zero-token. Prefers `gitleaks` if installed (far more accurate); the
|
|
28
|
+
fallback regex is best-effort and will miss many patterns or false-positive.
|