@olegkoval/agent-skills 1.8.0 → 1.9.1
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/.claude-plugin/plugin.json +4 -2
- package/.cursor-plugin/index.json +10 -0
- package/.kiro/steering/obsidian-pr-sync.md +137 -0
- package/.kiro/steering/obsidian-task-rollover.md +180 -0
- package/.windsurf/rules/obsidian-pr-sync.md +136 -0
- package/.windsurf/rules/obsidian-task-rollover.md +179 -0
- package/README.md +4 -2
- package/catalog/skills.json +44 -0
- package/package.json +1 -1
- package/packages/marketing/search-console-indexing-audit/SKILL.md +1 -0
- package/packages/marketing/search-console-indexing-audit/adapters/claude/skills/search-console-indexing-audit/SKILL.md +1 -0
- package/packages/marketing/search-console-indexing-audit/adapters/cursor/skills/search-console-indexing-audit/SKILL.md +1 -0
- package/packages/marketing/viral-launch/SKILL.md +1 -0
- package/packages/marketing/viral-launch/adapters/claude/skills/viral-launch/SKILL.md +1 -0
- package/packages/marketing/viral-launch/adapters/cursor/skills/viral-launch/SKILL.md +1 -0
- package/packages/music/fill-music-player/SKILL.md +1 -0
- package/packages/music/fill-music-player/adapters/claude/skills/fill-music-player/SKILL.md +1 -0
- package/packages/music/fill-music-player/adapters/cursor/skills/fill-music-player/SKILL.md +1 -0
- package/packages/photography/gallery/SKILL.md +1 -0
- package/packages/photography/gallery/adapters/claude/skills/gallery/SKILL.md +1 -0
- package/packages/photography/gallery/adapters/cursor/skills/gallery/SKILL.md +1 -0
- package/packages/software-development/add-to-my-skills/SKILL.md +1 -0
- package/packages/software-development/add-to-my-skills/adapters/claude/skills/add-to-my-skills/SKILL.md +1 -0
- package/packages/software-development/add-to-my-skills/adapters/cursor/skills/add-to-my-skills/SKILL.md +1 -0
- package/packages/software-development/ai-tools-setup/SKILL.md +1 -0
- package/packages/software-development/ai-tools-setup/adapters/claude/skills/ai-tools-setup/SKILL.md +1 -0
- package/packages/software-development/ai-tools-setup/adapters/cursor/skills/ai-tools-setup/SKILL.md +1 -0
- package/packages/software-development/changelog-generator/SKILL.md +1 -0
- package/packages/software-development/changelog-generator/adapters/claude/skills/changelog-generator/SKILL.md +1 -0
- package/packages/software-development/changelog-generator/adapters/cursor/skills/changelog-generator/SKILL.md +1 -0
- package/packages/software-development/cloudflare-block-countries/SKILL.md +1 -0
- package/packages/software-development/cloudflare-block-countries/adapters/claude/skills/cloudflare-block-countries/SKILL.md +1 -0
- package/packages/software-development/cloudflare-block-countries/adapters/cursor/skills/cloudflare-block-countries/SKILL.md +1 -0
- package/packages/software-development/docs-index-keeper/SKILL.md +1 -0
- package/packages/software-development/docs-index-keeper/adapters/claude/skills/docs-index-keeper/SKILL.md +1 -0
- package/packages/software-development/docs-index-keeper/adapters/cursor/skills/docs-index-keeper/SKILL.md +1 -0
- package/packages/software-development/gh-cli/SKILL.md +1 -0
- package/packages/software-development/gh-cli/adapters/claude/skills/gh-cli/SKILL.md +1 -0
- package/packages/software-development/gh-cli/adapters/cursor/skills/gh-cli/SKILL.md +1 -0
- package/packages/software-development/git-commit/SKILL.md +1 -0
- package/packages/software-development/git-commit/adapters/claude/skills/git-commit/SKILL.md +1 -0
- package/packages/software-development/git-commit/adapters/cursor/skills/git-commit/SKILL.md +1 -0
- package/packages/software-development/obsidian-pr-sync/SKILL.md +152 -0
- package/packages/software-development/obsidian-pr-sync/adapters/claude/plugin.json +5 -0
- package/packages/software-development/obsidian-pr-sync/adapters/claude/skills/obsidian-pr-sync/SKILL.md +155 -0
- package/packages/software-development/obsidian-pr-sync/adapters/cursor/plugin.json +6 -0
- package/packages/software-development/obsidian-pr-sync/adapters/cursor/skills/obsidian-pr-sync/SKILL.md +155 -0
- package/packages/software-development/obsidian-pr-sync/adapters/kiro/steering/obsidian-pr-sync.md +137 -0
- package/packages/software-development/obsidian-pr-sync/adapters/windsurf/rules/obsidian-pr-sync.md +136 -0
- package/packages/software-development/obsidian-task-rollover/SKILL.md +196 -0
- package/packages/software-development/obsidian-task-rollover/adapters/claude/plugin.json +5 -0
- package/packages/software-development/obsidian-task-rollover/adapters/claude/skills/obsidian-task-rollover/SKILL.md +199 -0
- package/packages/software-development/obsidian-task-rollover/adapters/cursor/plugin.json +6 -0
- package/packages/software-development/obsidian-task-rollover/adapters/cursor/skills/obsidian-task-rollover/SKILL.md +199 -0
- package/packages/software-development/obsidian-task-rollover/adapters/kiro/steering/obsidian-task-rollover.md +180 -0
- package/packages/software-development/obsidian-task-rollover/adapters/windsurf/rules/obsidian-task-rollover.md +179 -0
- package/packages/software-development/open-source-publisher/SKILL.md +1 -0
- package/packages/software-development/open-source-publisher/adapters/claude/skills/open-source-publisher/SKILL.md +1 -0
- package/packages/software-development/open-source-publisher/adapters/cursor/skills/open-source-publisher/SKILL.md +1 -0
- package/packages/software-development/product-builder/SKILL.md +1 -0
- package/packages/software-development/product-builder/adapters/claude/skills/product-builder/SKILL.md +1 -0
- package/packages/software-development/product-builder/adapters/cursor/skills/product-builder/SKILL.md +1 -0
- package/packages/software-development/promptctl/SKILL.md +1 -0
- package/packages/software-development/promptctl/adapters/claude/skills/promptctl/SKILL.md +1 -0
- package/packages/software-development/promptctl/adapters/cursor/skills/promptctl/SKILL.md +1 -0
- package/packages/software-development/semantic-release-beta/SKILL.md +1 -0
- package/packages/software-development/semantic-release-beta/adapters/claude/skills/semantic-release-beta/SKILL.md +1 -0
- package/packages/software-development/semantic-release-beta/adapters/cursor/skills/semantic-release-beta/SKILL.md +1 -0
- package/packages/software-development/starter-rules/SKILL.md +1 -0
- package/packages/software-development/starter-rules/adapters/claude/skills/starter-rules/SKILL.md +1 -0
- package/packages/software-development/starter-rules/adapters/cursor/skills/starter-rules/SKILL.md +1 -0
- package/scripts/build-adapters.sh +11 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "olko-agent-skills",
|
|
3
3
|
"description": "Agent-agnostic skill catalog for Codex, Claude, Cursor, and other skill-aware tools.",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.9.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Oleg Koval"
|
|
7
7
|
},
|
|
@@ -24,6 +24,8 @@
|
|
|
24
24
|
"./packages/software-development/open-source-publisher",
|
|
25
25
|
"./packages/marketing/viral-launch",
|
|
26
26
|
"./packages/marketing/search-console-indexing-audit",
|
|
27
|
-
"./packages/software-development/cloudflare-block-countries"
|
|
27
|
+
"./packages/software-development/cloudflare-block-countries",
|
|
28
|
+
"./packages/software-development/obsidian-pr-sync",
|
|
29
|
+
"./packages/software-development/obsidian-task-rollover"
|
|
28
30
|
]
|
|
29
31
|
}
|
|
@@ -80,6 +80,16 @@
|
|
|
80
80
|
"name": "olko:cloudflare-block-countries",
|
|
81
81
|
"source": "./packages/software-development/cloudflare-block-countries/adapters/cursor",
|
|
82
82
|
"description": "Block specific countries via Cloudflare WAF Custom Rules using the Cloudflare API. Handles creating new rulesets and updating existing ones across single or multiple zones."
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"name": "olko:obsidian-pr-sync",
|
|
86
|
+
"source": "./packages/software-development/obsidian-pr-sync/adapters/cursor",
|
|
87
|
+
"description": "Fetch open GitHub PRs assigned to you or requesting your review, and write a grouped, age-sorted '## PRs to review' section into today's Obsidian daily note. Idempotent — re-running replaces the section."
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"name": "olko:obsidian-task-rollover",
|
|
91
|
+
"source": "./packages/software-development/obsidian-task-rollover/adapters/cursor",
|
|
92
|
+
"description": "Bullet-journal end-of-day task migration: copy unchecked tasks from today's Obsidian daily note to the next workday's note under '## Carried over', and mark them [>] in the source. Skips weekends, idempotent."
|
|
83
93
|
}
|
|
84
94
|
]
|
|
85
95
|
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
<!-- Generated by scripts/build-adapters.sh. Do not edit directly. -->
|
|
2
|
+
|
|
3
|
+
---
|
|
4
|
+
inclusion: manual
|
|
5
|
+
description: "Fetch open GitHub PRs assigned to you or requesting your review, and write a grouped, age-sorted '## PRs to review' section into today's Obsidian daily note. Idempotent — re-running replaces the section."
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
# Obsidian PR Sync
|
|
10
|
+
|
|
11
|
+
Fetch all open PRs where the user is assigned or requested as reviewer, filter out
|
|
12
|
+
noise (bots, drafts, self-authored), and write a clean grouped section into today's
|
|
13
|
+
daily note.
|
|
14
|
+
|
|
15
|
+
## Configuration
|
|
16
|
+
|
|
17
|
+
Before running, confirm:
|
|
18
|
+
- `VAULT_DAILY` — absolute path to the daily notes folder (e.g. `/Users/you/obsidian/vault/Lead/Daily`)
|
|
19
|
+
- `GH_USERNAME` — GitHub login to exclude self-authored PRs (e.g. `oleg-koval`)
|
|
20
|
+
- `ORG_PREFIX` — org name to group as "Work" (e.g. `Teifi-Digital`); everything else goes to "Personal"
|
|
21
|
+
|
|
22
|
+
If not specified by the user, infer from context (git config, existing vault files).
|
|
23
|
+
|
|
24
|
+
## Step 1 — Fetch PRs
|
|
25
|
+
|
|
26
|
+
Run two `gh` queries and merge results, deduplicating by URL:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
# Review-requested
|
|
30
|
+
gh search prs --review-requested=@me --state=open \
|
|
31
|
+
--json title,url,repository,author,createdAt,isDraft --limit 50
|
|
32
|
+
|
|
33
|
+
# Assigned
|
|
34
|
+
gh search prs --assignee=@me --state=open \
|
|
35
|
+
--json title,url,repository,author,createdAt,isDraft --limit 50
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Merge both lists, deduplicate by `url`. The union is what needs attention.
|
|
39
|
+
|
|
40
|
+
## Step 2 — Filter
|
|
41
|
+
|
|
42
|
+
Discard entries where:
|
|
43
|
+
- `isDraft` is `true`
|
|
44
|
+
- `author.login` matches any bot pattern: `dependabot`, `copilot`, `renovate`, `github-actions`, or `author.is_bot` is `true`
|
|
45
|
+
- `author.login` equals `GH_USERNAME` — self-authored PRs are not reviews; they're your own work
|
|
46
|
+
|
|
47
|
+
## Step 3 — Enrich authors
|
|
48
|
+
|
|
49
|
+
For each unique author login, resolve a display name for the Obsidian wiki-link:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
gh api /users/<login> --jq '.name // .login'
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
If the API returns a name, use it (e.g. `Rutger Klaassen`). If it returns null, fall
|
|
56
|
+
back to the login with first letter uppercased. This gives `[[Rutger Klaassen]]` or
|
|
57
|
+
`[[Merlijnmacgillavry]]`.
|
|
58
|
+
|
|
59
|
+
Batch these lookups — run them in parallel if possible to keep the sync fast.
|
|
60
|
+
|
|
61
|
+
## Step 4 — Calculate age
|
|
62
|
+
|
|
63
|
+
For each PR: `days_old = (today - createdAt).days`. Use today's date in local time.
|
|
64
|
+
|
|
65
|
+
## Step 5 — Build the section
|
|
66
|
+
|
|
67
|
+
Format the section exactly as:
|
|
68
|
+
|
|
69
|
+
```markdown
|
|
70
|
+
## PRs to review
|
|
71
|
+
|
|
72
|
+
### Work (<ORG_PREFIX>)
|
|
73
|
+
- [ ] [TITLE](url) by [[Author Name]] (N days old)
|
|
74
|
+
|
|
75
|
+
### Personal
|
|
76
|
+
- [ ] [TITLE](url) by [[Author Name]] (N days old)
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Rules:
|
|
80
|
+
- **Work**: `repository.nameWithOwner` starts with `<ORG_PREFIX>/`
|
|
81
|
+
- **Personal**: everything else
|
|
82
|
+
- Within each group, sort by `createdAt` ascending (oldest first — most overdue at top)
|
|
83
|
+
- If a group has no PRs, omit that subsection entirely (don't render an empty `### Work` header)
|
|
84
|
+
- If there are zero PRs total, write: `## PRs to review\n\n_No open PRs — clear queue! 🎉_`
|
|
85
|
+
- Add `⚠️` after the age if `days_old >= 7`
|
|
86
|
+
|
|
87
|
+
**Example line:**
|
|
88
|
+
```
|
|
89
|
+
- [ ] [RSL-108] Image sync from InRiver by [[Merlijn Mac Gillavry]] (12 days old ⚠️)
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Step 6 — Write to today's daily note
|
|
93
|
+
|
|
94
|
+
**Find today's note:**
|
|
95
|
+
```bash
|
|
96
|
+
TODAY=$(date +%Y-%m-%d)
|
|
97
|
+
NOTE="${VAULT_DAILY}/${TODAY}.md"
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
If the file doesn't exist, create it with standard daily template frontmatter first,
|
|
101
|
+
then append the section. If the file exists:
|
|
102
|
+
|
|
103
|
+
**Replacement logic (idempotent):**
|
|
104
|
+
- If `## PRs to review` already exists: replace everything from that line up to (but not
|
|
105
|
+
including) the next `## ` heading or end-of-file with the newly built section.
|
|
106
|
+
- If it doesn't exist: append the section at the end of the file (before the nav footer
|
|
107
|
+
line `*← [[...` if present, otherwise at the very end).
|
|
108
|
+
|
|
109
|
+
This ensures re-running the skill produces the same result, not a growing list.
|
|
110
|
+
|
|
111
|
+
## Invocation patterns
|
|
112
|
+
|
|
113
|
+
**Manual (user-triggered):**
|
|
114
|
+
The user says something like "sync my PRs to today's note" or "update obsidian with my reviews".
|
|
115
|
+
Run the full flow and confirm how many PRs were written.
|
|
116
|
+
|
|
117
|
+
**Scheduled morning routine:**
|
|
118
|
+
Same flow. No user prompt needed — just run, update the note, and report a one-line
|
|
119
|
+
summary: `"PR sync: 3 work PRs, 2 personal PRs written to 2026-05-11.md"`.
|
|
120
|
+
|
|
121
|
+
**In a remote CCR agent:**
|
|
122
|
+
Clone the vault repo, run the sync, commit and push. The local Obsidian Git plugin
|
|
123
|
+
pulls the changes automatically.
|
|
124
|
+
|
|
125
|
+
## Output to user
|
|
126
|
+
|
|
127
|
+
After writing the file, show a brief confirmation:
|
|
128
|
+
|
|
129
|
+
```
|
|
130
|
+
Synced N PRs to Lead/Daily/YYYY-MM-DD.md
|
|
131
|
+
Work (<ORG_PREFIX>): X PRs
|
|
132
|
+
Personal: Y PRs
|
|
133
|
+
Skipped: Z bots/drafts
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
If any `gh` call fails (e.g. auth expired), surface the error clearly rather than
|
|
137
|
+
writing a partial/corrupt section.
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
<!-- Generated by scripts/build-adapters.sh. Do not edit directly. -->
|
|
2
|
+
|
|
3
|
+
---
|
|
4
|
+
inclusion: manual
|
|
5
|
+
description: "Bullet-journal end-of-day task migration: copy unchecked tasks from today's Obsidian daily note to the next workday's note under '## Carried over', and mark them [>] in the source. Skips weekends, idempotent."
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
# Obsidian Task Rollover
|
|
10
|
+
|
|
11
|
+
Bullet-journal–style end-of-day task migration. Unfinished tasks (`- [ ]`) from
|
|
12
|
+
today's note get copied forward to the next workday, and marked as migrated in
|
|
13
|
+
today's note.
|
|
14
|
+
|
|
15
|
+
## Configuration
|
|
16
|
+
|
|
17
|
+
- `VAULT_DAILY` — absolute path to the daily notes folder (e.g. `/Users/you/obsidian/vault/Lead/Daily`)
|
|
18
|
+
|
|
19
|
+
If not specified, infer from context or ask.
|
|
20
|
+
|
|
21
|
+
## Step 1 — Identify source note
|
|
22
|
+
|
|
23
|
+
Default source = **today's note**. If the user specifies a date ("roll over Monday's
|
|
24
|
+
tasks"), resolve that date instead.
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
SOURCE_DATE=$(date +%Y-%m-%d)
|
|
28
|
+
SOURCE="${VAULT_DAILY}/${SOURCE_DATE}.md"
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
If the source note doesn't exist, report and stop — nothing to migrate.
|
|
32
|
+
|
|
33
|
+
## Step 2 — Find next workday
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
TARGET_DATE=$(python3 -c "
|
|
37
|
+
from datetime import date, timedelta
|
|
38
|
+
d = date.fromisoformat('${SOURCE_DATE}') + timedelta(days=1)
|
|
39
|
+
while d.weekday() >= 5: # 5=Sat, 6=Sun
|
|
40
|
+
d += timedelta(days=1)
|
|
41
|
+
print(d)
|
|
42
|
+
")
|
|
43
|
+
TARGET="${VAULT_DAILY}/${TARGET_DATE}.md"
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Skips weekends. If today is Friday, tasks roll to Monday.
|
|
47
|
+
|
|
48
|
+
## Step 3 — Extract incomplete tasks
|
|
49
|
+
|
|
50
|
+
Read the source note and collect all lines matching `- [ ] ` that are:
|
|
51
|
+
- **Not** inside the `## PRs to review` section (that section is auto-managed by
|
|
52
|
+
the `obsidian-pr-sync` skill — don't touch it)
|
|
53
|
+
- **Not** already migrated (`- [>]` lines — idempotency guard)
|
|
54
|
+
|
|
55
|
+
Sections to skip entirely: `## PRs to review`. Stop collecting at the nav footer
|
|
56
|
+
(`*← [[...`).
|
|
57
|
+
|
|
58
|
+
Collect both the task lines and which section (h2 heading) they belong to, so the
|
|
59
|
+
target note can group them the same way.
|
|
60
|
+
|
|
61
|
+
## Step 4 — Mark tasks as migrated in source note
|
|
62
|
+
|
|
63
|
+
For each collected task line in the source note, replace:
|
|
64
|
+
```
|
|
65
|
+
- [ ] some task
|
|
66
|
+
```
|
|
67
|
+
with:
|
|
68
|
+
```
|
|
69
|
+
- [>] some task → [[Lead/Daily/TARGET_DATE|TARGET_DATE]]
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
The `[>]` is the bullet journal migration arrow — "moved forward". The link lets you
|
|
73
|
+
jump to where the task landed.
|
|
74
|
+
|
|
75
|
+
**Do not** replace tasks that are already checked (`- [x]`) or already migrated
|
|
76
|
+
(`- [>`). Only unticked `- [ ]` tasks.
|
|
77
|
+
|
|
78
|
+
## Step 5 — Write to target note
|
|
79
|
+
|
|
80
|
+
### If the target note exists
|
|
81
|
+
|
|
82
|
+
Check whether a `## Carried over` section already exists:
|
|
83
|
+
- If yes: **replace** its content (idempotent — re-running a migration is safe)
|
|
84
|
+
- If no: **insert** it before the nav footer line (`*← [[...`) or at end of file
|
|
85
|
+
|
|
86
|
+
### If the target note doesn't exist
|
|
87
|
+
|
|
88
|
+
Create it using the standard daily note template:
|
|
89
|
+
```markdown
|
|
90
|
+
---
|
|
91
|
+
type: daily
|
|
92
|
+
date: TARGET_DATE
|
|
93
|
+
tags: [lead/daily]
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
# WEEKDAY, D MMM YYYY
|
|
97
|
+
|
|
98
|
+
## Top 3 for today
|
|
99
|
+
1.
|
|
100
|
+
2.
|
|
101
|
+
3.
|
|
102
|
+
|
|
103
|
+
## People check-in
|
|
104
|
+
> Who needs something from me today?
|
|
105
|
+
|
|
106
|
+
- [[]]
|
|
107
|
+
|
|
108
|
+
## Notes / journal
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
## Open loops
|
|
112
|
+
> Things I started but didn't finish
|
|
113
|
+
|
|
114
|
+
-
|
|
115
|
+
|
|
116
|
+
## Actions
|
|
117
|
+
- [ ]
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
*← [[Lead/Daily/SOURCE_DATE|Yesterday]] | [[Lead/Daily/NEXT_NEXT_DATE|Tomorrow]] →*
|
|
121
|
+
```
|
|
122
|
+
Then append the `## Carried over` section.
|
|
123
|
+
|
|
124
|
+
### Carried over section format
|
|
125
|
+
|
|
126
|
+
```markdown
|
|
127
|
+
## Carried over
|
|
128
|
+
|
|
129
|
+
> Migrated from [[Lead/Daily/SOURCE_DATE|SOURCE_DATE]]
|
|
130
|
+
|
|
131
|
+
### SECTION_NAME (if tasks came from a named section)
|
|
132
|
+
- [ ] task text ↩ [[Lead/Daily/SOURCE_DATE|SOURCE_DATE]]
|
|
133
|
+
|
|
134
|
+
### Actions (if tasks came from ## Actions)
|
|
135
|
+
- [ ] another task ↩ [[Lead/Daily/SOURCE_DATE|SOURCE_DATE]]
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Rules:
|
|
139
|
+
- Group tasks by the section they came from in the source note
|
|
140
|
+
- If all tasks are from `## Actions`, omit the subsection header (keep it flat)
|
|
141
|
+
- The `↩` link back to the source date lets you trace where the task originated
|
|
142
|
+
|
|
143
|
+
## Step 6 — Report
|
|
144
|
+
|
|
145
|
+
```
|
|
146
|
+
Rolled over N tasks from SOURCE_DATE → TARGET_DATE
|
|
147
|
+
From ## Actions: X tasks
|
|
148
|
+
From ## Open loops: Y tasks
|
|
149
|
+
Marked [>] in: Lead/Daily/SOURCE_DATE.md
|
|
150
|
+
Written to: Lead/Daily/TARGET_DATE.md
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
If there are zero incomplete tasks, report:
|
|
154
|
+
```
|
|
155
|
+
No incomplete tasks in SOURCE_DATE — nothing to roll over ✓
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Invocation patterns
|
|
159
|
+
|
|
160
|
+
**Manual:**
|
|
161
|
+
- "roll over today's tasks to tomorrow"
|
|
162
|
+
- "migrate my open tasks, it's end of day"
|
|
163
|
+
- "carry forward unfinished items from today"
|
|
164
|
+
|
|
165
|
+
**Scheduled (end-of-day or start-of-morning):**
|
|
166
|
+
Runs silently. Picks up today's note automatically.
|
|
167
|
+
|
|
168
|
+
**In a remote CCR agent:**
|
|
169
|
+
Clone the vault repo, run the rollover, commit and push. The local Obsidian Git
|
|
170
|
+
plugin pulls the changes automatically.
|
|
171
|
+
|
|
172
|
+
## Edge cases
|
|
173
|
+
|
|
174
|
+
- **Tasks with sub-bullets**: Copy the full block (task + its indented children)
|
|
175
|
+
- **Duplicate migration**: Re-running replaces the `## Carried over` section — never
|
|
176
|
+
duplicates. Tasks already marked `[>]` in source are not re-processed.
|
|
177
|
+
- **Friday → Monday**: The weekend-skip logic handles this. The Monday note is created
|
|
178
|
+
if it doesn't exist.
|
|
179
|
+
- **Task already in target**: No dedup check — if you manually added the same task to
|
|
180
|
+
tomorrow and then run migration, it'll appear twice. Acceptable — easy to clean up.
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
<!-- Generated by scripts/build-adapters.sh. Do not edit directly. -->
|
|
2
|
+
|
|
3
|
+
---
|
|
4
|
+
description: "Fetch open GitHub PRs assigned to you or requesting your review, and write a grouped, age-sorted '## PRs to review' section into today's Obsidian daily note. Idempotent — re-running replaces the section."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
# Obsidian PR Sync
|
|
9
|
+
|
|
10
|
+
Fetch all open PRs where the user is assigned or requested as reviewer, filter out
|
|
11
|
+
noise (bots, drafts, self-authored), and write a clean grouped section into today's
|
|
12
|
+
daily note.
|
|
13
|
+
|
|
14
|
+
## Configuration
|
|
15
|
+
|
|
16
|
+
Before running, confirm:
|
|
17
|
+
- `VAULT_DAILY` — absolute path to the daily notes folder (e.g. `/Users/you/obsidian/vault/Lead/Daily`)
|
|
18
|
+
- `GH_USERNAME` — GitHub login to exclude self-authored PRs (e.g. `oleg-koval`)
|
|
19
|
+
- `ORG_PREFIX` — org name to group as "Work" (e.g. `Teifi-Digital`); everything else goes to "Personal"
|
|
20
|
+
|
|
21
|
+
If not specified by the user, infer from context (git config, existing vault files).
|
|
22
|
+
|
|
23
|
+
## Step 1 — Fetch PRs
|
|
24
|
+
|
|
25
|
+
Run two `gh` queries and merge results, deduplicating by URL:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# Review-requested
|
|
29
|
+
gh search prs --review-requested=@me --state=open \
|
|
30
|
+
--json title,url,repository,author,createdAt,isDraft --limit 50
|
|
31
|
+
|
|
32
|
+
# Assigned
|
|
33
|
+
gh search prs --assignee=@me --state=open \
|
|
34
|
+
--json title,url,repository,author,createdAt,isDraft --limit 50
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Merge both lists, deduplicate by `url`. The union is what needs attention.
|
|
38
|
+
|
|
39
|
+
## Step 2 — Filter
|
|
40
|
+
|
|
41
|
+
Discard entries where:
|
|
42
|
+
- `isDraft` is `true`
|
|
43
|
+
- `author.login` matches any bot pattern: `dependabot`, `copilot`, `renovate`, `github-actions`, or `author.is_bot` is `true`
|
|
44
|
+
- `author.login` equals `GH_USERNAME` — self-authored PRs are not reviews; they're your own work
|
|
45
|
+
|
|
46
|
+
## Step 3 — Enrich authors
|
|
47
|
+
|
|
48
|
+
For each unique author login, resolve a display name for the Obsidian wiki-link:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
gh api /users/<login> --jq '.name // .login'
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
If the API returns a name, use it (e.g. `Rutger Klaassen`). If it returns null, fall
|
|
55
|
+
back to the login with first letter uppercased. This gives `[[Rutger Klaassen]]` or
|
|
56
|
+
`[[Merlijnmacgillavry]]`.
|
|
57
|
+
|
|
58
|
+
Batch these lookups — run them in parallel if possible to keep the sync fast.
|
|
59
|
+
|
|
60
|
+
## Step 4 — Calculate age
|
|
61
|
+
|
|
62
|
+
For each PR: `days_old = (today - createdAt).days`. Use today's date in local time.
|
|
63
|
+
|
|
64
|
+
## Step 5 — Build the section
|
|
65
|
+
|
|
66
|
+
Format the section exactly as:
|
|
67
|
+
|
|
68
|
+
```markdown
|
|
69
|
+
## PRs to review
|
|
70
|
+
|
|
71
|
+
### Work (<ORG_PREFIX>)
|
|
72
|
+
- [ ] [TITLE](url) by [[Author Name]] (N days old)
|
|
73
|
+
|
|
74
|
+
### Personal
|
|
75
|
+
- [ ] [TITLE](url) by [[Author Name]] (N days old)
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Rules:
|
|
79
|
+
- **Work**: `repository.nameWithOwner` starts with `<ORG_PREFIX>/`
|
|
80
|
+
- **Personal**: everything else
|
|
81
|
+
- Within each group, sort by `createdAt` ascending (oldest first — most overdue at top)
|
|
82
|
+
- If a group has no PRs, omit that subsection entirely (don't render an empty `### Work` header)
|
|
83
|
+
- If there are zero PRs total, write: `## PRs to review\n\n_No open PRs — clear queue! 🎉_`
|
|
84
|
+
- Add `⚠️` after the age if `days_old >= 7`
|
|
85
|
+
|
|
86
|
+
**Example line:**
|
|
87
|
+
```
|
|
88
|
+
- [ ] [RSL-108] Image sync from InRiver by [[Merlijn Mac Gillavry]] (12 days old ⚠️)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Step 6 — Write to today's daily note
|
|
92
|
+
|
|
93
|
+
**Find today's note:**
|
|
94
|
+
```bash
|
|
95
|
+
TODAY=$(date +%Y-%m-%d)
|
|
96
|
+
NOTE="${VAULT_DAILY}/${TODAY}.md"
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
If the file doesn't exist, create it with standard daily template frontmatter first,
|
|
100
|
+
then append the section. If the file exists:
|
|
101
|
+
|
|
102
|
+
**Replacement logic (idempotent):**
|
|
103
|
+
- If `## PRs to review` already exists: replace everything from that line up to (but not
|
|
104
|
+
including) the next `## ` heading or end-of-file with the newly built section.
|
|
105
|
+
- If it doesn't exist: append the section at the end of the file (before the nav footer
|
|
106
|
+
line `*← [[...` if present, otherwise at the very end).
|
|
107
|
+
|
|
108
|
+
This ensures re-running the skill produces the same result, not a growing list.
|
|
109
|
+
|
|
110
|
+
## Invocation patterns
|
|
111
|
+
|
|
112
|
+
**Manual (user-triggered):**
|
|
113
|
+
The user says something like "sync my PRs to today's note" or "update obsidian with my reviews".
|
|
114
|
+
Run the full flow and confirm how many PRs were written.
|
|
115
|
+
|
|
116
|
+
**Scheduled morning routine:**
|
|
117
|
+
Same flow. No user prompt needed — just run, update the note, and report a one-line
|
|
118
|
+
summary: `"PR sync: 3 work PRs, 2 personal PRs written to 2026-05-11.md"`.
|
|
119
|
+
|
|
120
|
+
**In a remote CCR agent:**
|
|
121
|
+
Clone the vault repo, run the sync, commit and push. The local Obsidian Git plugin
|
|
122
|
+
pulls the changes automatically.
|
|
123
|
+
|
|
124
|
+
## Output to user
|
|
125
|
+
|
|
126
|
+
After writing the file, show a brief confirmation:
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
Synced N PRs to Lead/Daily/YYYY-MM-DD.md
|
|
130
|
+
Work (<ORG_PREFIX>): X PRs
|
|
131
|
+
Personal: Y PRs
|
|
132
|
+
Skipped: Z bots/drafts
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
If any `gh` call fails (e.g. auth expired), surface the error clearly rather than
|
|
136
|
+
writing a partial/corrupt section.
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
<!-- Generated by scripts/build-adapters.sh. Do not edit directly. -->
|
|
2
|
+
|
|
3
|
+
---
|
|
4
|
+
description: "Bullet-journal end-of-day task migration: copy unchecked tasks from today's Obsidian daily note to the next workday's note under '## Carried over', and mark them [>] in the source. Skips weekends, idempotent."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
# Obsidian Task Rollover
|
|
9
|
+
|
|
10
|
+
Bullet-journal–style end-of-day task migration. Unfinished tasks (`- [ ]`) from
|
|
11
|
+
today's note get copied forward to the next workday, and marked as migrated in
|
|
12
|
+
today's note.
|
|
13
|
+
|
|
14
|
+
## Configuration
|
|
15
|
+
|
|
16
|
+
- `VAULT_DAILY` — absolute path to the daily notes folder (e.g. `/Users/you/obsidian/vault/Lead/Daily`)
|
|
17
|
+
|
|
18
|
+
If not specified, infer from context or ask.
|
|
19
|
+
|
|
20
|
+
## Step 1 — Identify source note
|
|
21
|
+
|
|
22
|
+
Default source = **today's note**. If the user specifies a date ("roll over Monday's
|
|
23
|
+
tasks"), resolve that date instead.
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
SOURCE_DATE=$(date +%Y-%m-%d)
|
|
27
|
+
SOURCE="${VAULT_DAILY}/${SOURCE_DATE}.md"
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
If the source note doesn't exist, report and stop — nothing to migrate.
|
|
31
|
+
|
|
32
|
+
## Step 2 — Find next workday
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
TARGET_DATE=$(python3 -c "
|
|
36
|
+
from datetime import date, timedelta
|
|
37
|
+
d = date.fromisoformat('${SOURCE_DATE}') + timedelta(days=1)
|
|
38
|
+
while d.weekday() >= 5: # 5=Sat, 6=Sun
|
|
39
|
+
d += timedelta(days=1)
|
|
40
|
+
print(d)
|
|
41
|
+
")
|
|
42
|
+
TARGET="${VAULT_DAILY}/${TARGET_DATE}.md"
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Skips weekends. If today is Friday, tasks roll to Monday.
|
|
46
|
+
|
|
47
|
+
## Step 3 — Extract incomplete tasks
|
|
48
|
+
|
|
49
|
+
Read the source note and collect all lines matching `- [ ] ` that are:
|
|
50
|
+
- **Not** inside the `## PRs to review` section (that section is auto-managed by
|
|
51
|
+
the `obsidian-pr-sync` skill — don't touch it)
|
|
52
|
+
- **Not** already migrated (`- [>]` lines — idempotency guard)
|
|
53
|
+
|
|
54
|
+
Sections to skip entirely: `## PRs to review`. Stop collecting at the nav footer
|
|
55
|
+
(`*← [[...`).
|
|
56
|
+
|
|
57
|
+
Collect both the task lines and which section (h2 heading) they belong to, so the
|
|
58
|
+
target note can group them the same way.
|
|
59
|
+
|
|
60
|
+
## Step 4 — Mark tasks as migrated in source note
|
|
61
|
+
|
|
62
|
+
For each collected task line in the source note, replace:
|
|
63
|
+
```
|
|
64
|
+
- [ ] some task
|
|
65
|
+
```
|
|
66
|
+
with:
|
|
67
|
+
```
|
|
68
|
+
- [>] some task → [[Lead/Daily/TARGET_DATE|TARGET_DATE]]
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
The `[>]` is the bullet journal migration arrow — "moved forward". The link lets you
|
|
72
|
+
jump to where the task landed.
|
|
73
|
+
|
|
74
|
+
**Do not** replace tasks that are already checked (`- [x]`) or already migrated
|
|
75
|
+
(`- [>`). Only unticked `- [ ]` tasks.
|
|
76
|
+
|
|
77
|
+
## Step 5 — Write to target note
|
|
78
|
+
|
|
79
|
+
### If the target note exists
|
|
80
|
+
|
|
81
|
+
Check whether a `## Carried over` section already exists:
|
|
82
|
+
- If yes: **replace** its content (idempotent — re-running a migration is safe)
|
|
83
|
+
- If no: **insert** it before the nav footer line (`*← [[...`) or at end of file
|
|
84
|
+
|
|
85
|
+
### If the target note doesn't exist
|
|
86
|
+
|
|
87
|
+
Create it using the standard daily note template:
|
|
88
|
+
```markdown
|
|
89
|
+
---
|
|
90
|
+
type: daily
|
|
91
|
+
date: TARGET_DATE
|
|
92
|
+
tags: [lead/daily]
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
# WEEKDAY, D MMM YYYY
|
|
96
|
+
|
|
97
|
+
## Top 3 for today
|
|
98
|
+
1.
|
|
99
|
+
2.
|
|
100
|
+
3.
|
|
101
|
+
|
|
102
|
+
## People check-in
|
|
103
|
+
> Who needs something from me today?
|
|
104
|
+
|
|
105
|
+
- [[]]
|
|
106
|
+
|
|
107
|
+
## Notes / journal
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
## Open loops
|
|
111
|
+
> Things I started but didn't finish
|
|
112
|
+
|
|
113
|
+
-
|
|
114
|
+
|
|
115
|
+
## Actions
|
|
116
|
+
- [ ]
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
*← [[Lead/Daily/SOURCE_DATE|Yesterday]] | [[Lead/Daily/NEXT_NEXT_DATE|Tomorrow]] →*
|
|
120
|
+
```
|
|
121
|
+
Then append the `## Carried over` section.
|
|
122
|
+
|
|
123
|
+
### Carried over section format
|
|
124
|
+
|
|
125
|
+
```markdown
|
|
126
|
+
## Carried over
|
|
127
|
+
|
|
128
|
+
> Migrated from [[Lead/Daily/SOURCE_DATE|SOURCE_DATE]]
|
|
129
|
+
|
|
130
|
+
### SECTION_NAME (if tasks came from a named section)
|
|
131
|
+
- [ ] task text ↩ [[Lead/Daily/SOURCE_DATE|SOURCE_DATE]]
|
|
132
|
+
|
|
133
|
+
### Actions (if tasks came from ## Actions)
|
|
134
|
+
- [ ] another task ↩ [[Lead/Daily/SOURCE_DATE|SOURCE_DATE]]
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Rules:
|
|
138
|
+
- Group tasks by the section they came from in the source note
|
|
139
|
+
- If all tasks are from `## Actions`, omit the subsection header (keep it flat)
|
|
140
|
+
- The `↩` link back to the source date lets you trace where the task originated
|
|
141
|
+
|
|
142
|
+
## Step 6 — Report
|
|
143
|
+
|
|
144
|
+
```
|
|
145
|
+
Rolled over N tasks from SOURCE_DATE → TARGET_DATE
|
|
146
|
+
From ## Actions: X tasks
|
|
147
|
+
From ## Open loops: Y tasks
|
|
148
|
+
Marked [>] in: Lead/Daily/SOURCE_DATE.md
|
|
149
|
+
Written to: Lead/Daily/TARGET_DATE.md
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
If there are zero incomplete tasks, report:
|
|
153
|
+
```
|
|
154
|
+
No incomplete tasks in SOURCE_DATE — nothing to roll over ✓
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## Invocation patterns
|
|
158
|
+
|
|
159
|
+
**Manual:**
|
|
160
|
+
- "roll over today's tasks to tomorrow"
|
|
161
|
+
- "migrate my open tasks, it's end of day"
|
|
162
|
+
- "carry forward unfinished items from today"
|
|
163
|
+
|
|
164
|
+
**Scheduled (end-of-day or start-of-morning):**
|
|
165
|
+
Runs silently. Picks up today's note automatically.
|
|
166
|
+
|
|
167
|
+
**In a remote CCR agent:**
|
|
168
|
+
Clone the vault repo, run the rollover, commit and push. The local Obsidian Git
|
|
169
|
+
plugin pulls the changes automatically.
|
|
170
|
+
|
|
171
|
+
## Edge cases
|
|
172
|
+
|
|
173
|
+
- **Tasks with sub-bullets**: Copy the full block (task + its indented children)
|
|
174
|
+
- **Duplicate migration**: Re-running replaces the `## Carried over` section — never
|
|
175
|
+
duplicates. Tasks already marked `[>]` in source are not re-processed.
|
|
176
|
+
- **Friday → Monday**: The weekend-skip logic handles this. The Monday note is created
|
|
177
|
+
if it doesn't exist.
|
|
178
|
+
- **Task already in target**: No dedup check — if you manually added the same task to
|
|
179
|
+
tomorrow and then run migration, it'll appear twice. Acceptable — easy to clean up.
|
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<p><strong>Agent-agnostic skill catalog for Codex, Claude, Cursor, Copilot, Windsurf, Kiro, and other skill-aware tools.</strong></p>
|
|
4
4
|
<p>
|
|
5
5
|
<img src="https://img.shields.io/badge/license-MIT-16a34a" alt="MIT license">
|
|
6
|
-
<img src="https://img.shields.io/badge/skills-
|
|
6
|
+
<img src="https://img.shields.io/badge/skills-18-2563eb" alt="18 skills">
|
|
7
7
|
<img src="https://img.shields.io/badge/platforms-Codex%20%7C%20Claude%20%7C%20Cursor%20%7C%20Copilot%20%7C%20Windsurf%20%7C%20Kiro-111827" alt="Codex Claude Cursor Copilot Windsurf Kiro">
|
|
8
8
|
<img src="https://img.shields.io/badge/status-public%20catalog-16a34a" alt="Public catalog">
|
|
9
9
|
</p>
|
|
@@ -174,7 +174,7 @@ packages/{category}/{skill}/adapters/
|
|
|
174
174
|
|
|
175
175
|
</details>
|
|
176
176
|
|
|
177
|
-
## All
|
|
177
|
+
## All 18 Skills
|
|
178
178
|
|
|
179
179
|
These packages are the entry points. Each one is a structured workflow with concrete trigger conditions and execution steps. You can reference any skill directly by its `olko:*` lookup name.
|
|
180
180
|
|
|
@@ -194,6 +194,8 @@ These packages are the entry points. Each one is a structured workflow with conc
|
|
|
194
194
|
| [ai-tools-setup](packages/software-development/ai-tools-setup/SKILL.md) | Installs, repairs, and measures the RTK+ICM+Vox AI development toolkit | Setting up or repairing AI dev tooling hooks, MCP config, or reviewing a weekly token savings digest |
|
|
195
195
|
| [starter-rules](packages/software-development/starter-rules/SKILL.md) | Loads and enforces hard rules for every oleg-koval/* starter | Ensuring 300-line files, E2E tests, pre-commit hooks, Vertical Slice architecture, and KISS/DRY/SOLID |
|
|
196
196
|
| [open-source-publisher](packages/software-development/open-source-publisher/SKILL.md) | Prepares an open-source repository for public publishing with branding, CI/CD, and release hygiene | Releasing a private project publicly with proper GitHub Pages, README, and social preview |
|
|
197
|
+
| [obsidian-pr-sync](packages/software-development/obsidian-pr-sync/SKILL.md) | Fetches open GitHub PRs assigned to you or requesting review, and writes a grouped age-sorted section into today's Obsidian daily note | Syncing GitHub review queue to Obsidian at the start of the day or on demand |
|
|
198
|
+
| [obsidian-task-rollover](packages/software-development/obsidian-task-rollover/SKILL.md) | Migrates unchecked tasks from today's Obsidian daily note to the next workday under `## Carried over`, marking source tasks as `[>]` | End-of-day bullet-journal task migration, rolling unfinished work to the next workday |
|
|
197
199
|
|
|
198
200
|
### Music
|
|
199
201
|
|