with one click
git-workflow
// Enforces branch and commit discipline — never push directly to main, always work on a named feature branch, always ask the user for a branch name before touching any file, and commit after every completed todo item.
// Enforces branch and commit discipline — never push directly to main, always work on a named feature branch, always ask the user for a branch name before touching any file, and commit after every completed todo item.
[HINT] Download the complete skill directory including SKILL.md and all related files
| name | git-workflow |
| description | Enforces branch and commit discipline — never push directly to main, always work on a named feature branch, always ask the user for a branch name before touching any file, and commit after every completed todo item. |
| license | MIT |
| compatibility | opencode |
STOP. Before reading a single file or running a single command:
- Ask the user for a branch name (suggest one based on the task).
- Create and check out that branch.
Only after the branch is checked out may you read files, write code, or run builds.
If you are mid-session and have already done work without a branch, create the branch immediately (all unstaged changes carry over automatically), then commit what is done before continuing.
main.main.feat/poo-animation, fix/health-bar-colour).The following actions each require explicit user instruction before performing them. Do not bundle or assume permission for one because permission was given for another:
| Action | What "explicit" means |
|---|---|
Push a branch to origin | User says "push the branch" or "push to origin" |
Merge into main | User says "merge to main" or "merge it" |
Push main to origin | User says "push main" |
| Create a tag | User says "tag it" or "create a tag" |
Push a tag to origin | User says "push the tag" |
| Create a GitHub release | User says "create a release" or "publish it" |
Never chain these steps together automatically. After completing work, stop and report what is done. Ask the user how they want to proceed with each step.
<type>: <short description> — types are feat, fix, chore, refactor, docs, test.After any build command completes (VS Code, PyCharm, or OpenCode), you must do all three of the following before stopping or waiting:
chore: rebuild artifacts for vX.Y.Z — do not wait for the user to ask. The commit is already implied by the release flow. Stage and commit all three artifact files in a single commit.Never silently halt after a build. Never leave artifact files uncommitted. Never wait for the user to say "keep going" after a successful build.
Do not rebuild on every individual commit. Rebuild once, as a dedicated
chore: commit, immediately before the branch is ready to merge to main:
| IDE | Command (run from the given directory) | Output artifact to commit |
|---|---|---|
| VS Code | npx @vscode/vsce package (run from vscode/) | vscode/codotchi-X.Y.Z.vsix |
| PyCharm | See PyCharm build procedure below | pycharm/build/distributions/pycharm-gotchi-X.Y.Z.zip |
The build commit must come after all feature, fix, test, and doc commits on the branch — never rebuild mid-branch and then continue adding changes on top.
Never merge to main without both artifacts present and up to date.
The PyCharm build frequently fails with a file-lock error on extnet.dll when
another Java process is still running from a previous build attempt or IDE session.
Always follow these steps in order:
Kill all lingering java/gradle processes before running the build:
Get-Process | Where-Object { $_.Name -like "*java*" -or $_.Name -like "*gradle*" } | Stop-Process -Force
Start-Sleep -Seconds 3
Clear the Gradle configuration cache (it gets poisoned when a build is interrupted mid-extraction):
Remove-Item -Recurse -Force ".gradle\configuration-cache" -ErrorAction SilentlyContinue
(run from pycharm/)
Run the build with -x buildSearchableOptions --no-configuration-cache to prevent re-poisoning and skip the task that causes the file-lock hang:
$env:JAVA_HOME = 'C:\Users\DylanSiow-Lee\.gradle\caches\modules-2\files-2.1\com.jetbrains\jbre\jbr_jcef-17.0.10-windows-x64-b1207.12\extracted\jbr_jcef-17.0.10-windows-x64-b1207.12'
& '.\gradlew.bat' buildPlugin -x buildSearchableOptions --no-configuration-cache
(run from pycharm/)
Why
-x buildSearchableOptions? This task launches a headless IDE sandbox that extractsextnet.dllfrom the JBR tarball. When PyCharm is open it holds a lock on that DLL, causing the build to fail or hang every time. Skipping it produces a fully functional plugin zip.
Note: The
powershell -Command "..."one-liner form does not reliably set$env:JAVA_HOMEinside the child shell on this machine. Always use the two-statement form above (set the variable, then call gradlew) in the same PowerShell session.
The Bash tool default timeout is 120 000 ms (2 min). The PyCharm build can take
up to 3–4 min on a cold daemon. Always use timeout: 240000 (4 min) when
invoking the build or unitTest task.
If the build times out:
timeout: 240000.Never leave the build in an unresolved state. If the build succeeds on a retry, continue immediately with the next step — do not wait for the user to say "keep going".
NEVER run gradlew test — the org.jetbrains.intellij plugin hijacks the
built-in test task to set up an IDE sandbox, which re-extracts the JBR and
fails with a file-lock error (extnet.dll) when any IDE or Java process is
running.
Instead, always run the custom unitTest task:
$env:JAVA_HOME = 'C:\Users\DylanSiow-Lee\.gradle\caches\modules-2\files-2.1\com.jetbrains\jbre\jbr_jcef-17.0.10-windows-x64-b1207.12\extracted\jbr_jcef-17.0.10-windows-x64-b1207.12'
& '.\gradlew.bat' unitTest --no-configuration-cache
(run from pycharm/)
The unitTest task runs JUnit 5 tests directly on the JVM toolchain — no
sandbox, no JBR extraction, no IDE dependency. It is safe to run at any time,
including while PyCharm or VS Code is open.
The release flow has multiple discrete steps. Each step requires its own explicit user instruction. Do not perform any of them automatically at the end of a feature or bug fix.
Typical release flow (each line needs separate approval):
chore: rebuild artifacts for vX.Y.Z — this must be the last commit on the branch before mergingnode scripts/package.js (run from opencode-codotchi/) and commit as chore: rebuild opencode-codotchi zip for vX.Y.Znode bin/install.js --install (run from opencode-codotchi/) — never run without explicit user confirmationgit push origin <branch> — push the feature branchgit checkout main && git merge <branch> — merge to maingit push origin main — push maingit tag vX.Y.Z — create the version tag locally on maingit push origin vX.Y.Z — push the tag (bypasses the rule with a "Bypassed rule violations" warning — this is expected and the tag is created successfully)releases/, apply the 3-version rule, move older releases to releases/old_releases/ — see release-management skill — commit and pushUse a plain git push:
git push origin vX.Y.Z
The remote will respond with a "Bypassed rule violations" warning — this is expected. The tag is created on the remote successfully despite the warning. No API call or PAT required.
When creating a GitHub release for vX.Y.Z, the release body must cover everything new since the previous GitHub release (not the previous git tag). These two are often different — some tags are never published as GitHub releases, and some GitHub releases are deleted. Follow these steps:
Find the most recent GitHub release (not git tag) by fetching the releases list:
# use get_release.ps1 pattern to call:
# GET https://api.github.com/repos/dylscoop/codotchi/releases
# look at the tag_name of the first (most recent) entry
This tells you the <prev-release-tag> to use as the baseline.
Collect all non-merge commits between the previous release tag and the new one:
git log <prev-release-tag>..vX.Y.Z --oneline --no-merges
For each feat: and fix: commit, summarise the user-visible change. Group into sections:
feat: commits)fix: commits; cross-reference BUGFIX-NNN if applicable)chore:, docs:, and test: commits from the release body entirelyInclude the artifact filenames so users know exactly what to download:
## Artifacts
- `codotchi-X.Y.Z.vsix` — VS Code extension
- `pycharm-codotchi-X.Y.Z.zip` — PyCharm plugin
- `opencode-codotchi-X.Y.Z.zip` — OpenCode plugin
gh CLI is not available on this machine. Use the GitHub REST API via a PowerShell script instead (see below).
gh CLIgh is not installed. Use this PowerShell approach every time.
WARNING: The Windows Credential Manager may only store one entry for
github.comand it may belong todsiowlee(a different account without push access). Always verify the retrieved token's username. If it returnsdsiowlee, ask the user to paste thedylscoopPAT directly — do not use thedsiowleetoken.
Attempt retrieval with:
$lines = @('protocol=https', 'host=github.com', '')
$creds = $lines | & 'C:\Program Files\Git\mingw64\libexec\git-core\git-credential-wincred.exe' get
$creds # check that username=dylscoop before using the password
$token = ($creds | Where-Object { $_ -match '^password=' }) -replace '^password=', ''
If the username is not dylscoop, ask the user to paste their PAT. A classic PAT
(prefix ghp_) with repo scope works for both git push and API calls. Fine-grained
PATs (prefix github_pat_) have been observed to pass API permission checks but still
fail git push with 403 — prefer classic PATs for pushing.
Note: the pipe-from-
echoform (echo 'protocol=https' | ...) does not work in PowerShell 5.1 — use the@()array form above.
Inline PowerShell with complex quoting is unreliable in the Bash tool. Always write the
script to a temp file and execute it with -ExecutionPolicy Bypass -File:
# create_release.ps1 (delete after use)
$token = 'PASTE_TOKEN_HERE'
$releaseBody = @"
## Features
- ...
## Bug fixes
- ...
## Artifacts
- ``codotchi-X.Y.Z.vsix`` - VS Code extension
- ``pycharm-codotchi-X.Y.Z.zip`` - PyCharm plugin
"@
$payload = @{
tag_name = 'vX.Y.Z'
target_commitish = 'main'
name = 'vX.Y.Z - Short release headline'
body = $releaseBody
draft = $false
prerelease = $false
} | ConvertTo-Json -Depth 3
$headers = @{
Authorization = "token $token"
Accept = 'application/vnd.github+json'
'X-GitHub-Api-Version' = '2022-11-28'
}
try {
$r = Invoke-RestMethod -Uri 'https://api.github.com/repos/dylscoop/codotchi/releases' `
-Method Post -Headers $headers -Body $payload -ContentType 'application/json'
Write-Host "SUCCESS: $($r.html_url)"
} catch {
Write-Host "ERROR: $($_.Exception.Message)"
Write-Host $_.ErrorDetails.Message
}
Run it:
powershell -ExecutionPolicy Bypass -File create_release.ps1
Then delete the script immediately (it contains the PAT).
``) inside @"..."@ here-strings to produce literal backticks in the Markdown body.dylscoop/codotchi; update the URI if the repo ever changes.https://github.com/dylscoop/codotchi/releases.