@wonsukchoi/crondex 0.3.0 → 0.4.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 CHANGED
@@ -62,7 +62,8 @@ crondex/
62
62
  │ ├── content/
63
63
  │ ├── finance/
64
64
  │ ├── security/
65
- └── learning/
65
+ ├── learning/
66
+ │ └── team/
66
67
  └── scripts/
67
68
  ├── build-catalog.js regenerates catalog.json from jobs/**/*.yaml
68
69
  └── validate-jobs.js validates every job against the schema
@@ -70,7 +71,7 @@ crondex/
70
71
 
71
72
  ## Available jobs
72
73
 
73
- 35 jobs across 7 categories. Full details (description, tags, variables)
74
+ 46 jobs across 8 categories. Full details (description, tags, variables)
74
75
  live in `catalog.json` and each job's YAML file — run `crondex list` or
75
76
  browse `jobs/<category>/` for the plain-language rundown of each.
76
77
 
@@ -92,6 +93,9 @@ browse `jobs/<category>/` for the plain-language rundown of each.
92
93
  | `db-backup-verify` | `0 5 * * *` | script |
93
94
  | `license-compliance-check` | `0 8 * * 1` | script |
94
95
  | `orphaned-branch-cleanup` | `0 9 * * 1` | script |
96
+ | `dns-record-check` | `0 */6 * * *` | script |
97
+ | `queue-depth-check` | `*/10 * * * *` | script |
98
+ | `api-rate-limit-check` | `*/15 * * * *` | script |
95
99
 
96
100
  **productivity**
97
101
 
@@ -119,6 +123,8 @@ browse `jobs/<category>/` for the plain-language rundown of each.
119
123
  | `changelog-digest` | `0 10 * * 5` | script + agent-prompt |
120
124
  | `broken-link-check` | `0 7 * * 1` | script |
121
125
  | `social-mentions-watch` | `0 9 * * *` | agent-prompt only |
126
+ | `seo-meta-check` | `0 7 * * 1` | script |
127
+ | `rss-feed-validate` | `0 8 * * *` | script |
122
128
 
123
129
  **finance**
124
130
 
@@ -127,6 +133,8 @@ browse `jobs/<category>/` for the plain-language rundown of each.
127
133
  | `subscription-audit` | `0 9 1 * *` | script |
128
134
  | `net-worth-snapshot` | `0 9 1 * *` | script |
129
135
  | `saas-seat-audit` | `0 9 1 * *` | script |
136
+ | `invoice-overdue-check` | `0 9 * * *` | script |
137
+ | `tax-deadline-reminder` | `0 9 * * *` | script |
130
138
 
131
139
  **security**
132
140
 
@@ -135,6 +143,8 @@ browse `jobs/<category>/` for the plain-language rundown of each.
135
143
  | `secrets-scan` | `0 3 * * *` | script |
136
144
  | `open-port-check` | `0 */4 * * *` | script |
137
145
  | `failed-login-watch` | `*/15 * * * *` | script |
146
+ | `sudo-usage-audit` | `0 * * * *` | script |
147
+ | `firewall-rule-diff` | `0 6 * * *` | script |
138
148
 
139
149
  **learning**
140
150
 
@@ -144,6 +154,13 @@ browse `jobs/<category>/` for the plain-language rundown of each.
144
154
  | `reading-list-nudge` | `0 9 * * 6` | script |
145
155
  | `course-progress-checkin` | `0 9 * * 1` | script |
146
156
 
157
+ **team**
158
+
159
+ | id | schedule | modes |
160
+ |---|---|---|
161
+ | `1on1-prep-reminder` | `0 9 * * 3` | script |
162
+ | `pto-balance-check` | `0 9 1 * *` | script |
163
+
147
164
  ## How a job works
148
165
 
149
166
  Every job is one YAML file with a `runner`:
package/catalog.json CHANGED
@@ -1,8 +1,56 @@
1
1
  {
2
2
  "generated_by": "scripts/build-catalog.js",
3
3
  "schema": "schema/job.schema.json",
4
- "count": 35,
4
+ "count": 46,
5
5
  "jobs": [
6
+ {
7
+ "id": "1on1-prep-reminder",
8
+ "version": 1,
9
+ "name": "1:1 Prep Reminder",
10
+ "description": "Nudges you to prep talking points before a recurring 1:1 and shows your last notes. Use this if you've ever walked into a 1:1 with nothing prepared and just winged it.",
11
+ "category": "team",
12
+ "tags": [
13
+ "1on1",
14
+ "meetings",
15
+ "team"
16
+ ],
17
+ "schedule": "0 9 * * 3",
18
+ "timezone": "America/Los_Angeles",
19
+ "runner": "shell",
20
+ "modes": [
21
+ "script"
22
+ ],
23
+ "compatible_agents": [
24
+ "generic",
25
+ "claude",
26
+ "codex"
27
+ ],
28
+ "path": "jobs/team/1on1-prep-reminder.yaml"
29
+ },
30
+ {
31
+ "id": "api-rate-limit-check",
32
+ "version": 1,
33
+ "name": "API Rate Limit Check",
34
+ "description": "Checks how many API requests you have left before hitting a rate limit. Use this if you've ever gotten a 429 in production because nobody was watching the remaining quota.",
35
+ "category": "devops",
36
+ "tags": [
37
+ "api",
38
+ "rate-limit",
39
+ "monitoring"
40
+ ],
41
+ "schedule": "*/15 * * * *",
42
+ "timezone": "UTC",
43
+ "runner": "shell",
44
+ "modes": [
45
+ "script"
46
+ ],
47
+ "compatible_agents": [
48
+ "generic",
49
+ "claude",
50
+ "codex"
51
+ ],
52
+ "path": "jobs/devops/api-rate-limit-check.yaml"
53
+ },
6
54
  {
7
55
  "id": "backup-reminder",
8
56
  "version": 1,
@@ -279,6 +327,30 @@
279
327
  ],
280
328
  "path": "jobs/devops/disk-space-check.yaml"
281
329
  },
330
+ {
331
+ "id": "dns-record-check",
332
+ "version": 1,
333
+ "name": "DNS Record Drift Check",
334
+ "description": "Checks that a DNS record still resolves to the value you expect, and flags drift. Use this if you've ever had DNS quietly change (an expired record, a misconfigured provider) and only found out when something broke.",
335
+ "category": "devops",
336
+ "tags": [
337
+ "dns",
338
+ "monitoring",
339
+ "drift"
340
+ ],
341
+ "schedule": "0 */6 * * *",
342
+ "timezone": "UTC",
343
+ "runner": "shell",
344
+ "modes": [
345
+ "script"
346
+ ],
347
+ "compatible_agents": [
348
+ "generic",
349
+ "claude",
350
+ "codex"
351
+ ],
352
+ "path": "jobs/devops/dns-record-check.yaml"
353
+ },
282
354
  {
283
355
  "id": "docker-image-prune",
284
356
  "version": 1,
@@ -351,6 +423,30 @@
351
423
  ],
352
424
  "path": "jobs/security/failed-login-watch.yaml"
353
425
  },
426
+ {
427
+ "id": "firewall-rule-diff",
428
+ "version": 1,
429
+ "name": "Firewall Rule Diff",
430
+ "description": "Diffs your current firewall rules against a saved baseline and flags any drift. Use this if a firewall rule has ever changed without anyone remembering who did it or why.",
431
+ "category": "security",
432
+ "tags": [
433
+ "security",
434
+ "firewall",
435
+ "drift"
436
+ ],
437
+ "schedule": "0 6 * * *",
438
+ "timezone": "UTC",
439
+ "runner": "shell",
440
+ "modes": [
441
+ "script"
442
+ ],
443
+ "compatible_agents": [
444
+ "generic",
445
+ "claude",
446
+ "codex"
447
+ ],
448
+ "path": "jobs/security/firewall-rule-diff.yaml"
449
+ },
354
450
  {
355
451
  "id": "focus-block-reminder",
356
452
  "version": 1,
@@ -425,6 +521,30 @@
425
521
  ],
426
522
  "path": "jobs/productivity/inbox-triage.yaml"
427
523
  },
524
+ {
525
+ "id": "invoice-overdue-check",
526
+ "version": 1,
527
+ "name": "Invoice Overdue Check",
528
+ "description": "Flags invoices that are past due and still unpaid. Use this if you freelance or run a small business and invoices have ever slipped through the cracks.",
529
+ "category": "finance",
530
+ "tags": [
531
+ "invoices",
532
+ "accounts-receivable",
533
+ "finance"
534
+ ],
535
+ "schedule": "0 9 * * *",
536
+ "timezone": "UTC",
537
+ "runner": "shell",
538
+ "modes": [
539
+ "script"
540
+ ],
541
+ "compatible_agents": [
542
+ "generic",
543
+ "claude",
544
+ "codex"
545
+ ],
546
+ "path": "jobs/finance/invoice-overdue-check.yaml"
547
+ },
428
548
  {
429
549
  "id": "license-compliance-check",
430
550
  "version": 1,
@@ -571,6 +691,54 @@
571
691
  ],
572
692
  "path": "jobs/devops/orphaned-branch-cleanup.yaml"
573
693
  },
694
+ {
695
+ "id": "pto-balance-check",
696
+ "version": 1,
697
+ "name": "PTO Balance Check",
698
+ "description": "Warns you before unused PTO expires or resets. Use this if you've ever lost vacation days because you forgot they don't roll over.",
699
+ "category": "team",
700
+ "tags": [
701
+ "pto",
702
+ "vacation",
703
+ "team"
704
+ ],
705
+ "schedule": "0 9 1 * *",
706
+ "timezone": "America/Los_Angeles",
707
+ "runner": "shell",
708
+ "modes": [
709
+ "script"
710
+ ],
711
+ "compatible_agents": [
712
+ "generic",
713
+ "claude",
714
+ "codex"
715
+ ],
716
+ "path": "jobs/team/pto-balance-check.yaml"
717
+ },
718
+ {
719
+ "id": "queue-depth-check",
720
+ "version": 1,
721
+ "name": "Queue Depth Check",
722
+ "description": "Checks how backed up a job queue is and warns if it crosses a threshold. Use this if a stuck worker has ever let a queue silently balloon until someone noticed customers weren't getting emails.",
723
+ "category": "devops",
724
+ "tags": [
725
+ "queue",
726
+ "redis",
727
+ "monitoring"
728
+ ],
729
+ "schedule": "*/10 * * * *",
730
+ "timezone": "UTC",
731
+ "runner": "shell",
732
+ "modes": [
733
+ "script"
734
+ ],
735
+ "compatible_agents": [
736
+ "generic",
737
+ "claude",
738
+ "codex"
739
+ ],
740
+ "path": "jobs/devops/queue-depth-check.yaml"
741
+ },
574
742
  {
575
743
  "id": "reading-list-nudge",
576
744
  "version": 1,
@@ -622,6 +790,30 @@
622
790
  ],
623
791
  "path": "jobs/devops/repo-health-check.yaml"
624
792
  },
793
+ {
794
+ "id": "rss-feed-validate",
795
+ "version": 1,
796
+ "name": "RSS Feed Validation",
797
+ "description": "Checks your RSS/Atom feed is valid XML and shows the most recent item's publish date. Use this if you've ever shipped a broken feed and only found out when a reader's app stopped updating.",
798
+ "category": "content",
799
+ "tags": [
800
+ "rss",
801
+ "feed",
802
+ "content"
803
+ ],
804
+ "schedule": "0 8 * * *",
805
+ "timezone": "UTC",
806
+ "runner": "shell",
807
+ "modes": [
808
+ "script"
809
+ ],
810
+ "compatible_agents": [
811
+ "generic",
812
+ "claude",
813
+ "codex"
814
+ ],
815
+ "path": "jobs/content/rss-feed-validate.yaml"
816
+ },
625
817
  {
626
818
  "id": "saas-seat-audit",
627
819
  "version": 1,
@@ -697,6 +889,30 @@
697
889
  ],
698
890
  "path": "jobs/security/secrets-scan.yaml"
699
891
  },
892
+ {
893
+ "id": "seo-meta-check",
894
+ "version": 1,
895
+ "name": "SEO Meta Tag Check",
896
+ "description": "Checks a list of pages for missing title, meta description, and Open Graph tags. Use this if pages have ever shipped without basic SEO/social-preview tags because nobody double-checked.",
897
+ "category": "content",
898
+ "tags": [
899
+ "seo",
900
+ "content",
901
+ "meta-tags"
902
+ ],
903
+ "schedule": "0 7 * * 1",
904
+ "timezone": "UTC",
905
+ "runner": "shell",
906
+ "modes": [
907
+ "script"
908
+ ],
909
+ "compatible_agents": [
910
+ "generic",
911
+ "claude",
912
+ "codex"
913
+ ],
914
+ "path": "jobs/content/seo-meta-check.yaml"
915
+ },
700
916
  {
701
917
  "id": "social-mentions-watch",
702
918
  "version": 1,
@@ -796,6 +1012,54 @@
796
1012
  ],
797
1013
  "path": "jobs/finance/subscription-audit.yaml"
798
1014
  },
1015
+ {
1016
+ "id": "sudo-usage-audit",
1017
+ "version": 1,
1018
+ "name": "Sudo Usage Audit",
1019
+ "description": "Reports new sudo commands run since the last check. Use this if you want to notice unexpected privilege escalation on a shared or internet-facing server.",
1020
+ "category": "security",
1021
+ "tags": [
1022
+ "security",
1023
+ "sudo",
1024
+ "audit"
1025
+ ],
1026
+ "schedule": "0 * * * *",
1027
+ "timezone": "UTC",
1028
+ "runner": "shell",
1029
+ "modes": [
1030
+ "script"
1031
+ ],
1032
+ "compatible_agents": [
1033
+ "generic",
1034
+ "claude",
1035
+ "codex"
1036
+ ],
1037
+ "path": "jobs/security/sudo-usage-audit.yaml"
1038
+ },
1039
+ {
1040
+ "id": "tax-deadline-reminder",
1041
+ "version": 1,
1042
+ "name": "Tax Deadline Reminder",
1043
+ "description": "Warns you ahead of upcoming tax deadlines you've listed. Use this if quarterly estimated payments or annual filing dates have ever snuck up on you.",
1044
+ "category": "finance",
1045
+ "tags": [
1046
+ "tax",
1047
+ "deadlines",
1048
+ "finance"
1049
+ ],
1050
+ "schedule": "0 9 * * *",
1051
+ "timezone": "UTC",
1052
+ "runner": "shell",
1053
+ "modes": [
1054
+ "script"
1055
+ ],
1056
+ "compatible_agents": [
1057
+ "generic",
1058
+ "claude",
1059
+ "codex"
1060
+ ],
1061
+ "path": "jobs/finance/tax-deadline-reminder.yaml"
1062
+ },
799
1063
  {
800
1064
  "id": "uptime-ping-check",
801
1065
  "version": 1,
@@ -0,0 +1,32 @@
1
+ id: rss-feed-validate
2
+ version: 1
3
+ name: RSS Feed Validation
4
+ description: >
5
+ Checks your RSS/Atom feed is valid XML and shows the most recent
6
+ item's publish date. Use this if you've ever shipped a broken feed
7
+ and only found out when a reader's app stopped updating.
8
+ category: content
9
+ tags: [rss, feed, content]
10
+ schedule: "0 8 * * *"
11
+ timezone: "UTC"
12
+ runner: shell
13
+ command: >
14
+ url={{feed_url}};
15
+ xml=$(curl -sL --max-time 10 "$url");
16
+ [ -z "$xml" ] && { echo "ERROR: could not fetch $url"; exit 1; };
17
+ if command -v xmllint >/dev/null 2>&1; then
18
+ echo "$xml" | xmllint --noout - 2>&1 && echo "OK: valid XML" || { echo "INVALID XML"; exit 1; };
19
+ else
20
+ echo "xmllint not installed, skipping strict XML validation";
21
+ fi;
22
+ pubdate=$(echo "$xml" | grep -oE "<pubDate>[^<]+</pubDate>" | head -n1 | sed 's/<[^>]*>//g');
23
+ echo "Most recent item pubDate: ${pubdate:-unknown}"
24
+ variables:
25
+ feed_url:
26
+ default: "https://example.com/feed.xml"
27
+ description: URL of the RSS/Atom feed to check.
28
+ compatible_agents: [generic, claude, codex]
29
+ notes: >
30
+ Zero-token. Only reports the latest pubDate for you to eyeball —
31
+ doesn't flag "stale" automatically since feed cadences vary too much
32
+ for one threshold. Install `xmllint` (libxml2) for strict validation.
@@ -0,0 +1,32 @@
1
+ id: seo-meta-check
2
+ version: 1
3
+ name: SEO Meta Tag Check
4
+ description: >
5
+ Checks a list of pages for missing title, meta description, and
6
+ Open Graph tags. Use this if pages have ever shipped without basic
7
+ SEO/social-preview tags because nobody double-checked.
8
+ category: content
9
+ tags: [seo, content, meta-tags]
10
+ schedule: "0 7 * * 1"
11
+ timezone: "UTC"
12
+ runner: shell
13
+ command: >
14
+ file={{urls_file}};
15
+ [ -f "$file" ] || { echo "ERROR: $file not found"; exit 1; };
16
+ while IFS= read -r url; do
17
+ [ -z "$url" ] && continue;
18
+ html=$(curl -sL --max-time 10 "$url");
19
+ missing="";
20
+ echo "$html" | grep -qi "<title>" || missing="$missing title";
21
+ echo "$html" | grep -qi 'name="description"' || missing="$missing meta-description";
22
+ echo "$html" | grep -qi 'property="og:title"' || missing="$missing og:title";
23
+ if [ -n "$missing" ]; then echo "MISSING on $url:$missing"; else echo "OK: $url"; fi
24
+ done < "$file"
25
+ variables:
26
+ urls_file:
27
+ default: "./pages.txt"
28
+ description: Plain text file with one page URL per line to check.
29
+ compatible_agents: [generic, claude, codex]
30
+ notes: >
31
+ Zero-token. Basic presence check only (does the tag exist), not content
32
+ quality — pair with a fuller SEO audit for anything deeper.
@@ -0,0 +1,31 @@
1
+ id: api-rate-limit-check
2
+ version: 1
3
+ name: API Rate Limit Check
4
+ description: >
5
+ Checks how many API requests you have left before hitting a rate
6
+ limit. Use this if you've ever gotten a 429 in production because
7
+ nobody was watching the remaining quota.
8
+ category: devops
9
+ tags: [api, rate-limit, monitoring]
10
+ schedule: "*/15 * * * *"
11
+ timezone: "UTC"
12
+ runner: shell
13
+ command: >
14
+ url={{api_url}};
15
+ headers=$(curl -sI --max-time 10 "$url");
16
+ remaining=$(echo "$headers" | grep -i "^x-ratelimit-remaining:" | awk '{print $2}' | tr -d '\r');
17
+ if [ -z "$remaining" ]; then echo "no rate-limit headers found on $url (nothing to check, or a different header convention)"; exit 0;
18
+ elif [ "$remaining" -le {{warn_threshold}} ]; then echo "WARNING: $url has only $remaining requests remaining"; exit 1;
19
+ else echo "OK: $url has $remaining requests remaining"; fi
20
+ variables:
21
+ api_url:
22
+ default: "https://api.example.com/status"
23
+ description: An endpoint on the API you want to watch — any request that returns rate-limit headers works.
24
+ warn_threshold:
25
+ default: 50
26
+ description: Warn if remaining requests drops to this or below.
27
+ compatible_agents: [generic, claude, codex]
28
+ notes: >
29
+ Assumes the standard `X-RateLimit-Remaining` response header — adjust
30
+ the grep pattern if your API uses a different convention
31
+ (e.g. `RateLimit-Remaining`, a custom header).
@@ -0,0 +1,32 @@
1
+ id: dns-record-check
2
+ version: 1
3
+ name: DNS Record Drift Check
4
+ description: >
5
+ Checks that a DNS record still resolves to the value you expect, and
6
+ flags drift. Use this if you've ever had DNS quietly change (an
7
+ expired record, a misconfigured provider) and only found out when
8
+ something broke.
9
+ category: devops
10
+ tags: [dns, monitoring, drift]
11
+ schedule: "0 */6 * * *"
12
+ timezone: "UTC"
13
+ runner: shell
14
+ command: >
15
+ domain={{domain}}; type={{record_type}}; expected="{{expected_value}}";
16
+ command -v dig >/dev/null 2>&1 || { echo "ERROR: dig not installed"; exit 1; };
17
+ actual=$(dig +short "$domain" "$type" | tr '\n' ' ' | sed 's/ *$//');
18
+ if [ -z "$actual" ]; then echo "ERROR: no $type record found for $domain"; exit 1;
19
+ elif echo "$actual" | grep -qF "$expected"; then echo "OK: $domain $type matches expected ($actual)";
20
+ else echo "DRIFT: $domain $type is '$actual', expected to contain '$expected'"; exit 1; fi
21
+ variables:
22
+ domain:
23
+ default: "example.com"
24
+ description: Domain to check.
25
+ record_type:
26
+ default: "A"
27
+ description: DNS record type (A, CNAME, TXT, MX, etc).
28
+ expected_value:
29
+ default: "93.184.216.34"
30
+ description: Value the record should contain — replace with your actual expected record.
31
+ compatible_agents: [generic, claude, codex]
32
+ notes: Zero-token, deterministic. Requires `dig` (part of dnsutils/bind-tools).
@@ -0,0 +1,35 @@
1
+ id: queue-depth-check
2
+ version: 1
3
+ name: Queue Depth Check
4
+ description: >
5
+ Checks how backed up a job queue is and warns if it crosses a
6
+ threshold. Use this if a stuck worker has ever let a queue silently
7
+ balloon until someone noticed customers weren't getting emails.
8
+ category: devops
9
+ tags: [queue, redis, monitoring]
10
+ schedule: "*/10 * * * *"
11
+ timezone: "UTC"
12
+ runner: shell
13
+ command: >
14
+ command -v redis-cli >/dev/null 2>&1 || { echo "ERROR: redis-cli not installed"; exit 1; };
15
+ depth=$(redis-cli -h {{redis_host}} -p {{redis_port}} llen {{queue_key}} 2>/dev/null);
16
+ if [ -z "$depth" ]; then echo "ERROR: could not read queue depth for {{queue_key}}"; exit 1;
17
+ elif [ "$depth" -ge {{threshold}} ]; then echo "WARNING: queue {{queue_key}} depth is $depth (threshold {{threshold}})"; exit 1;
18
+ else echo "OK: queue {{queue_key}} depth is $depth"; fi
19
+ variables:
20
+ redis_host:
21
+ default: "localhost"
22
+ description: Redis host.
23
+ redis_port:
24
+ default: 6379
25
+ description: Redis port.
26
+ queue_key:
27
+ default: "jobs:pending"
28
+ description: Redis list key backing the queue.
29
+ threshold:
30
+ default: 1000
31
+ description: Warn if the queue depth reaches this many items.
32
+ compatible_agents: [generic, claude, codex]
33
+ notes: >
34
+ Redis list-backed queues only (uses LLEN). Adapt the depth-check
35
+ command for RabbitMQ, SQS, or other queue systems.
@@ -0,0 +1,32 @@
1
+ id: invoice-overdue-check
2
+ version: 1
3
+ name: Invoice Overdue Check
4
+ description: >
5
+ Flags invoices that are past due and still unpaid. Use this if you
6
+ freelance or run a small business and invoices have ever slipped
7
+ through the cracks.
8
+ category: finance
9
+ tags: [invoices, accounts-receivable, finance]
10
+ schedule: "0 9 * * *"
11
+ timezone: "UTC"
12
+ runner: shell
13
+ command: >
14
+ file={{invoices_file}};
15
+ [ -f "$file" ] || { echo "ERROR: $file not found"; exit 1; };
16
+ today=$(date +%s);
17
+ tail -n +2 "$file" | while IFS=, read -r id client amount due paid; do
18
+ [ "$paid" = "yes" ] && continue;
19
+ due_epoch=$(date -j -f %Y-%m-%d "$due" +%s 2>/dev/null || date -d "$due" +%s);
20
+ days=$(( (today-due_epoch)/86400 ));
21
+ if [ "$days" -gt 0 ]; then echo "OVERDUE: invoice $id ($client, \$$amount) — $days day(s) past due ($due)"; fi
22
+ done
23
+ variables:
24
+ invoices_file:
25
+ default: "./invoices.csv"
26
+ description: >
27
+ CSV with header "invoice_id,client,amount,due_date,paid"
28
+ (due_date is YYYY-MM-DD, paid is yes/no).
29
+ compatible_agents: [generic, claude, codex]
30
+ notes: >
31
+ Zero-token. You maintain invoices.csv yourself (mark paid=yes once
32
+ settled) — this doesn't connect to any billing/accounting system.
@@ -0,0 +1,33 @@
1
+ id: tax-deadline-reminder
2
+ version: 1
3
+ name: Tax Deadline Reminder
4
+ description: >
5
+ Warns you ahead of upcoming tax deadlines you've listed. Use this if
6
+ quarterly estimated payments or annual filing dates have ever snuck
7
+ up on you.
8
+ category: finance
9
+ tags: [tax, deadlines, finance]
10
+ schedule: "0 9 * * *"
11
+ timezone: "UTC"
12
+ runner: shell
13
+ command: >
14
+ file={{deadlines_file}}; warn={{warn_days}};
15
+ [ -f "$file" ] || { echo "ERROR: $file not found"; exit 1; };
16
+ today=$(date +%s);
17
+ tail -n +2 "$file" | while IFS=, read -r label due; do
18
+ [ -z "$due" ] && continue;
19
+ due_epoch=$(date -j -f %Y-%m-%d "$due" +%s 2>/dev/null || date -d "$due" +%s);
20
+ days=$(( (due_epoch-today)/86400 ));
21
+ if [ "$days" -ge 0 ] && [ "$days" -le "$warn" ]; then echo "REMINDER: $label due in $days day(s) ($due)"; fi
22
+ done
23
+ variables:
24
+ deadlines_file:
25
+ default: "./tax-deadlines.csv"
26
+ description: CSV with header "label,date" (date is YYYY-MM-DD), one deadline per row.
27
+ warn_days:
28
+ default: 14
29
+ description: Start warning this many days before a deadline.
30
+ compatible_agents: [generic, claude, codex]
31
+ notes: >
32
+ Zero-token. You maintain tax-deadlines.csv yourself with your actual
33
+ jurisdiction's dates — this job doesn't know tax law or deadlines on its own.
@@ -0,0 +1,30 @@
1
+ id: firewall-rule-diff
2
+ version: 1
3
+ name: Firewall Rule Diff
4
+ description: >
5
+ Diffs your current firewall rules against a saved baseline and flags
6
+ any drift. Use this if a firewall rule has ever changed without
7
+ anyone remembering who did it or why.
8
+ category: security
9
+ tags: [security, firewall, drift]
10
+ schedule: "0 6 * * *"
11
+ timezone: "UTC"
12
+ runner: shell
13
+ command: >
14
+ baseline={{baseline_path}};
15
+ if command -v ufw >/dev/null 2>&1; then current=$(sudo ufw status verbose 2>/dev/null);
16
+ elif command -v iptables >/dev/null 2>&1; then current=$(sudo iptables -S 2>/dev/null);
17
+ else echo "ERROR: no supported firewall tool found (ufw/iptables)"; exit 1; fi;
18
+ if [ ! -f "$baseline" ]; then echo "$current" > "$baseline"; echo "no baseline found — saved current rules as the new baseline"; exit 0; fi;
19
+ if diff -q <(echo "$current") "$baseline" >/dev/null 2>&1; then echo "OK: firewall rules match baseline";
20
+ else echo "DRIFT: firewall rules differ from baseline:"; diff <(echo "$current") "$baseline"; exit 1; fi
21
+ variables:
22
+ baseline_path:
23
+ default: "./firewall-baseline.txt"
24
+ description: File storing the known-good firewall rule snapshot.
25
+ compatible_agents: [generic, claude, codex]
26
+ notes: >
27
+ Requires sudo access to read ufw/iptables rules (configure passwordless
28
+ sudo for this specific read-only command if running unattended). First
29
+ run saves the baseline; later runs diff against it. Requires bash
30
+ (process substitution).
@@ -0,0 +1,35 @@
1
+ id: sudo-usage-audit
2
+ version: 1
3
+ name: Sudo Usage Audit
4
+ description: >
5
+ Reports new sudo commands run since the last check. Use this if you
6
+ want to notice unexpected privilege escalation on a shared or
7
+ internet-facing server.
8
+ category: security
9
+ tags: [security, sudo, audit]
10
+ schedule: "0 * * * *"
11
+ timezone: "UTC"
12
+ runner: shell
13
+ command: >
14
+ log={{auth_log_path}}; state={{state_file}};
15
+ [ -f "$log" ] || { echo "ERROR: $log not found"; exit 1; };
16
+ total=$(grep -c "sudo:.*COMMAND=" "$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" -gt 0 ]; then
22
+ echo "New sudo commands since last check ($new):";
23
+ grep "sudo:.*COMMAND=" "$log" | tail -n "$new";
24
+ else echo "OK: no new sudo usage since last check"; fi
25
+ variables:
26
+ auth_log_path:
27
+ default: "/var/log/auth.log"
28
+ description: Path to the auth log (Linux-style).
29
+ state_file:
30
+ default: "./.sudo-audit-state"
31
+ description: File this job uses to remember the last count seen, so it only reports new entries.
32
+ compatible_agents: [generic, claude, codex]
33
+ notes: >
34
+ Linux-oriented (/var/log/auth.log with sudo entries). On macOS use
35
+ `log show --predicate 'process == "sudo"'` instead and adapt the command.
@@ -0,0 +1,26 @@
1
+ id: 1on1-prep-reminder
2
+ version: 1
3
+ name: 1:1 Prep Reminder
4
+ description: >
5
+ Nudges you to prep talking points before a recurring 1:1 and shows
6
+ your last notes. Use this if you've ever walked into a 1:1 with
7
+ nothing prepared and just winged it.
8
+ category: team
9
+ tags: [1on1, meetings, team]
10
+ schedule: "0 9 * * 3"
11
+ timezone: "America/Los_Angeles"
12
+ runner: shell
13
+ command: >
14
+ echo "1:1 with {{person_name}} coming up. Jot down talking points.";
15
+ if [ -f "{{notes_file}}" ]; then echo "--- last notes ---"; tail -n 10 "{{notes_file}}"; fi
16
+ variables:
17
+ person_name:
18
+ default: "your manager"
19
+ description: Who the 1:1 is with.
20
+ notes_file:
21
+ default: "./1on1-notes.txt"
22
+ description: Plain text file you append notes/action items to after each 1:1.
23
+ compatible_agents: [generic, claude, codex]
24
+ notes: >
25
+ Zero-token. Adjust the schedule to match your actual 1:1 day/time —
26
+ the default (Wednesday morning) is just a placeholder.
@@ -0,0 +1,33 @@
1
+ id: pto-balance-check
2
+ version: 1
3
+ name: PTO Balance Check
4
+ description: >
5
+ Warns you before unused PTO expires or resets. Use this if you've
6
+ ever lost vacation days because you forgot they don't roll over.
7
+ category: team
8
+ tags: [pto, vacation, team]
9
+ schedule: "0 9 1 * *"
10
+ timezone: "America/Los_Angeles"
11
+ runner: shell
12
+ command: >
13
+ today_epoch=$(date +%s);
14
+ expiry_epoch=$(date -j -f %Y-%m-%d "{{expiry_date}}" +%s 2>/dev/null || date -d "{{expiry_date}}" +%s);
15
+ days_left=$(( (expiry_epoch-today_epoch)/86400 ));
16
+ if [ "$days_left" -lt 0 ]; then echo "note: expiry date has passed — update expiry_date for the next period.";
17
+ elif [ "$days_left" -le {{warn_days_before_expiry}} ] && [ {{pto_balance_hours}} -gt 0 ]; then
18
+ echo "REMINDER: {{pto_balance_hours}}h PTO expires in $days_left day(s) (on {{expiry_date}}) — use it or lose it.";
19
+ else echo "OK: {{pto_balance_hours}}h PTO, $days_left day(s) until expiry."; fi
20
+ variables:
21
+ pto_balance_hours:
22
+ default: 40
23
+ description: Your current unused PTO balance, in hours — update this yourself as it changes.
24
+ expiry_date:
25
+ default: "2026-12-31"
26
+ description: Date (YYYY-MM-DD) this PTO expires or resets.
27
+ warn_days_before_expiry:
28
+ default: 30
29
+ description: Start warning this many days before expiry.
30
+ compatible_agents: [generic, claude, codex]
31
+ notes: >
32
+ Zero-token. You maintain pto_balance_hours and expiry_date yourself —
33
+ this doesn't pull from any HR system.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wonsukchoi/crondex",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "A public directory of pre-made, agent-editable cron jobs.",
5
5
  "type": "module",
6
6
  "license": "MIT",