A lot of AI workflow advice stops at better prompts. That helps, but it does not solve the bigger problem: the same useful setup patterns keep getting rebuilt from scratch.
If you find yourself repeatedly teaching an agent how to bootstrap repo state, create recurring work loops, package pull requests, and post updates to the right place, you are no longer dealing with a one-off prompt problem. You are dealing with a reusable workflow problem.
That is where OpenClaw skills get interesting. A good skill is not just a note about how to do something. It is a way to encode judgment, structure, defaults, and guardrails so the same category of work becomes repeatable.
In this post, I walk through a practical example: creating an OpenClaw skill for structured repo automation. The goal is a reusable skill that can set up recurring runs for a repository, maintain repo-local state, package coherent pull requests on designated runs, and post updates to Discord. Think of it as the difference between chatting with a capable assistant and building a small operating system for a recurring type of work.
Why plain prompts are not enough
A plain prompt is great when the task is isolated. It is much weaker when the workflow repeats across multiple projects.
The repeated setup usually looks something like this:
- create repo-local memory files
- define normal runs versus PR-packaging runs
- enforce
main-first branch discipline - route status updates to a Discord channel
- stop the agent from opening junk pull requests
- keep next steps readable for future runs
You can absolutely describe that in chat every time. The problem is that it wastes tokens, introduces drift, and makes it easy to forget the little rules that matter.
A skill is better because it captures the trigger for when the workflow applies, the inputs required to configure it, the default decisions that are usually right, the file structure to generate, the branch and pull request rules to preserve, and the quality bar for what should count as useful progress. That is a different level of abstraction than "here is a prompt."
The scheduled repo automation pattern
The core pattern is a scheduled repo worker. Normal runs make bounded progress. A designated PR run packages coherent work. Repo-local files store current state and next actions. The human reviews pull requests and adjusts priorities instead of redoing setup from scratch.
This pattern works well for product repos that need steady implementation progress, content or course repos that need incremental publishing work, internal automation repos that benefit from a structured engineering loop, and projects where daily progress matters more than marathon sessions.
This is not a magic autonomous company. It is a constrained system for recurring execution. That distinction matters.
Why this kind of skill is valuable
A reusable scheduled-repo skill turns repeated operational knowledge into a portable setup you can apply to the next repo without rebuilding the workflow from memory.
1. It reduces setup repetition
You do not have to keep re-inventing the same workflow for every repo. The skill carries the defaults, the file structure, the branch rules, and the quality bar — so setup goes from a thirty-minute conversation to a short configuration step.
2. It encodes safer defaults
Good defaults prevent silly failures such as:
- packaging from a stale feature branch
- posting to the wrong Discord channel
- opening a PR that only contains docs churn
- forgetting to update state files
3. It makes autonomous runs more reviewable
Instead of random edits appearing out of nowhere, the repo has a visible loop: what is happening now, what changed last, and what should happen next.
4. It reduces token waste
When model usage is expensive or limited, repo-local memory matters more. Durable files like WORK_STATE.md and NEXT_ACTIONS.md reduce wasted context across sessions.
5. Structure still matters with abundant tokens
Even with plenty of usage headroom, more tokens do not magically create discipline. They can actually make drift worse if the workflow is under-specified.
Turning a model into a bounded builder loop
A skill like this is not just about saving a few prompts. It is about creating a system where the model does useful recurring implementation work while the human stays in the loop as reviewer, prioritizer, product or architecture guide, and quality controller.
If the system is well designed, the agent can make bounded progress on a schedule, preserve repo-local context between runs, package coherent pull requests, and leave a clean audit trail. Your role becomes reviewing PRs, nudging the roadmap, improving ideas, and catching low-quality directions early — which is a far more believable model than fully hands-off coding theater.
Three modes for the skill
One of the biggest design choices is admitting that not every repository behaves the same way. Some repos are exploratory and need flexible project memory. Others are highly structured and need the automation to respect an existing queue and task engine. Treating both the same usually produces awkward results.
- docs/WORK_STATE.md
- docs/NEXT_ACTIONS.md
- docs/PROJECT_LOG.md
- state.json
- queue.json
- NEXT_TASK.md
- RUN_LOG.md
- plan/tasks/*.md
- state.json / queue.json
- NEXT_TASK.md
- docs/WORK_STATE.md
- docs/PROJECT_LOG.md
Mode 1: project-memory
This is for open-ended repos that do not already have a strong task engine. The skill creates and maintains human-readable state files. The point is not paperwork — it is to give recurring runs a durable memory layer that survives beyond any single chat session. Best when the project is still evolving and the automation needs human-readable context to stay grounded.
Mode 2: task-engine
Some repos are already much more structured, with existing state.json, queue.json, NEXT_TASK.md, and task specs in a plan/tasks/ directory. In that case, the skill should not bulldoze that structure. It should adapt to the existing task engine — preserving the current-task contract, keeping automation predictable, and maintaining rules like "one task per PR."
Mode 3: hybrid
Hybrid is for repos that already have a task engine but still need higher-level project memory. That means keeping the machine-readable workflow while also adding human-readable memory files. This gives you both task progression and project-level handoff, which turns out to be surprisingly useful in longer-running automation setups.
Skill file layout
The skill structure can stay small. A first version needs only four files:
What belongs in SKILL.md
The main skill file should answer when this skill applies, what mode to choose, what inputs to collect, what files to generate, what branch and PR rules to enforce, and what quality rules to preserve. Here is a realistic example:
## scheduled-repo-worker Bootstrap and maintain recurring repo automation for coding or content projects that should make bounded progress on a schedule, update repo-local project state, create PRs on designated runs, and post summaries to Discord. ### When to use this skill Trigger this skill when the user asks to: - set up scheduled or recurring automation for a repo - create a structured work loop with PR packaging - configure an agent to run on a cron schedule against a repo ### Inputs required | Input | Required | Notes | |------------------|----------|-------------------------------------------------| | repo_path | yes | local path or GitHub URL | | project_goal | yes | one or two sentences on what success looks like | | mode | yes | project-memory / task-engine / hybrid | | schedule_preset | yes | light / medium / custom | | discord_target | yes | channel ID or full Discord webhook URL | | quality_notes | no | special constraints (e.g. "prefer TypeScript") | ### Mode selection guide - No existing task engine → project-memory - Existing state.json/queue.json → task-engine - Task engine + project context → hybrid ### Branch and PR rules Always apply these on every PR run: 1. git checkout main 2. git pull --ff-only origin main 3. Create a fresh branch (never stack on older PR branches) 4. Open a PR only if the work is meaningful and reviewable 5. Skip the PR and note the reason if only status-doc changes exist ### Quality bar Do not generate a PR that only contains: - updates to WORK_STATE.md or PROJECT_LOG.md - reformatted code with no behavior change - TODO comments without accompanying implementation
Reference file: question-flow.md
This file helps gather the minimum required setup cleanly. A good question flow covers the six key inputs and offers schedule presets so users do not need to think in cron syntax on day one.
## Question flow for scheduled-repo-worker setup
Ask these questions in order. Skip optional questions if the user
has already provided the information.
---
**Q1 — Repo** (required)
What is the path or GitHub URL for the repo you want to automate?
---
**Q2 — Goal** (required)
In one or two sentences, what does success look like for this repo
over the next month?
Example answers:
- "Ship the initial API with docs and a passing test suite."
- "Publish 8 new course modules with exercises and solutions."
- "Keep dependency upgrades and lint fixes merged on a weekly cadence."
---
**Q3 — Mode** (required)
Does the repo already have a task engine (state.json, queue.json,
NEXT_TASK.md, or a plan/tasks/ directory)?
- Yes → task-engine (or hybrid if you also want project memory)
- No → project-memory
---
**Q4 — Schedule** (required)
Pick a preset or describe your own cadence:
light → 2 normal runs + 1 PR run per day
9 AM normal | 3 PM normal | 9 PM PR
medium → 5 normal runs + 1 PR run per day
4 AM normal | 8 AM normal | 12 PM normal
4 PM PR | 8 PM normal | 12 AM normal
custom → describe your preferred times and which runs are PR runs
Cron examples:
light : "0 9,15 * * *" normal + "0 21 * * *" PR
medium : "0 4,8,12,20,0 * * *" normal + "0 16 * * *" PR
---
**Q5 — Discord target** (required)
Paste a Discord channel ID or a full webhook URL.
Either format works — the skill will extract the channel ID cleanly.
---
**Q6 — Quality priorities** (optional)
Any special constraints?
Examples:
- "Prefer TypeScript strict mode, no any"
- "Every module must include tests"
- "Keep bundle size under 200 KB"
- "No third-party dependencies without approval"Reference file: project-memory-templates.md
These templates are the backbone of recurring autonomous work in open-ended repos. They turn vague continuity into explicit, machine-readable state that survives across sessions.
# WORK_STATE.md — template ## Current Status Active development — authentication layer complete, dashboard in progress. ## Current Strategic Focus Implement the dashboard data-fetching layer and connect it to the existing auth context. ## Just Completed - Added JWT refresh token endpoint (POST /auth/refresh) - Wrote unit tests for token expiry edge cases - Updated OpenAPI spec with new auth routes ## In Progress - Dashboard: fetching user metrics from /api/metrics (50% done) - Storybook stories for Button and Input components (not started) ## Blockers None. ## Next Recommended Task Complete the dashboard metrics fetch and add a loading skeleton component while data is in flight. ## Testing Status All auth tests passing. Dashboard tests not yet written. ## PR Status PR #12 merged 2026-04-07 — auth refresh token endpoint
# NEXT_ACTIONS.md — template ## Priority queue 1. Dashboard metrics fetch + loading skeleton 2. Storybook stories for Button and Input 3. Error boundary for dashboard data failures 4. E2E test: login → dashboard → logout flow ## Deferred - Dark mode support (waiting for design input) - Notification system (blocked on backend events API) ## Notes for next PR run The next PR should bundle the dashboard data layer and at minimum a loading state. Do not include the Storybook stories — those are still incomplete.
# PROJECT_LOG.md — template ## 2026-04-08 — Normal run Completed dashboard metrics fetch. Added loading skeleton component. Wrote 3 unit tests for the fetch hook. WORK_STATE.md updated. ## 2026-04-07 — PR run Packaged PR #12: auth refresh token endpoint. Merged same day. Discord update posted to #dev-updates. ## 2026-04-07 — Normal run Auth refresh token endpoint complete. Tests passing. Updated NEXT_ACTIONS.md to promote dashboard task to top.
Reference file: task-engine-notes.md
This file explains how the skill should behave when it encounters an existing task engine, so it does not tramples the repo's existing structure.
## task-engine-notes When the repo already has a task engine, the scheduled-repo-worker skill adapts rather than replacing. ### Detection The repo has a task engine if ANY of these exist: - state.json or .state.json at repo root - queue.json or plan/queue.json - NEXT_TASK.md at repo root - plan/tasks/ directory with .md files ### Behavior on normal runs 1. Read state.json to identify the current task 2. Read the corresponding task file (e.g. plan/tasks/TASK-042.md) 3. Implement the task within the specified scope 4. Update state.json: mark task as in-progress or complete 5. Append a one-line entry to RUN_LOG.md 6. Do NOT modify queue.json order unless the task spec says so ### Behavior on PR runs 1. git checkout main && git pull --ff-only origin main 2. Create branch: task/TASK-042-short-description 3. Confirm the task is genuinely complete (tests passing, scope met) 4. Open PR with title matching the task spec title 5. Include in PR body: task ID, what was done, tests run 6. Post Discord update with PR link and task summary ### Preserving the contract - Never skip a task unless the task spec explicitly marks it blocked - Never reorder queue.json based on your own judgment - If the current task is blocked, add a note to state.json and stop — do not pick the next task without human approval ### Hybrid additions If the user also wants project memory, add these alongside the task engine files (do not replace them): - docs/WORK_STATE.md ← human-readable project health summary - docs/PROJECT_LOG.md ← dated log of what happened across runs These files should summarize task progress in plain language, not duplicate the machine-readable state.json content.
Branch and PR rules that prevent the common failures
One of the most common failure modes in scheduled automation is stale branch packaging. The fix is boring but important. PR-run guidance should always encode this sequence:
git checkout main git pull --ff-only origin main # verify you are on the latest main before creating a branch git checkout -b task/short-description-$(date +%Y%m%d)
It also helps to explicitly state:
- do not stack on an older PR branch
- create a PR only if the work is meaningful and reviewable
- skip PRs that only contain status-doc churn and explain why
Those are exactly the sorts of rules that belong in a reusable skill instead of being rediscovered the hard way.
Why repo-local memory is the real backbone
Without durable repo-local state, the automation stays shallow. Chat memory alone is not enough. What survives and compounds is what gets written to files.
The WORK_STATE.md template above might look simple, but the impact on recurring run quality is significant. It reduces token waste, improves handoff quality between sessions, and makes PR packaging runs more grounded because the agent knows exactly what was completed, what is in progress, and what comes next.
The alternative — relying on the model to reconstruct context from the diff — works once or twice but degrades quickly. Files do not forget.
Failure modes worth designing around
A good skill should explicitly protect against the obvious failure modes.
Wrong delivery target
The skill should accept either a raw channel ID or a full Discord URL, then extract the channel ID cleanly. That sounds minor, but little conveniences like that are exactly what make a reusable skill feel polished instead of brittle.
Docs-only churn
If a PR run packages only status updates — changes to WORK_STATE.md or PROJECT_LOG.md with nothing else — that is a smell. The workflow should skip the PR, log the reason, and wait for the next normal run to add substantive work first.
Stale branch packaging
Always sync main before creating a branch. If git pull --ff-only fails, stop and report the conflict rather than packaging from an outdated base.
Over-rigid task systems
Task engines are good, but sometimes they need a higher-level project memory layer too. The hybrid mode exists for exactly this case.
Under-specified quality goals
If the repo needs rich content, strong design, or scalable structure, say so explicitly in the quality notes and in the state files. Otherwise the automation may optimize for shallow completion — technically progressing through tasks without producing work worth merging.
When to use this skill
Use when
- the repo needs recurring bounded progress
- PR packaging should happen on a schedule
- multiple repos need similar setup patterns
- reviewable automation matters more than raw speed
- repo-local memory would improve continuity
Avoid when
- the repo is a tiny one-off
- the project goal is still too vague
- a schedule would create churn without direction
- the work is too sensitive to automate without additional controls
A minimum viable version is enough to start
You do not need a giant skill framework on day one. A genuinely useful first version is:
- one good
SKILL.mdwith trigger conditions, inputs, branch rules, and quality bar - one
question-flow.mdwith setup questions and schedule presets - one
project-memory-templates.mdwith the three state file templates - one
task-engine-notes.mdexplaining how to adapt to existing queues
That is enough to test the pattern on real repos and refine it from there. The skill itself improves through the same loop it describes: bounded runs, concrete feedback, and targeted adjustments over time.
Final takeaway
The biggest shift here is not "AI can write code on a schedule." That part is easy to overstate.
The real shift is that a well-designed skill can turn repeated operational knowledge into a reusable workflow with guardrails. Once that exists, scheduled runs stop feeling like random background automation and start feeling like a constrained engineering loop.
The repo carries memory. The automation works in bounded slices. PR runs package coherent work. The human reviews and improves the direction. The skill is not just a convenience layer — it is a way to turn raw model capability into something closer to a repeatable system.