@maccesar/aiskills 1.21.1 → 1.22.0
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/README.md +19 -14
- package/lib/commands/doctor.js +10 -5
- package/lib/config.js +3 -4
- package/lib/symlink.js +5 -4
- package/package.json +2 -1
- package/skills/release/SKILL.md +26 -0
- package/skills/release/agents/openai.yaml +6 -0
- package/{commands/release.md → skills/release/references/workflow.md} +46 -39
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
`aiskills` is a toolkit of curated skills for AI coding assistants. It provides skill files for Claude Code, Gemini CLI, or Codex CLI.
|
|
10
10
|
|
|
11
|
-
Each skill is a small knowledge package: a `SKILL.md` file with YAML frontmatter plus
|
|
11
|
+
Each skill is a small knowledge package: a `SKILL.md` file with YAML frontmatter plus optional references, scripts, and invocation policy. Most activate when a prompt matches; sensitive workflows such as `release` can require explicit invocation.
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
|
@@ -73,6 +73,7 @@ All three platforms use the same Agent Skills format: a `SKILL.md` file with YAM
|
|
|
73
73
|
| vscode-extension-dev | VS Code | VS Code Extension API docs | 14 files |
|
|
74
74
|
| stitch-showcase | Design Tools | Google Stitch export workflow | 16 files |
|
|
75
75
|
| session-log | Project | Convention + 3 A/B rounds | 2 files |
|
|
76
|
+
| release | Publishing | Portable, confirmation-gated workflow | 1 file |
|
|
76
77
|
| seo-launch | Web / SEO | Head tags, share cards, server files | 5 files |
|
|
77
78
|
| npm-supply-chain | npm / CI | npm and GitHub changelogs, 2025–2026 | 5 files |
|
|
78
79
|
|
|
@@ -80,20 +81,22 @@ Use `aiskills list` to see available skills from the command line. Pull requests
|
|
|
80
81
|
|
|
81
82
|
---
|
|
82
83
|
|
|
83
|
-
##
|
|
84
|
+
## Explicit-only release skill
|
|
84
85
|
|
|
85
|
-
|
|
86
|
+
End-to-end release janitor that works across project types: npm, Titanium (`tiapp.xml`), Composer, Cargo, CocoaPods, or versionless (git-tag-only) repos. **Designed for a dirty working tree** — it groups your uncommitted work into semantic commits, then ships the release on top.
|
|
86
87
|
|
|
87
|
-
|
|
88
|
-
| ---------- | ------------------------------------------------------------------------------ |
|
|
89
|
-
| `/release` | Full release workflow: detect project, bump semver, update CHANGELOG + README, commit, push, tag, GitHub release |
|
|
88
|
+
Unlike the other skills, `release` is never supposed to activate merely because a repository looks ready. Name it explicitly:
|
|
90
89
|
|
|
91
|
-
|
|
90
|
+
| Platform | Invocation |
|
|
91
|
+
| --- | --- |
|
|
92
|
+
| Claude Code | `/release [patch\|minor\|major]` |
|
|
93
|
+
| Codex CLI | `$release [patch\|minor\|major]` |
|
|
94
|
+
| Gemini CLI | `Use the release skill [with a patch\|minor\|major bump]` |
|
|
92
95
|
|
|
93
|
-
|
|
96
|
+
Codex carries platform-specific metadata that disables implicit invocation. Claude Code has its own equivalent frontmatter field, but adding it to this universal `SKILL.md` makes Codex reject the skill; the common body therefore enforces the boundary for Claude and Gemini: the prompt must name `release` before the workflow may proceed. Gemini still asks for activation consent. Every platform then stops again at the release plan and requires a second explicit confirmation before any mutation.
|
|
94
97
|
|
|
95
98
|
When to use it:
|
|
96
|
-
- You have weeks of work in the working tree (with maybe a few interim commits you made along the way) and want one
|
|
99
|
+
- You have weeks of work in the working tree (with maybe a few interim commits you made along the way) and want one workflow to clean everything into proper semantic commits and ship a release.
|
|
97
100
|
- You maintain `CHANGELOG.md` in Keep-a-Changelog format and want the `[Unreleased]` section promoted automatically.
|
|
98
101
|
- You want the bump level inferred from Conventional Commits across both your existing commits and the proposed new ones, with the option to override.
|
|
99
102
|
|
|
@@ -101,7 +104,8 @@ Example prompts:
|
|
|
101
104
|
```
|
|
102
105
|
/release
|
|
103
106
|
/release minor
|
|
104
|
-
|
|
107
|
+
$release major
|
|
108
|
+
Use the release skill with a patch bump
|
|
105
109
|
```
|
|
106
110
|
|
|
107
111
|
How it works:
|
|
@@ -128,15 +132,16 @@ Language policy (two independent axes):
|
|
|
128
132
|
Hard restrictions:
|
|
129
133
|
- Never `--force-push`, `--amend` published commits, or `--no-verify`.
|
|
130
134
|
- Aborts on merge conflicts or rebase-in-progress.
|
|
131
|
-
-
|
|
135
|
+
- Warns before creating the first tag or GitHub release in a public/internal repository.
|
|
132
136
|
- Skips push / tag / release gracefully when the repo has no remote or `gh` is not installed.
|
|
133
137
|
|
|
134
138
|
Distribution note:
|
|
135
|
-
-
|
|
139
|
+
- The release workflow now ships through both installation options as one Agent Skill. The former Claude-only `commands/release.md` is removed automatically on the next `aiskills update` or `aiskills install`.
|
|
140
|
+
- If npm updates before an enabled Claude marketplace cache, the CLI keeps the old plugin command as the temporary `/release` provider and suppresses the new same-name mirror rather than creating a duplicate. Refresh with `/plugin marketplace update maccesar-aiskills`, run `aiskills install`, then `/reload-plugins` to finish the handoff to the skill.
|
|
136
141
|
|
|
137
142
|
## How skills work
|
|
138
143
|
|
|
139
|
-
|
|
144
|
+
Most skills activate based on what you ask. You can write prompts normally:
|
|
140
145
|
|
|
141
146
|
```
|
|
142
147
|
"How do I create better visual hierarchy in this UI?"
|
|
@@ -146,7 +151,7 @@ Skills activate based on what you ask. You can write prompts normally:
|
|
|
146
151
|
|
|
147
152
|
The assistant reads the skill's `SKILL.md`, checks whether the request fits, and then loads the reference files for that skill. That keeps the answer tied to the source material.
|
|
148
153
|
|
|
149
|
-
You do not need to name a skill explicitly
|
|
154
|
+
You do not normally need to name a skill explicitly. `release` is the deliberate exception because it can commit, tag, push, and publish; invoke it using the platform-specific form documented above.
|
|
150
155
|
|
|
151
156
|
---
|
|
152
157
|
|
package/lib/commands/doctor.js
CHANGED
|
@@ -75,7 +75,9 @@ export async function doctorCommand() {
|
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
const expectedCommands = COMMANDS.length - pluginCommands.length;
|
|
78
|
-
if (
|
|
78
|
+
if (COMMANDS.length === 0) {
|
|
79
|
+
console.log(` ${CHECK} Slash commands: none (workflows ship as cross-agent skills)`);
|
|
80
|
+
} else if (pluginCommands.length === COMMANDS.length) {
|
|
79
81
|
console.log(` ${CHECK} Slash commands: all ${COMMANDS.length} served by the marketplace plugin`);
|
|
80
82
|
} else if (missingCommands.length === 0) {
|
|
81
83
|
console.log(` ${CHECK} Slash commands: ${expectedCommands}/${expectedCommands} installed in ~/.claude/commands/`);
|
|
@@ -113,10 +115,13 @@ export async function doctorCommand() {
|
|
|
113
115
|
|
|
114
116
|
for (const skill of SKILLS) {
|
|
115
117
|
// A skill the marketplace plugin provides is *supposed* to have no mirror
|
|
116
|
-
// here — the CLI removes it on purpose to avoid a duplicate entry.
|
|
117
|
-
//
|
|
118
|
-
//
|
|
119
|
-
if (
|
|
118
|
+
// here — the CLI removes it on purpose to avoid a duplicate entry. During
|
|
119
|
+
// command-to-skill migrations, a same-name command in an older enabled
|
|
120
|
+
// cache also suppresses the mirror until the marketplace refreshes.
|
|
121
|
+
if (
|
|
122
|
+
platform.name === 'claude' &&
|
|
123
|
+
(pluginProvidesSkill(skill, homeDir) || pluginProvidesCommand(skill, homeDir))
|
|
124
|
+
) {
|
|
120
125
|
servedByPlugin.push(skill);
|
|
121
126
|
continue;
|
|
122
127
|
}
|
package/lib/config.js
CHANGED
|
@@ -31,6 +31,7 @@ export const SKILLS = [
|
|
|
31
31
|
'humaniza',
|
|
32
32
|
'npm-supply-chain',
|
|
33
33
|
'refactoring-ui',
|
|
34
|
+
'release',
|
|
34
35
|
'seo-launch',
|
|
35
36
|
'session-log',
|
|
36
37
|
'stitch-showcase',
|
|
@@ -41,12 +42,10 @@ export const SKILLS = [
|
|
|
41
42
|
export const LEGACY_SKILLS = [];
|
|
42
43
|
|
|
43
44
|
// Slash commands to install (Claude Code only — copied to ~/.claude/commands/)
|
|
44
|
-
export const COMMANDS = [
|
|
45
|
-
'release',
|
|
46
|
-
];
|
|
45
|
+
export const COMMANDS = [];
|
|
47
46
|
|
|
48
47
|
// Legacy commands to remove during updates/uninstall
|
|
49
|
-
export const LEGACY_COMMANDS = [];
|
|
48
|
+
export const LEGACY_COMMANDS = ['release'];
|
|
50
49
|
|
|
51
50
|
// Cache/config directory
|
|
52
51
|
export const getConfigDir = () => path.join(os.homedir(), '.aiskills');
|
package/lib/symlink.js
CHANGED
|
@@ -83,8 +83,8 @@ async function removePath(path) {
|
|
|
83
83
|
* @returns {Promise<boolean>} True if the plugin provides this skill
|
|
84
84
|
*/
|
|
85
85
|
export async function isClaudePluginSkillInstalled(skillName, baseDir) {
|
|
86
|
-
const { pluginProvidesSkill } = await import('./claude-plugin.js');
|
|
87
|
-
return pluginProvidesSkill(skillName, baseDir);
|
|
86
|
+
const { pluginProvidesSkill, pluginProvidesCommand } = await import('./claude-plugin.js');
|
|
87
|
+
return pluginProvidesSkill(skillName, baseDir) || pluginProvidesCommand(skillName, baseDir);
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
/**
|
|
@@ -118,8 +118,9 @@ export async function createSkillSymlinks(platformSkillsDir, skills, baseDir) {
|
|
|
118
118
|
const useRelative = !!baseDir;
|
|
119
119
|
|
|
120
120
|
for (const skill of skills) {
|
|
121
|
-
// Skip Claude when the marketplace plugin already provides this skill
|
|
122
|
-
//
|
|
121
|
+
// Skip Claude when the marketplace plugin already provides this skill or
|
|
122
|
+
// still provides a same-name legacy command during a command-to-skill
|
|
123
|
+
// migration; clean up any stale symlink left from a previous CLI install.
|
|
123
124
|
if (isClaudePlatform && await isClaudePluginSkillInstalled(skill, baseDir)) {
|
|
124
125
|
const stalePath = join(platformSkillsDir, skill);
|
|
125
126
|
if (existsSync(stalePath)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@maccesar/aiskills",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.22.0",
|
|
4
4
|
"description": "AI coding assistant skills for Claude Code, Gemini CLI, and Codex CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"codex",
|
|
21
21
|
"llm",
|
|
22
22
|
"agents",
|
|
23
|
+
"release",
|
|
23
24
|
"refactoring-ui",
|
|
24
25
|
"design",
|
|
25
26
|
"ui",
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: release
|
|
3
|
+
description: 'Use only when the user explicitly invokes `$release`, `/release`, or asks to use the release skill by name. Never activate merely because work appears ready or the user discusses releases. Handles the full repository release workflow: semantic commits, semver, CHANGELOG and README updates, confirmation, push, tag, GitHub release, and publication verification.'
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Release
|
|
7
|
+
|
|
8
|
+
Publish a repository only through an explicit, reviewable authorization sequence.
|
|
9
|
+
|
|
10
|
+
## Invocation boundary
|
|
11
|
+
|
|
12
|
+
This is an explicit-only skill.
|
|
13
|
+
|
|
14
|
+
- Proceed only when the user's current request names `$release`, `/release`, or the `release` skill itself.
|
|
15
|
+
- A generic request that merely discusses releases, versions, tags, publishing, or a repository that looks ready is not an invocation. Stop and tell the user how to invoke the skill.
|
|
16
|
+
- Invoking the skill authorizes read-only analysis and a release plan. It does not authorize commits, tags, pushes, package publication, GitHub releases, merges, or pull requests.
|
|
17
|
+
- Accept an optional `patch`, `minor`, or `major` override from the invocation. Otherwise infer the bump from the repository changes.
|
|
18
|
+
|
|
19
|
+
## Required workflow
|
|
20
|
+
|
|
21
|
+
1. Read [references/workflow.md](references/workflow.md) completely before running repository checks.
|
|
22
|
+
2. Follow its Steps 0–4 in order and present the single confirmation block.
|
|
23
|
+
3. Stop. Do not perform any mutation until the user explicitly confirms that exact plan.
|
|
24
|
+
4. After confirmation, follow Step 5 exactly and verify every publication channel triggered by the release.
|
|
25
|
+
|
|
26
|
+
Repository instructions remain authoritative. If they impose stricter release checks or extra synchronized version files, include those requirements in the plan and execution.
|
|
@@ -1,39 +1,46 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
1
|
+
# Release workflow
|
|
2
|
+
|
|
3
|
+
<!-- TOC-START -->
|
|
4
|
+
## Contents
|
|
5
|
+
|
|
6
|
+
- [Read-only context to collect](#read-only-context-to-collect)
|
|
7
|
+
- [Your task](#your-task)
|
|
8
|
+
- [What this skill actually does (read this first)](#what-this-skill-actually-does-read-this-first)
|
|
9
|
+
- [Verbosity discipline](#verbosity-discipline)
|
|
10
|
+
- [Step 0 — Lock interaction language (do this BEFORE printing anything)](#step-0--lock-interaction-language-do-this-before-printing-anything)
|
|
11
|
+
- [Step 1 — Establish state (silent)](#step-1--establish-state-silent)
|
|
12
|
+
- [Step 2 — Infer the bump (silent)](#step-2--infer-the-bump-silent)
|
|
13
|
+
- [Step 3 — Compose the CHANGELOG entry (silent)](#step-3--compose-the-changelog-entry-silent)
|
|
14
|
+
- [Language policy (applies to Steps 1–5)](#language-policy-applies-to-steps-15)
|
|
15
|
+
- [Step 4 — Present the plan in ONE block and STOP](#step-4--present-the-plan-in-one-block-and-stop)
|
|
16
|
+
- [Step 5 — Execute (silent until done)](#step-5--execute-silent-until-done)
|
|
17
|
+
- [Hard restrictions (never violate)](#hard-restrictions-never-violate)
|
|
18
|
+
|
|
19
|
+
<!-- TOC-END -->
|
|
20
|
+
|
|
21
|
+
## Read-only context to collect
|
|
22
|
+
|
|
23
|
+
Collect this state with read-only tools before planning anything:
|
|
24
|
+
|
|
25
|
+
- Working tree status: `git status --porcelain`
|
|
26
|
+
- Current branch: `git branch --show-current`
|
|
27
|
+
- Last tag: `git describe --tags --abbrev=0`
|
|
28
|
+
- Commits since the last tag, or the full log when no tag exists
|
|
29
|
+
- Remote URL and primary branch
|
|
30
|
+
- Recent commit subjects and conventions
|
|
31
|
+
- Whether `gh` is installed and, for GitHub remotes, repository visibility
|
|
32
|
+
- Presence of `package.json`, `tiapp.xml`, `composer.json`, `Cargo.toml`, a root `*.podspec`, `CHANGELOG.md`, and `README.md`
|
|
33
|
+
- Merge or rebase state and unresolved conflicts
|
|
34
|
+
|
|
35
|
+
The explicit invocation may include `patch`, `minor`, or `major` to override the inferred bump. If none is present, infer it from the work being released.
|
|
29
36
|
|
|
30
37
|
## Your task
|
|
31
38
|
|
|
32
39
|
Execute the **release workflow** in five strict, ordered steps. **Do not skip Step 4** — it is the user's confirmation gate and is non-negotiable.
|
|
33
40
|
|
|
34
|
-
### What this
|
|
41
|
+
### What this skill actually does (read this first)
|
|
35
42
|
|
|
36
|
-
|
|
43
|
+
The release skill is **not** "make a release commit from already-staged work". It is the full janitor: it takes a project that has been worked on without commits (or with mixed work + a release intent) and turns it into a clean, shipped release.
|
|
37
44
|
|
|
38
45
|
**Working tree dirty is the expected starting state, not an anomaly.** When the user invokes `/release` with 12 modified files since the last tag, what they want is:
|
|
39
46
|
|
|
@@ -55,9 +62,9 @@ If the working tree is **completely empty** AND there are zero commits since the
|
|
|
55
62
|
|
|
56
63
|
### Step 0 — Lock interaction language (do this BEFORE printing anything)
|
|
57
64
|
|
|
58
|
-
Before you produce any user-facing output, scan the user's last 1–3 messages in this conversation and determine their language. **This file is in English for distribution; that does not mean you respond in English.** Lock that detected language and use it for
|
|
65
|
+
Before you produce any user-facing output, scan the user's last 1–3 messages in this conversation and determine their language. **This file is in English for distribution; that does not mean you respond in English.** Lock that detected language and use it for every message you print to the user until the skill ends: the Step 4 plan, errors, and final report.
|
|
59
66
|
|
|
60
|
-
If the user has not yet said anything in this session (rare
|
|
67
|
+
If the user has not yet said anything in this session (rare when the skill is invoked as the first message), default to the language of the repo's `README.md`. If that is also unclear, default to English.
|
|
61
68
|
|
|
62
69
|
If the user switches language mid-flow, switch with them on the next message.
|
|
63
70
|
|
|
@@ -168,7 +175,7 @@ Apply Conventional Commits rules across that combined set:
|
|
|
168
175
|
- Any `feat:` (no breaking) → **minor**
|
|
169
176
|
- Otherwise → **patch**
|
|
170
177
|
|
|
171
|
-
|
|
178
|
+
An explicit invocation override (`patch` / `minor` / `major`) takes precedence over the inference.
|
|
172
179
|
|
|
173
180
|
If there are zero existing commits AND zero proposed commits AND the working tree is clean → abort: "Nothing to release."
|
|
174
181
|
|
|
@@ -208,7 +215,7 @@ There are **two independent language axes**. Do not mix them.
|
|
|
208
215
|
|
|
209
216
|
#### Axis 1 — Interaction language (your conversation with the user)
|
|
210
217
|
|
|
211
|
-
**Always match the user's language.** Detect from the user's last 1–3 messages in this conversation — not from this
|
|
218
|
+
**Always match the user's language.** Detect from the user's last 1–3 messages in this conversation — not from this workflow file (which is in English for distribution), and not from the project files. If the user has been speaking Spanish, every plan preview, confirmation prompt, error message, and final report you print **must be in Spanish**. If the user switches mid-flow, switch with them.
|
|
212
219
|
|
|
213
220
|
This is about what the user **reads on screen**. It does **not** affect what gets written to disk or to GitHub.
|
|
214
221
|
|
|
@@ -222,7 +229,7 @@ This is about what the user **reads on screen**. It does **not** affect what get
|
|
|
222
229
|
2. Classify the prose: Spanish, English, or other.
|
|
223
230
|
3. Tie-break with `CHANGELOG.md` (recent entries) if README is too short or ambiguous.
|
|
224
231
|
4. Final tie-break: the recent `git log` subjects.
|
|
225
|
-
5. If everything is ambiguous, default to English and
|
|
232
|
+
5. If everything is ambiguous, default to English and surface that assumption in the Step 4 block so the user can correct it before confirming.
|
|
226
233
|
|
|
227
234
|
The detected language applies to **all** of the following:
|
|
228
235
|
|
|
@@ -284,7 +291,7 @@ CHANGELOG entry:
|
|
|
284
291
|
### Fixed
|
|
285
292
|
- ...
|
|
286
293
|
|
|
287
|
-
README updates (gaps found): <one-line per gap, e.g. "add
|
|
294
|
+
README updates (gaps found): <one-line per gap, e.g. "add the new public skill to the available-skills table"> ← omit this line if no gaps
|
|
288
295
|
Release commit: bumps <version-file> A.B.C→X.Y.Z (+ <secondary version file> to the same number), inserts CHANGELOG section, applies README updates. Subject: `<exact line>`.
|
|
289
296
|
Push: release commit to <branch>.
|
|
290
297
|
Publishing: pushing the tag triggers `<workflow>.yml`, which publishes to <registry>. ← include ONLY when Step 1.9 found a tag-triggered publishing workflow; localize to user's language
|
|
@@ -427,9 +434,9 @@ If everything was routine and no merge was requested, the second line is just th
|
|
|
427
434
|
- **Never** `--no-verify`, `--no-gpg-sign`, or any hook-skipping flag unless the user explicitly asks.
|
|
428
435
|
- **Never** delete tags or branches.
|
|
429
436
|
- **Never** merge to main with anything other than `--ff-only`. If fast-forward is not possible, abort and let the user resolve. Do not fall back to `--no-ff`, `-X theirs`, `-X ours`, or any rebase strategy.
|
|
430
|
-
- **Never** proceed past Step 4 without explicit confirmation.
|
|
437
|
+
- **Never** proceed past Step 4 without explicit confirmation. Explicitly invoking the skill is consent to **plan**, not consent to commit and push.
|
|
431
438
|
- If the working tree has merge conflicts or rebase-in-progress markers → **abort** with a diagnosis and let the user resolve manually.
|
|
432
439
|
- If the repo is **public/internal** and has **no prior tag** and/or **no prior GitHub release**, surface a ⚠️ line in the Step 4 plan (one per missing milestone) before creating the first ever tag or release — these are meaningful one-way actions. The user's plain confirmation in Step 4 (`yes` / `sí` / `proceed` / …) covers both ⚠️s in that single round-trip; do not require a separate confirmation prompt. On a **private repo** these confirmations are unnecessary and must NOT be raised — private mode skips both the tag and the GitHub release by default, so there's nothing to confirm. The user already opted in/out via the `con tag` modifier in Step 4 (and even then, the GitHub release stays skipped on private repos).
|
|
433
|
-
- If the repo has no remote →
|
|
434
|
-
- If the repo has a remote but `gh` is not available →
|
|
440
|
+
- If the repo has no remote → land the semantic and release commits only; skip push, tag, and GitHub release. Tell the user.
|
|
441
|
+
- If the repo has a remote but `gh` is not available → push the branch and tag, but skip the GitHub release; tell the user how to create it manually if they want to.
|
|
435
442
|
- **Never** create a GitHub release on a private repo, even if the user added `con tag` to the confirmation. The `con tag` modifier only re-enables the git tag; the GitHub release stays skipped.
|