| name | github-task-sync |
| description | Manage task documentation by syncing between local task directories and GitHub issues |
GitHub Task Sync Skill
Seamlessly manage task documentation by syncing between local task directories and GitHub issues. All task documentation (SPEC, PLAN, TEST_PLAN, COMMIT_MESSAGE) lives both locally and on GitHub, with easy push/pull synchronization.
Overview
This skill provides a complete workflow for managing tasks:
- Create a new GitHub issue with
create-issue.sh
- Push local task files to GitHub with
push.sh or push-file.sh
- Pull task files from GitHub with
pull.sh or pull-file.sh
- Read task files from GitHub to stdout with
read-issue-file.sh
- Log work progress with
log-entry.sh (creates AI Work Log comment with timestamped entries)
Quick Start
./create-issue.sh "Add dark mode toggle" "Implement dark/light theme switcher"
./push.sh 188 ./tasks/188-add-dark-mode-toggle
./pull.sh 188
Scripts
There are 7 scripts in this skill:
- create-issue.sh - Create GitHub issue and initialize task directory
- push.sh - Push all task files to GitHub
- push-file.sh - Push single task file with status summary
- pull.sh - Pull all task files from GitHub
- pull-file.sh - Pull single task file from GitHub
- read-issue-file.sh - Read task file from GitHub to stdout
- log-entry.sh - Add timestamped entry to AI Work Log
create-issue.sh
Create a new GitHub issue and initialize a task directory. Can also convert existing task directories to GitHub issues. Automatically applies GitHub labels based on issue context.
Usage:
./create-issue.sh <title> [description] [existing-task-dir] [labels]
Arguments:
title - GitHub issue title
description - Issue description (optional)
existing-task-dir - Path to existing task directory to convert (optional)
labels - Comma-separated labels to apply (optional, e.g., "UI,bug" or "CLI,feature")
Available labels:
UI - User interface related issues
CLI - Command-line interface related issues
bug - Bug fixes and issue resolutions
feature - New features and enhancements
Examples:
./create-issue.sh "Add dark mode toggle"
./create-issue.sh "Add dark mode toggle" "Implement dark/light theme switcher in settings" "" "UI,feature"
./create-issue.sh "Fix login button styling" "" ./tasks/login-styling "UI,bug"
./create-issue.sh "Add date filter to extract" "Filter commits by date range" "" "CLI,feature"
What it does:
- Analyzes issue content to determine appropriate labels (optional)
- Creates a new GitHub issue with the provided title, description, and labels
- Creates local task directory named
{issue-number}-{title-slug}/
- If task files exist, automatically syncs them to GitHub
- Outputs issue URL and task directory path
Output:
Creating GitHub issue...
Applying labels: UI,feature
✓ GitHub issue created: https://github.com/<github-user>/<repo-name>/issues/189
✓ Created task directory: tasks/189-add-dark-mode-toggle
✅ Task setup complete!
Issue: https://github.com/<github-user>/<repo-name>/issues/189
Task Directory: tasks/189-add-dark-mode-toggle
Task Number: 189
push.sh
Push all task documentation files (SPEC.md, PLAN.md, TEST_PLAN.md, COMMIT_MESSAGE.md) to a GitHub issue as collapsible comments.
Usage:
./push.sh <issue-url-or-number> [task-directory]
Arguments:
issue-url-or-number - Full GitHub URL or just the issue number
task-directory - Directory containing task files (optional, defaults to current directory)
Examples:
./push.sh 188 ./tasks/188-account-deletion
./push.sh https://github.com/<github-user>/<repo-name>/issues/188 ./tasks/188-account-deletion
./push.sh 188
What it does:
- Uploads all four task file types as separate collapsible comments
- Each file type gets a unique marker so it can be updated independently
- Creates new comments or updates existing ones
- Each file wrapped in
<details> section that starts collapsed
Output:
📤 Syncing task files to GitHub issue #188 in <github-user>/<repo-name>
Processing SPEC.md...
+ Creating new comment...
✓ Created
Processing PLAN.md...
↻ Updating existing comment (ID: 123456789)...
✓ Updated
...
✅ Sync complete!
View the issue: https://github.com/<github-user>/<repo-name>/issues/188
push-file.sh
Update a single task file comment on a GitHub issue with a status summary and file content.
Usage:
./push-file.sh <issue-url-or-number> <file-type> <status-file> <content-file>
Arguments:
issue-url-or-number - GitHub issue URL or issue number
file-type - One of: SPEC, PLAN, TEST_PLAN, COMMIT_MESSAGE
status-file - File containing status summary (2 paragraphs + optional bullets)
content-file - File containing the full file content
Examples:
./push-file.sh 188 SPEC SPEC-STATUS.md SPEC.md
./push-file.sh 188 PLAN plan-status.txt PLAN.md
Status File Format:
The status file should contain a 2-paragraph summary describing the document state:
**Status:** [Draft | Complete | Review Needed | etc.]
This is the first paragraph explaining the current state of the document.
It should describe what has been completed, what's pending, or any key status information.
This is the second paragraph providing additional context or details about the document state.
- Key point 1 (optional)
- Key point 2 (optional)
What it does:
- Creates or updates a single comment for the specified file type
- Combines the status summary with the file content in a collapsible section
- Each file type has a unique marker for independent updates
Output:
↻ Updating SPEC comment on issue #188 (ID: 123456789)...
✓ Updated successfully
View the issue: https://github.com/<github-user>/<repo-name>/issues/188
pull.sh
Pull all task documentation files from a GitHub issue to a local task directory. Automatically determines the task directory name from the issue title.
Usage:
./pull.sh <issue-url-or-number>
Arguments:
issue-url-or-number - GitHub issue URL or issue number
Examples:
./pull.sh 188
./pull.sh https://github.com/<github-user>/<repo-name>/issues/188
What it does:
- Fetches the issue title from GitHub
- Converts the title to a URL-safe slug
- Creates task directory as
tasks/{issue-number}-{title-slug}/
- Fetches all four task files from GitHub issue comments
- Extracts content from collapsible sections
- Writes each to local file (SPEC.md, PLAN.md, etc.)
Output:
📥 Fetching issue #188 from <github-user>/<repo-name>...
📥 Pulling task files from GitHub issue #188: "Account deletion and data export"
📁 Task directory: tasks/188-account-deletion-and-data-export
Pulling SPEC.md...
✓ Pulled to SPEC.md
Pulling PLAN.md...
✓ Pulled to PLAN.md
...
✅ Pull complete!
Task directory: tasks/188-account-deletion-and-data-export
pull-file.sh
Pull a single task file from a GitHub issue to a local file.
Usage:
./pull-file.sh <issue-url-or-number> <file-type> [output-file]
Arguments:
issue-url-or-number - GitHub issue URL or issue number
file-type - One of: SPEC, PLAN, TEST_PLAN, COMMIT_MESSAGE
output-file - File to write to (default: {file-type}.md in current directory)
Examples:
./pull-file.sh 188 SPEC
./pull-file.sh 188 PLAN ./my-plan.md
./pull-file.sh 188 SPEC | head -20
Output:
Pure file content (great for piping or redirecting)
read-issue-file.sh
Read a task file from a GitHub issue and output to stdout. Useful for debugging, piping, or quick content inspection.
Usage:
./read-issue-file.sh <issue-url-or-number> <file-type>
Arguments:
issue-url-or-number - GitHub issue URL or issue number
file-type - One of: SPEC, PLAN, TEST_PLAN, COMMIT_MESSAGE
Examples:
./read-issue-file.sh 188 SPEC
./read-issue-file.sh 188 PLAN > my-plan.md
./read-issue-file.sh 188 SPEC | head -20
Output:
Pure file content sent to stdout
log-entry.sh
Add timestamped entries to a task's AI Work Log on a GitHub issue. Creates or updates a running log of work progress throughout the task lifecycle.
Usage:
./log-entry.sh <issue-url-or-number> <entry-text>
Arguments:
issue-url-or-number - GitHub issue URL or issue number
entry-text - Description of work being done (e.g., "Started writing spec")
Examples:
./log-entry.sh 188 "Started writing spec"
./log-entry.sh 188 "Finished writing plan"
./log-entry.sh https://github.com/<github-user>/<repo-name>/issues/190 "Started implementation"
What it does:
- Creates a new "AI Work Log" comment on the issue if it doesn't exist
- Appends timestamped entries to the work log (one per line with format:
- YYYY-MM-DD HH:MM:SS: entry-text)
- Each entry is timestamped and represents a work milestone
- Useful for tracking progress through spec writing, planning, implementation, testing, and completion
Output:
↻ Adding entry to work log on issue #188...
✓ Entry added
View the issue: https://github.com/<github-user>/<repo-name>/issues/188
Task Directory Structure
When using create-issue.sh, directories are automatically named with the issue number:
tasks/
├── 188-account-deletion/
│ ├── SPEC.md (Specification)
│ ├── PLAN.md (Implementation plan)
│ ├── TEST_PLAN.md (Test scenarios)
│ └── COMMIT_MESSAGE.md (Git commit message)
├── 189-add-dark-mode/
│ └── [similar structure]
└── archive/
└── [completed tasks]
Naming Convention: {issue-number}-{task-name-slug}
The issue number in the directory name provides direct reference to the GitHub issue.
Workflow
Creating a New Task
./create-issue.sh "Add authentication" "Implement magic link authentication"
./log-entry.sh 190 "Started writing spec"
./push.sh 190 ./tasks/190-add-authentication
./log-entry.sh 190 "Finished writing spec"
./log-entry.sh 190 "Started writing plan"
./push.sh 190 ./tasks/190-add-authentication
./log-entry.sh 190 "Finished writing plan"
./log-entry.sh 190 "Started implementation"
Converting Existing Tasks to GitHub Issues
If you have an existing task directory without a GitHub issue:
./create-issue.sh "My feature" "Description" ./tasks/my-feature
Syncing During Work
Push workflow (local → GitHub):
./log-entry.sh 188 "Started writing code"
./push-file.sh 188 SPEC SPEC-STATUS.md SPEC.md
./push.sh 188 ./tasks/188-account-deletion
./log-entry.sh 188 "Finished writing code"
Pull workflow (GitHub → local):
./pull.sh 188 ./tasks/188-account-deletion
./pull-file.sh 188 PLAN
./log-entry.sh 188 "Pulled latest files from GitHub"
Task Completion
When finishing a task (via /finish command):
- All work is complete and tested
- Run
push.sh one final time to sync latest versions
- Task directory is archived from
tasks/ to tasks/archive/
- GitHub issue remains as permanent record
Key Features
- ✅ Bidirectional sync - Push changes to GitHub or pull from GitHub
- ✅ Selective updates - Push/pull individual files or all at once
- ✅ Status tracking - Each file can have a 2-paragraph status summary
- ✅ Collapsible display - Large files stay organized on GitHub
- ✅ AI Work Log - Timestamped activity log tracking progress (spec writing, planning, implementation, etc.)
- ✅ Issue creation - Automatically initialize task structure
- ✅ Directory conversion - Convert existing tasks to GitHub issues
- ✅ No git commits - Task files never committed (in
.gitignore)
- ✅ GitHub-centric - Documentation source of truth lives on GitHub
Requirements
gh CLI installed and authenticated
- Bash shell
- Read/write access to the GitHub repository
- Git repository with GitHub remote (for auto-detection)
Integration with Other Commands
With /write-spec:
- Creates SPEC.md locally
- Agent calls
push-file.sh to sync status + content to GitHub
With /write-plan:
- Creates PLAN.md locally
- Agent calls
push-file.sh to sync to GitHub
With /finish:
- Calls
push.sh to sync all files to GitHub as final step
- Task archived and GitHub issue contains complete documentation
Setup & Configuration
The scripts automatically detect the GitHub repository from your current git remote (origin). No configuration needed!
Repository Detection:
-
Auto-detect (recommended): Scripts automatically extract owner/repo from git remote get-url origin
- Supports both HTTPS:
https://github.com/owner/repo.git
- Supports SSH:
git@github.com:owner/repo.git
-
Environment variables (optional override):
export GITHUB_OWNER="myorg"
export GITHUB_REPO="myrepo"
-
Full URLs (always works):
./push.sh "https://github.com/otherorg/otherrepo/issues/42" ./tasks/42-myfeature
Error Handling:
If you run scripts outside a git repository or without a GitHub remote, you'll see a helpful error:
Error: Not in a git repository
Please run this command from within a git repository, or set GITHUB_OWNER and GITHUB_REPO environment variables