Installs into .claude/skills of the current project.
Are you the author of Gen Taskfiles?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/sgaunet-gen-taskfiles)
---
name: gen-taskfiles
description: Generate mise.toml, Taskfile.yml, Taskfile_dev.yml, and .pre-commit-config.yaml for Go projects with comprehensive task automation
argument-hint: "[--force] [--dry-run]"
user-invocable: true
disable-model-invocation: true
allowed-tools: Read, Write, Bash(git:*), Bash(test:*), AskUserQuestion
---
# Generate Taskfiles
Instantly create a complete Task automation setup for Go projects including a `mise.toml` (development tool versions), the main Taskfile, development tasks, and pre-commit hooks configuration. This skill provides a comprehensive task runner setup with linting, testing, building, and release automation — and pins the tool versions so local development and CI stay in sync.
## Why This Skill Exists
**Problem**: Setting up task automation for Go projects requires manually creating Taskfile configuration, understanding Task syntax, pinning tool versions, and configuring pre-commit hooks - a 20-30 minute process.
**Solution**: One-command generation that:
- Creates complete dev setup (4 files): `mise.toml`, `Taskfile.yml`, `Taskfile_dev.yml`, `.pre-commit-config.yaml`
- Pins tool versions in `mise.toml` (go, task, golangci-lint, goreleaser) so local dev and CI use identical versions
- Includes tasks: lint, test, build, snapshot, release, image, doc
- Configures pre-commit hooks for automated quality checks
- Integrates with golangci-lint and goreleaser
**mise.toml** is the single source of truth for tool versions. It is consumed by the CI generators (`/gen-github-dir`, `/gen-forgejo-dir`, `/gen-gitlab-ci`), whose workflows install tools via mise and then run `task …`. See https://mise.jdx.dev.
## Content Generation Rules
**CRITICAL**: When generating any content (taskfiles, commit messages, or any other output):
- **NEVER** add Claude Code attribution or co-authorship
- **NEVER** include phrases like "Generated by Claude", "Created with Claude Code", or similar
- **NEVER** add "Co-Authored-By: Claude" in commit messages or documentation
- All generated content should appear as if written by a human developer
- Focus on technical accuracy and providing working templates
## Process (6 Phases)
### Phase 1: Prerequisites Validation
**Critical checks before proceeding:**
1. **Validate Git repository:**
```bash
git rev-parse --git-dir
```
- If fails: Exit with error "Not a git repository. Run 'git init' first."
2. **Validate Go project:**
```bash
test -f go.mod
```
- If fails: Exit with error "go.mod not found. This skill is for Go projects only."
3. **Check existing taskfiles:**
```bash
test -f mise.toml
test -f Taskfile.yml
test -f Taskfile_dev.yml
test -f .pre-commit-config.yaml
```
- Store which files exist: `existingFiles = []`
- If any exist: Store `hasExistingFiles = true`
- Note `mise.toml` separately as `existingMise = true|false` (a pre-existing
`mise.toml` already pins tool versions; default to preserving it unless `--force`).
4. **Verify skill assets directory:**
- Use Read tool to verify `${CLAUDE_PLUGIN_ROOT}/assets/taskfiles/Taskfile.yml` exists
- Use Read tool to verify `${CLAUDE_PLUGIN_ROOT}/assets/mise/mise.toml` exists
- If either fails: Exit with error "Skill assets directory not found at ${CLAUDE_PLUGIN_ROOT}/assets/. Plugin may be corrupted. Reinstall the go-specialist plugin."
5. **Check for supporting configs (non-blocking):**
```bash
test -f .golangci.yml
test -f .goreleaser.yml
```
- If .golangci.yml missing: Store `linterMissing = true` (warn in Phase 6)
- If .goreleaser.yml missing: Store `goreleaserMissing = true` (warn in Phase 6)
### Phase 2: Argument Parsing
Parse skill arguments from `$argument` string:
**Supported flags:**
- `--force`: Skip confirmation for existing files
- `--dry-run`: Show preview without writing files
**Parsing logic:**
```
arguments = split($argument by space)
for each arg in arguments:
if arg == "--force": set forceMode = true
if arg == "--dry-run": set dryRunMode = true
```
### Phase 3: Template Reading
**Read all template files** from skill assets directory:
**Files to read:**
1. **mise.toml**
- Path: `${CLAUDE_PLUGIN_ROOT}/assets/mise/mise.toml`
- Target: `mise.toml` (project root)
2. **Taskfile.yml** (66 lines)
- Path: `${CLAUDE_PLUGIN_ROOT}/assets/taskfiles/Taskfile.yml`
- Target: `Taskfile.yml` (project root)
3. **Taskfile_dev.yml** (14 lines)
- Path: `${CLAUDE_PLUGIN_ROOT}/assets/taskfiles/Taskfile_dev.yml`
- Target: `Taskfile_dev.yml` (project root)
4. **.pre-commit-config.yaml** (25 lines)
- Path: `${CLAUDE_PLUGIN_ROOT}/assets/taskfiles/.pre-commit-config.yaml`
- Target: `.pre-commit-config.yaml` (project root)
**Template handling:**
- Store content in memory for Phase 3.5 substitution
- All substitutions handled in Phase 3.5 (not inline)
**Error handling:**
- If any Read fails: Exit with error "Failed to read template file: {filename}. Plugin may be corrupted. Ensure ${CLAUDE_PLUGIN_ROOT}/assets/taskfiles/ directory exists."
### Phase 3.5: Auto-Detection & Substitution
**Detection Function Library:** Use the shared detection functions from `${CLAUDE_PLUGIN_ROOT}/assets/detection-functions.md`. Read that file to get all bash detection functions (`detect_project_name`, `detect_git_owner`, `detect_main_dir`, `detect_registry`, `detect_go_version`, `detect_golangci_lint_version`, `detect_goreleaser_version`, `strip_leading_v`, `substitute_placeholders`, `substitute_version_placeholders`).
**Detection Workflow:**
1. **Detect all values:**
```bash
PROJECT_NAME=$(detect_project_name)
OWNER=$(detect_git_owner)
REGISTRY=$(detect_registry)
MAIN_DIR=$(detect_main_dir)
```
0. **Detect tool versions for mise.toml:**
```bash
GO_VERSION=$(detect_go_version)
GOLANGCI_LINT_VERSION=$(detect_golangci_lint_version)
GORELEASER_VERSION=$(detect_goreleaser_version)
GOLANGCI_LINT_VERSION_BARE=$(strip_leading_v "${GOLANGCI_LINT_VERSION:-v2.2.2}")
mise_template=$(substitute_version_placeholders "$mise_template" \
"GO_VERSION=${GO_VERSION:-1.25}" \
"GOLANGCI_LINT_VERSION_BARE=${GOLANGCI_LINT_VERSION_BARE:-2.2.2}" \
"GORELEASER_VERSION=${GORELEASER_VERSION:-v2.12.0}")
```
- `mise.toml` uses the bare golangci-lint version (no leading `v`), the
v-prefixed goreleaser tag, and `major.minor` Go from go.mod.
2. **Handle missing critical values:**
- If `PROJECT_NAME` is empty: Use "app" as default
- If `OWNER` is empty: Preserve `[OWNER]` placeholder
- Non-critical values have sensible defaults
3. **Substitute placeholders in Taskfile.yml template:**
```bash
taskfile_template=$(substitute_placeholders "$taskfile_template" \
"$PROJECT_NAME" "$OWNER" "$REGISTRY" "$MAIN_DIR")
```
4. **Detect pre-commit-hooks version:**
```bash
PRE_COMMIT_HOOKS_VERSION=$(detect_pre_commit_hooks_version)
```
- If empty (gh not available or API failure): Use fallback `v4.3.0`
5. **Substitute version placeholders in .pre-commit-config.yaml template:**
```bash
precommit_template=$(substitute_version_placeholders "$precommit_template" \
"PRE_COMMIT_HOOKS_VERSION=${PRE_COMMIT_HOOKS_VERSION:-v4.3.0}")
```
Note: Taskfile_dev.yml has no placeholders
### Phase 4: User Confirmation
**Build preview summary:**
```
Files to be created:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✅ mise.toml - Pinned dev tool versions (go, task, golangci-lint, goreleaser)
✅ Taskfile.yml (66 lines) - Main task definitions
✅ Taskfile_dev.yml (14 lines) - Development tasks
✅ .pre-commit-config.yaml (25 lines) - Git pre-commit hooks
Total: 4 files
[If existingMise == true and not --force:]
ℹ️ mise.toml already exists — it will be PRESERVED (your tool pins are kept).
✅ Auto-detected Configuration
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Project Settings:
• Project name: <PROJECT_NAME> (from go.mod)
• Binary name: <PROJECT_NAME>
• Main directory: <MAIN_DIR>
Tool Versions (mise.toml):
• Go: <GO_VERSION> (from go.mod)
• golangci-lint: <GOLANGCI_LINT_VERSION_BARE>
• goreleaser: <GORELEASER_VERSION>
• task: latest
Repository Settings:
• Owner: <OWNER> (from git remote)
• Registry: <REGISTRY>
Task Categories:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🔧 Development:
- default: List all available tasks
- check-before-commit: Run all quality checks
- lint: Run golangci-lint
- test: Run unit tests with race detection
- build: Build project binaries
📦 Release:
- snapshot: Create snapshot release (goreleaser)
- release: Create production release (goreleaser)
- image: Build and push Docker image
📚 Documentation:
- doc: Start godoc server
🛠️ Dev Tools (Taskfile_dev.yml):
- dev:install-pre-commit: Install pre-commit hooks
- dev:pre-commit: Run all pre-commit hooks manually
🎯 Pre-commit Hooks:
- check-yaml: Validate YAML syntax
- check-added-large-files: Prevent large files
- unit-tests: Run tests before commit
- lint: Run linter before commit
- build: Test build before commit
[If hasExistingFiles == true:]
⚠️ WARNING: Some files already exist and will be overwritten:
[List existing files]
```
**Dry run mode:**
If `dryRunMode == true`:
- Show preview summary above
- Display first 20 lines of each file
- Show customization requirements
- Display next steps guide
- Exit without creating files
**Confirmation logic:**
1. **If `--force` flag provided:** Skip confirmation, proceed to Phase 5
2. **If existing files without `--force`:**
```
Use AskUserQuestion:
Question: "Task configuration files already exist. Overwrite?"
Options:
1. "Yes, overwrite files" [Recommended if upgrading]
2. "Show full preview first"
3. "Cancel"
If option 2: Display full content preview, then re-ask confirmation
If option 3: Exit gracefully
```
3. **If no existing files:**
```
Use AskUserQuestion:
Question: "Create task configuration files (3 files)?"
Options:
1. "Yes, create files"
2. "Show preview first"
3. "Cancel"
```
### Phase 5: File Creation
**File writing sequence:**
Write files in order:
1. `mise.toml`
- Write the version-substituted template to project root
- **Preserve-if-exists:** if `existingMise == true` and `--force` was NOT
given, skip writing (keep the project's existing tool pins) and note it in
the report. With `--force`, overwrite like the other files.
2. `Taskfile.yml`
- Replace `BINFILE: gitlab-backup` with detected binary name
- Write to project root
3. `Taskfile_dev.yml`
- Write as-is to project root
4. `.pre-commit-config.yaml`
- Write as-is to project root
**For each file:**
- Use Write tool with full file path
- Write content from Phase 3 templates
- Track success/failure status
- Continue with remaining files if one fails (partial success acceptable)
**Error handling:**
- If individual file write fails: Log error, continue with next file
- If all writes fail: Report failure with details
- If partial success: Report which files succeeded/failed
**Track results:**
```
successfulFiles = []
failedFiles = []
for each file:
try write:
if success: add to successfulFiles
if failure: add to failedFiles
```
### Phase 6: Validation & Success Report
**Post-creation validation:** for each file in `successfulFiles`, confirm it exists and is
non-zero; move any failure to `failedFiles`.
**Report to the user** — cover these facts; no fixed layout required:
- **Files written:** each path with its line count, and a total. Mark `mise.toml` as
created vs. preserved (an existing one is never overwritten).
- **Detected values:** project name and binary name (from go.mod), main directory, owner
(from git remote), registry, the Go / golangci-lint / goreleaser versions pinned in
`mise.toml`, and the pre-commit hooks version.
- **Key tasks:** `task` or `task -a` lists everything; highlight `task check-before-commit`,
`task lint`, `task test`, `task build`, `task snapshot`, `task release`, `task doc`,
`task dev:install-pre-commit`, `task dev:pre-commit`.
- **Prerequisites:** tool versions are pinned in `mise.toml`, so mise is installed once per
machine (`brew install mise`, or `curl https://mise.run | sh` —
https://mise.jdx.dev/getting-started.html) and then provides go, task, golangci-lint and
goreleaser at the exact CI versions. Follow with `mise install`, plus either
`mise activate <shell>` in the shell rc or one-offs via `mise exec -- task lint`.
pre-commit installs separately (`brew install pre-commit` or `pip install pre-commit`),
then `task dev:install-pre-commit`.
- **Missing configs:** if `linterMissing`, warn that `.golangci.yml` is absent and point at
`/gen-linter`; if `goreleaserMissing`, same for `.goreleaser.yml` and `/gen-goreleaser`.
Note that mise supplies both binaries either way — only the config is missing.
- **Optional customizations:** multi-binary projects need the build task extended; the
commented-out `trailing-whitespace` and `end-of-file-fixer` hooks can be enabled; the
Docker image is already wired to `<REGISTRY>/<OWNER>/<PROJECT_NAME>:latest` and worth a
check.
- **Pre-commit hooks:** installed with `task dev:install-pre-commit`, tested with
`task dev:pre-commit`, then run on every `git commit` — checking YAML syntax, large
files, unit tests, the linter and a snapshot build. `git commit --no-verify` bypasses
them in an emergency.
- **Next steps:** install mise and run `mise install`, review `mise.toml` and
`Taskfile.yml`, install the hooks, generate any missing config, run `task lint`,
`task test` and `task build`, then `git add mise.toml Taskfile*.yml .pre-commit-config.yaml`
and `git commit -m "build: add mise, task automation and pre-commit hooks"`.
- **Docs:** https://taskfile.dev · https://pre-commit.com · `task -a` for the task list.
**On failure:** report which files were written, which failed and why, and that `--force`
retries. Partial success is a warning, total failure an error — for a total failure also
name the likely causes (permissions, disk space, filesystem restrictions).
## Arguments
Arguments are parsed from the `argument` string parameter:
- **`--force`**: Skip confirmation prompt and overwrite existing files
- Use when: Upgrading existing task configuration
- Behavior: Overwrites files directly without confirmation
- **`--dry-run`**: Preview files without writing to disk
- Shows: File list, line counts, preview of content
- Writes: Nothing
- Use when: Reviewing what will be created before committing
**Parsing example:**
```
argument = "--force"
Split by space, check for each flag:
- forceMode = true
- dryRunMode = false
```
## Error Handling
### Critical Errors (Exit Immediately)
**Not a Git repository:**
```
❌ Error: Not a git repository
This skill requires a Git repository. Initialize one:
git init
git add .
git commit -m "Initial commit"
```
**Not a Go project:**
```
❌ Error: go.mod not found
This skill is for Go projects only. Initialize a Go module:
go mod init github.com/username/project
```
**Skill assets missing:**
```
❌ Error: Skill assets directory not found
The go-specialist plugin may be corrupted. Try:
1. Reinstalling the plugin
2. Updating Claude Code to latest version
3. Reporting issue at: https://github.com/sgaunet/claude-plugins/issues
```
### Warning Errors (Continue with Warnings)
**Existing task files:**
- Without `--force`: Request user confirmation
- With `--force`: Overwrite silently
**Missing .golangci.yml or .goreleaser.yml:**
- Don't block creation
- Warn in success report
- Suggest using the `/gen-linter` or `/gen-goreleaser` skills
### Recovery Actions
**If file write fails:**
```
❌ Error: Failed to write [filename]
Check:
1. Current directory is writable
2. Sufficient disk space
3. No file system restrictions
Current permissions: [show with ls -ld .]
```
## File Mapping
| Source Path | Target (Relative to CWD) | Lines | Purpose |
|-------------|--------------------------|-------|---------|
| `${CLAUDE_PLUGIN_ROOT}/assets/mise/mise.toml` | `mise.toml` | ~35 | Pinned dev tool versions (preserve-if-exists) |
| `${CLAUDE_PLUGIN_ROOT}/assets/taskfiles/Taskfile.yml` | `Taskfile.yml` | 66 | Main task definitions |
| `${CLAUDE_PLUGIN_ROOT}/assets/taskfiles/Taskfile_dev.yml` | `Taskfile_dev.yml` | 14 | Development tasks |
| `${CLAUDE_PLUGIN_ROOT}/assets/taskfiles/.pre-commit-config.yaml` | `.pre-commit-config.yaml` | 25 | Git pre-commit hooks |
## Integration with Other Skills
**Works with:**
- `/commit`: Commit generated taskfiles
- `/gen-linter`: Generate .golangci.yml (required for lint task)
- `/gen-goreleaser`: Generate .goreleaser.yml (required for snapshot/release tasks)
- `/gen-github-dir`: GitHub workflows can call task commands
- `/gen-gitlab-ci`: GitLab CI can call task commands
**Typical Workflow:**
```bash
# 1. Generate task configuration (also writes mise.toml)
/gen-taskfiles
# 2. Generate supporting configs
/gen-linter # Creates .golangci.yml
/gen-goreleaser # Creates .goreleaser.yml
# 3. Install tools (one mise install pins everything) and hooks
brew install mise pre-commit # or: curl https://mise.run | sh
mise install # installs go, task, golangci-lint, goreleaser
task dev:install-pre-commit
# 4. Test tasks
task lint
task test
task build
# 5. Commit everything
git add mise.toml Taskfile*.yml .pre-commit-config.yaml .golangci.yml .goreleaser.yml
git commit -m "build: add mise, task automation and pre-commit hooks"
# 6. Verify hooks work
# Make a test change, try to commit - hooks should run
```
## Task Descriptions
### Main Tasks (Taskfile.yml)
**default**: List all available tasks
- Dependencies: Checks for pre-commit hooks installed
- Command: `task -a`
**check-before-commit**: Run complete quality check suite
- Dependencies: test, snapshot, lint (in order)
- Use: Before pushing code or creating PR
**lint**: Run golangci-lint
- Command: `golangci-lint run`
- Requirements: .golangci.yml file
**test**: Run unit tests with race detection
- Command: `go test -count=2 -race ./...`
- Runs tests twice to catch flaky tests
- Race detector finds concurrency issues
**build**: Build project binaries
- Command: CGO-disabled builds for static binaries
- Customize: Update for your binary names
**image**: Build and push Docker image
- Dependencies: build task
- Customize: Update registry and image name
**doc**: Start godoc documentation server
- Command: `godoc -http=:6060`
- Access: http://localhost:6060
**snapshot**: Create snapshot release
- Command: `goreleaser --clean --snapshot`
- Requirements: .goreleaser.yml file
- Use: Test release process without publishing
**release**: Create production release
- Command: `goreleaser --clean`
- Requirements: .goreleaser.yml file, git tag
- Use: On tagged commits to publish release
### Development Tasks (Taskfile_dev.yml)
**dev:install-pre-commit**: Install pre-commit hooks
- Command: `pre-commit install`
- Run once: After cloning repository
**dev:pre-commit**: Run all pre-commit hooks manually
- Command: `pre-commit run --all-files`
- Use: Test hooks before committing
## Pre-commit Hooks Configuration
**.pre-commit-config.yaml** configures automatic quality checks:
**Standard hooks** (from pre-commit/pre-commit-hooks):
- `check-yaml`: Validate YAML syntax (enabled)
- `check-added-large-files`: Prevent commits of large files (enabled)
- `trailing-whitespace`: Remove trailing whitespace (commented, can enable)
- `end-of-file-fixer`: Ensure files end with newline (commented, can enable)
**Local hooks** (run task commands):
- `unit-tests`: Run `task test` before commit
- `lint`: Run `task lint` before commit
- `build`: Run `task snapshot` before commit
All local hooks use `pass_filenames: false` to run full checks, not per-file.
## Best Practices
**Before running this skill:**
1. Ensure git repository initialized
2. Have go.mod configured
3. Review task documentation: https://taskfile.dev
**After generation:**
1. Review and customize Taskfile.yml
2. Generate .golangci.yml and .goreleaser.yml if missing
3. Install Task runner if not already installed
4. Install pre-commit: `task dev:install-pre-commit`
5. Test all tasks: `task lint`, `task test`, `task build`
6. Commit with meaningful message
**Ongoing usage:**
1. Run `task check-before-commit` before pushing code
2. Let pre-commit hooks catch issues automatically
3. Use `task snapshot` to test releases locally
4. Keep Task and pre-commit tools updated
5. Add custom tasks as project needs evolve
## Limitations
**This skill does NOT:**
- Generate .golangci.yml (use `/gen-linter` skill)
- Generate .goreleaser.yml (use `/gen-goreleaser` skill)
- Install Task runner or pre-commit tools (manual installation required)
- Modify existing taskfiles intelligently (use `--force` to overwrite)
- Install pre-commit hooks automatically (run `task dev:install-pre-commit`)
- Customize binary names automatically (detects from go.mod, may need manual adjustment)
**Scope boundaries:**
- Only handles task and pre-commit configuration files
- Templates are opinionated (aligned with gitlab-backup project patterns)
- Assumes standard Go project structure
- Requires manual customization for multi-binary projects
- Docker image task requires customization for your registry
## Examples
```bash
# Standard generation (3 files)
/gen-taskfiles
# Preview before creating
/gen-taskfiles --dry-run
# Overwrite existing configuration
/gen-taskfiles --force
# Force with dry run
/gen-taskfiles --force --dry-run
```
## Output Summary
**Standard mode (default):**
- 4 files created (mise.toml + 3 task files)
- Complete task automation setup with pinned tool versions and pre-commit hooks
**Dry run mode (`--dry-run`):**
- 0 files created
- Preview shown
- Safe exploration
## Task vs Make
**Why Task instead of Make?**
- YAML syntax (easier than Makefile)
- Cross-platform (Windows, macOS, Linux)
- Built-in parallel execution
- Better dependency management
- Includes from other taskfiles
- Modern tool designed for development workflows
**Migration from Make:**
If you have a Makefile, you can:
1. Keep both (Task can call make targets)
2. Gradually migrate targets to Taskfile.yml
3. Use Task as the primary interface, delegate to make when needed