ワンクリックで
release
Use when the user says "release", "tag a release", "cut a release", "bump version", "ship it", "publish", or "/release". Handles version bumping, changelog generation, validation, tagging, and GitHub release creation.
メニュー
Use when the user says "release", "tag a release", "cut a release", "bump version", "ship it", "publish", or "/release". Handles version bumping, changelog generation, validation, tagging, and GitHub release creation.
Use when the user says "delegate", "assign bot work", "dispatch issues", "triage open issues", "send to bot", or explicitly "/delegate". Scans open GitHub issues, classifies which are bot-delegatable, enriches them with design direction and context, and assigns via @claude comments. Analyzes prior bot failures and decomposes large issues.
Use when the user says "crystallize", "compact", "compile", "distill", or asks to reduce a skill's reliance on LLM prose reasoning. Phase-transitions deterministic operations out of skill docs into real scripts with real test data. Rewrites the SKILL.md to be shorter and call the scripts instead of describing the logic. Aggressive about the boundary: LLM does judgment, prose, ambiguity resolution. Scripts do math, time comparison, parsing, counting, aggregation, schema validation.
This skill should be used when the user asks to "test on device", "test on emulator", "run emulator", "launch AVD", "test PWA", "test on Android", "test on mobile", "verify on real device", "check on phone", or discusses testing a feature on an actual device or emulator rather than headless Playwright. Also use when validating features that headless browsers cannot cover (biometric, PWA install, Chrome autofill, touch gestures, password managers). Use proactively when a feature has been implemented that touches any of these capabilities.
Protocol for capturing a complete development arc (TRACE). Includes telemetry, strategy pivots, logs, and performance metadata. Use this to record the "how and why" of an objective, especially for performance-critical or non-deterministic tasks.
Use when the user says "cycle", "pump", "sdlc", "next cycle", or "/cycle". Runs one full SDLC cycle — discover, prioritize, cluster, delegate, develop, gate — filtered by theme.
Use when the user says "develop", "work on issue", "implement issue", "fix issue N", or explicitly "/develop N". Spawns a local develop agent in a worktree to implement one or more GitHub issues. Supports batch mode ("/develop 3,9,16") with max 4 parallel agents. Without arguments, auto-proposes bot-labeled issues ranked by risk and relevance.
| name | release |
| description | Use when the user says "release", "tag a release", "cut a release", "bump version", "ship it", "publish", or "/release". Handles version bumping, changelog generation, validation, tagging, and GitHub release creation. |
Process reference:
.claude/process.mddefines the label taxonomy, workflow states, and conventions that this skill must follow.
Automated release process for MobiSSH. Handles version bumping across all touchpoints, changelog generation from git history, full validation, and tagging.
Every release must update ALL of these in sync:
| File | Field | Example |
|---|---|---|
server/package.json | "version" | "0.3.0" |
The server reads version from server/package.json at startup and injects it as <meta name="app-version" content="{version}:{git-hash}">.
public/sw.js CACHE_NAME is automatically derived from a content hash of public/ files by container-ctl.sh at build time. No manual bump needed — it changes only when actual file content changes.
Root package.json has no version field (private workspace). Don't add one.
# Latest tag and commits since
git describe --tags --abbrev=0
git log $(git describe --tags --abbrev=0)..HEAD --oneline | wc -l
git log $(git describe --tags --abbrev=0)..HEAD --oneline
Version bump rules (semver):
For MobiSSH's current maturity (pre-1.0), minor bumps are the norm. 85 commits with features = minor.
Group commits since last tag by category. Parse commit prefixes:
| Prefix | Category |
|---|---|
feat:, feat( | Features |
fix:, fix( | Bug Fixes |
refactor: | Refactoring |
test: | Testing |
chore:, build:, docs: | Maintenance |
security: | Security |
Merge pull request | Skip (noise) |
Format as a concise changelog section. Include issue numbers where present. Don't list every commit -- group related work (e.g., "TypeScript migration Phases 0-5" not 10 separate phase commits).
Run the full CI gate before tagging. ALL must pass:
scripts/test-fast-gate.sh # TypeScript + ESLint + Vitest
scripts/test-headless.sh # Headless Playwright E2E
If an emulator is available (adb devices | grep emulator), also run:
scripts/run-emulator-tests.sh
scripts/run-appium-tests.sh # Appium gesture baseline
Do NOT tag if any validation fails. Fix first, commit, then re-run.
Static security analysis using the AI tools installed on this container. Review
.claude/rules/security.md for the project's security posture, then run each tool
with a security-focused prompt against the codebase.
VERSION="{VERSION}" # from Step 1
SECURITY_DIR="test-history/security/v${VERSION}"
mkdir -p "$SECURITY_DIR"
Before running the tools, assemble a context file with the project documentation so the auditors understand what MobiSSH is, its architecture, trust boundaries, and security policy. Without this they hallucinate about the attack surface.
CONTEXT_FILE="$SECURITY_DIR/audit-context.md"
cat > "$CONTEXT_FILE" << 'CONTEXT_EOF'
# MobiSSH — Security Audit Context
CONTEXT_EOF
# Append project docs that define intent, architecture, and security posture
cat CLAUDE.md >> "$CONTEXT_FILE"
echo -e "\n---\n" >> "$CONTEXT_FILE"
cat .claude/rules/security.md >> "$CONTEXT_FILE"
echo -e "\n---\n" >> "$CONTEXT_FILE"
cat .claude/rules/server.md >> "$CONTEXT_FILE"
The prompts include the assembled context so the tools understand:
The audit concerns from security.md: plaintext credential storage, vault bypass
paths, cache policy violations, secret leakage, XSS/injection in the WebSocket
bridge, and SSRF via the SSH proxy.
Gemini (headless, non-interactive):
gemini -p "$(cat "$CONTEXT_FILE")
---
You are a security auditor. The project documentation above describes what MobiSSH
is, how it's deployed, and its security policy. Use this to understand the real
attack surface — don't guess.
Key trust boundaries:
- Tailscale mesh provides network-layer auth (no public internet exposure)
- WebSocket bridge proxies SSH — the bridge itself has no auth beyond Tailscale
- AES-GCM vault stores credentials client-side with biometric unlock
- Service worker caches for offline only (network-first, no-store headers)
Audit for security issues, ranked by severity (critical/high/medium/low):
1. Credential handling: plaintext storage, vault bypass, key material in localStorage/logs
2. WebSocket bridge: command injection, SSRF via SSH host/port params, auth bypass
3. Service worker: cache poisoning, stale credential serving, scope escalation
4. XSS vectors: user input rendered without sanitization (terminal output, profile names)
5. Dependencies: known CVEs in server/package.json deps
6. Docker/deployment: container escape paths, exposed ports, secret leakage in build args
For each finding: severity, file:line, description, recommended fix.
Skip theoretical issues that don't apply given the Tailscale-only deployment.
Output as markdown." > "$SECURITY_DIR/gemini-audit.md" 2>&1
Codex (non-interactive exec mode):
codex exec "$(cat "$CONTEXT_FILE")
---
You are a security auditor. The project documentation above describes MobiSSH's
architecture, deployment model, and security policy. Read it carefully before auditing.
Key facts:
- Deployed on Tailscale mesh only — not public internet
- Single Node.js process: static files + WebSocket SSH bridge on port 8081
- AES-GCM vault with PasswordCredential for credential storage
- Cache-Control: no-store on all static responses, SW is network-first
- Docker container with baked git hash, Tailscale serve for HTTPS termination
Review this codebase for:
1. Plaintext credential storage or vault bypass paths (policy: block feature if vault unavailable)
2. WebSocket/SSH proxy injection or SSRF (user-supplied host/port forwarded to ssh2)
3. Cache-Control violations (must be no-store on ALL static responses)
4. XSS in terminal output, profile names, or user input handling
5. Secret leakage in logs, error messages, console output, or git history
6. Dependency vulnerabilities in server/package.json
Report findings as: severity | file:line | description | fix.
Only report findings that are real given the architecture. No theoretical noise.
Output as markdown." > "$SECURITY_DIR/codex-audit.md" 2>&1
Read both reports:
$SECURITY_DIR/gemini-audit.md
$SECURITY_DIR/codex-audit.md
For each finding:
.claude/process.md:
bug + security, file immediatelybug + security, file with contextchore + security, batch into one issue or skip if noisescripts/gh-file-issue.sh for each real finding. Title format:
security: {brief description}. Body should include the tool's analysis, the
verified file:line, and the recommended fix.Stage the audit results:
git add "$SECURITY_DIR/"
These get included in the release commit (Step 5) as permanent evidence of the security review for this version.
gemini nor codex is available, log a warning and skip. Do NOT
block the release for missing tools.Update all touchpoints:
server/package.json: Update "version" fieldpublic/sw.js CACHE_NAME is auto-derived by container-ctl.sh at build time (content hash of public/ files). No manual bump needed.
git add server/package.json test-history/
git commit -m "release: v{VERSION}"
git tag -a "v{VERSION}" -m "{CHANGELOG_SUMMARY}"
The tag message should contain the full changelog section (not just the version number). This is the primary record of what changed.
Move timestamped test-history runs into a versioned directory for the release. This creates a permanent record of test evidence (video recordings with gesture debug overlays, screenshots, HTML reports) tied to each version.
# Create versioned archive directory
mkdir -p test-history/appium/v{VERSION}
# Move all timestamped runs since last release into versioned dir
# (each run-appium-tests.sh invocation creates test-history/appium/YYYYMMDD-HHMMSS/)
for dir in test-history/appium/20*; do
[ -d "$dir" ] && mv "$dir" "test-history/appium/v{VERSION}/$(basename "$dir")"
done
# Stage and include in the release commit
git add test-history/
Video files (.webm, .mp4) are stored in Git LFS (.gitattributes has filter=lfs diff=lfs merge=lfs -text). Screenshot PNGs use binary -diff. Videos are the primary evidence that gestures work correctly at each release point. If new video files were committed before the LFS rules existed, run git lfs migrate import --include="test-history/**/*.webm,test-history/**/*.mp4" to convert them to LFS pointers before pushing.
If no test-history runs exist (e.g., no emulator was available), skip this step. Don't fail the release for missing test evidence.
Scan the changelog commits for issue references (#N, fix(#N), feat(#N)). For each referenced issue that is still open:
.claude/process.md:scripts/gh-ops.sh close N --comment "Fixed in v{VERSION} ({COMMIT_SHA})"
scripts/gh-ops.sh labels N --rm bot --rm divergence
scripts/gh-ops.sh labels N --add "v{VERSION}"
If there's no label for this version yet, create one:
scripts/gh-ops.sh labels 0 --add "v{VERSION}" # create label via gh-ops
# If label doesn't exist yet, create it manually (no gh-ops subcommand for label creation):
gh label create "v{VERSION}" --description "Released in v{VERSION}" --color "0E8A16"
Don't close issues that are only partially addressed. If a commit references an issue but only fixes part of it, leave the issue open and add a comment noting partial progress.
Create a GitHub release with the changelog. Note: gh release create has no gh-ops.sh
wrapper yet — this is an acceptable exception for a rare, manual operation:
gh release create "v{VERSION}" --title "v{VERSION}" --notes "{CHANGELOG}"
Ask the user before pushing. Show what will be pushed:
git log origin/main..HEAD --oneline
git tag -l --sort=-version:refname | head -3
Then push:
git push origin main --follow-tags
After push, rebuild the production container and verify:
scripts/container-ctl.sh restart
scripts/container-ctl.sh status
Check that the version meta tag matches the new release.
Create a TRACE for every release:
scripts/trace-init.sh "release-v{VERSION}"
Record in strategy/initial_plan.md:
Log pivots when:
Populate TRACE.md on completion with:
Release TRACEs are always created (not optional) since they document the decision trail for what went into production.