Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
fandhe-ai avatar

Contribute Skill

  • 202 installs
  • 1 repo stars
  • Updated August 2, 2026
  • fandhe-ai/agent-cli-skills

Helps with ai & agent building tasks.

About

contribute-skill is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.

  • contribute-skill
  • AI & Agent Building
  • AI-coding skill

Contribute Skill by the numbers

  • 202 all-time installs (skills.sh)
  • Ranked #2,878 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
  • Data as of Aug 3, 2026 (Skillselion catalog sync)
npx skills add https://github.com/fandhe-ai/agent-cli-skills --skill contribute-skill

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs202
repo stars1
Last updatedAugust 2, 2026
Repositoryfandhe-ai/agent-cli-skills

What it does

Helps with ai & agent building tasks.

Files

SKILL.mdMarkdownGitHub ↗

contribute-skill

ローカルで改修した skills/<skill-name>/ を、skills-lock.json に記録された upstream リポジトリへ PR として投稿します。

前提条件

  • gh CLI がインストールされ認証済みであること(対象 org への push / PR 権限が必要)
  • 対象スキルが skills-lock.json に登録されていること
  • 対象スキルのローカル改修が最新のコミットに含まれ、作業ツリーが clean であること

責務の分離

  • create-pr: 現在のリポジトリ内でカレントブランチから base へ PR を作成する
  • contribute-skill: 別リポジトリ(upstream)へ clone → 変更反映 → push → PR 作成を行う

外部リポジトリ貢献は clone / path 変換 / 異なる認証境界が関わるため、別スキルとして分離しています。

フロー

Step 1: 引数を検証する

SKILL_NAME="$ARGUMENTS"

# 空判定ガード: パス解決の前に SKILL_NAME を確定させる
if [[ -z "${SKILL_NAME}" ]]; then
  echo "対象スキルを指定してください。候補:"
  ls -1 skills/ 2>/dev/null
  ls -1 .agents/skills/ 2>/dev/null
  echo "(lockfile 由来のスキルは .agents/skills/ のみに存在する場合がある)"
  exit 1   # ユーザーが選んだスキル名を引数に付けて再実行する
fi

# kebab-case 検証(パストラバーサル防止): パス解決より前に実施する
if [[ ! "${SKILL_NAME}" =~ ^[a-z][a-z0-9-]+$ ]]; then
  echo "エラー: SKILL_NAME は小文字 kebab-case のみ許可されています: ${SKILL_NAME}"
  exit 1
fi

# override: 環境変数 LOCAL_SKILL_DIR が設定済みならそれを検証して使う
if [[ -n "${LOCAL_SKILL_DIR:-}" ]]; then
  if [[ "${LOCAL_SKILL_DIR}" != "skills/${SKILL_NAME}" && "${LOCAL_SKILL_DIR}" != ".agents/skills/${SKILL_NAME}" ]]; then
    echo "エラー: LOCAL_SKILL_DIR は skills/${SKILL_NAME} か .agents/skills/${SKILL_NAME} のいずれかを指定してください: ${LOCAL_SKILL_DIR}"
    exit 1
  fi
  if [[ ! -d "${LOCAL_SKILL_DIR}" ]]; then
    echo "エラー: 指定された LOCAL_SKILL_DIR が存在しません: ${LOCAL_SKILL_DIR}"
    exit 1
  fi
else
  # 自動解決(両方存在する場合は中止して override を促す)
  have_skills=0; have_agents=0
  [[ -d "skills/${SKILL_NAME}" ]] && have_skills=1
  [[ -d ".agents/skills/${SKILL_NAME}" ]] && have_agents=1
  if [[ "${have_skills}" -eq 1 && "${have_agents}" -eq 1 ]]; then
    echo "エラー: skills/${SKILL_NAME} と .agents/skills/${SKILL_NAME} の両方が存在します。"
    echo "環境変数 LOCAL_SKILL_DIR にどちらかを指定して再実行してください(例: LOCAL_SKILL_DIR=.agents/skills/${SKILL_NAME})。"
    exit 1
  elif [[ "${have_skills}" -eq 1 ]]; then
    LOCAL_SKILL_DIR="skills/${SKILL_NAME}"
  elif [[ "${have_agents}" -eq 1 ]]; then
    LOCAL_SKILL_DIR=".agents/skills/${SKILL_NAME}"
  else
    echo "エラー: ローカルスキルが見つかりません: skills/${SKILL_NAME} / .agents/skills/${SKILL_NAME}"
    exit 1
  fi
fi

引数が空の場合はパス解決に進まず、skills/.agents/skills/ の候補一覧を表示して終了します。Claude はその一覧をユーザーに提示し、スキル名を選んでもらってから再実行を促してください。後続の Step では ${LOCAL_SKILL_DIR}/ を使ってローカルパスを参照します。 skills/.agents/skills/両方にディレクトリが存在する場合は中止し、環境変数 LOCAL_SKILL_DIR に改修対象のパス(skills/<name>.agents/skills/<name> のいずれか)を指定して再実行するよう案内します(silently に skills/ を優先しません)。環境変数 LOCAL_SKILL_DIR が設定済みの場合は、許可された2パスのいずれかであること・実在することを検証してから採用し、自動解決をスキップします。どちらにも存在しなければエラーで中止します。

Step 2: upstream を特定する

ルートの skills-lock.json を読み、skills.<SKILL_NAME>.source を取り出します。

# jq が使えるなら jq で取得する
SOURCE=$(jq -r ".skills[\"${SKILL_NAME}\"].source" skills-lock.json)
SOURCE_TYPE=$(jq -r ".skills[\"${SKILL_NAME}\"].sourceType" skills-lock.json)

# 安全弁: Fandhe-AI org 以外への push を拒否する
# 短縮形 (Fandhe-AI/<repo>) と URL 形式 (https://github.com/Fandhe-AI/<repo>) の両方を許可する
case "${SOURCE}" in
  Fandhe-AI/*)
    # 短縮形: そのまま使用
    REPO_SLUG="${SOURCE}"
    ;;
  https://github.com/Fandhe-AI/*)
    # URL 形式: OWNER/REPO 形式に正規化し末尾 .git を除去する
    REPO_SLUG="${SOURCE#https://github.com/}"
    REPO_SLUG="${REPO_SLUG%.git}"
    ;;
  *)
    echo "エラー: source '${SOURCE}' は Fandhe-AI org のリポジトリではありません。中止します。"
    exit 1
    ;;
esac

# sourceType が github 以外なら中止(GitHub 以外の source は本スキルの想定外)
if [[ "${SOURCE_TYPE}" != "github" ]]; then
  echo "エラー: sourceType '${SOURCE_TYPE}' は github ではありません。中止します。"
  exit 1
fi
  • sourceFandhe-AI/(短縮形)または https://github.com/Fandhe-AI/(URL 形式)のいずれでも始まらない場合は エラーで中止 します(安全弁:見知らぬリポジトリへ意図せず push しないため)。
  • sourceTypegithub 以外の場合も エラーで中止 します(GitHub 以外の source は本スキルの想定外であり、gh repo clone / gh pr create が正常動作しないため)。
  • 正規化後の REPO_SLUG は以降の Step で gh repo clonegh pr create --repo に利用します。

Step 3: 変更内容を確認する

git log --oneline -- "${LOCAL_SKILL_DIR}/"
git diff HEAD~1 HEAD -- "${LOCAL_SKILL_DIR}/"

ユーザーに「この改修内容で upstream に PR を作ってよいか」を確認します。

Step 4: セキュリティチェック(必須)

create-pr と同様に以下をレビューします。

  • 認証・認可の実装漏れ
  • API キー・シークレットのハードコーディング
  • XSS の可能性(ドキュメントでも外部埋め込みが含まれる場合)
  • 入力バリデーションの欠如
  • OWASP Top 10

問題があれば upstream 貢献を中止し、ユーザーに警告します。

Step 5: 作業用ディレクトリを用意する

UID_VAL=$(id -u)
TS=$(date +%Y%m%d-%H%M%S)
WORKDIR="/tmp/claude-${UID_VAL}/contribute-${SKILL_NAME}-${TS}"
mkdir -p "$WORKDIR"

$TMPDIR が設定されていればそちらを優先します(サンドボックス互換)。

Step 6: upstream を clone する

# cd する前にローカルリポジトリのルートを捕捉する(cd - は stdout を汚染するため使用しない)
ORIG_DIR="$(pwd)"
gh repo clone "${REPO_SLUG}" "$WORKDIR/upstream"
cd "$WORKDIR/upstream"

デフォルトブランチを取得して DEFAULT_BRANCH に設定します。

DEFAULT_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's|refs/remotes/origin/||')
echo "デフォルトブランチ: ${DEFAULT_BRANCH:-main}"

Step 7: 変更を反映する

upstream 側でスキルがどのパス構造に置かれているか確認します。UPSTREAM_SKILL_PATH の決定は、クローンしたリポジトリのレイアウトのみで判定します(cd "$WORKDIR/upstream" 済みの前提)。

skills-lock.jsonskillPath はローカル install パスであり upstream リポジトリ内の配置ではないため、使用しません。

# upstream のスキル配置はクローンしたリポジトリのレイアウトで判定する
# (skills-lock.json の skillPath はローカル install パスであり upstream の配置ではないため使わない)
if [[ -d "skills/${SKILL_NAME}" ]]; then
  UPSTREAM_SKILL_PATH="skills/${SKILL_NAME}"
elif [[ -d ".agents/skills/${SKILL_NAME}" ]]; then
  UPSTREAM_SKILL_PATH=".agents/skills/${SKILL_NAME}"
elif [[ -d "skills" ]]; then
  # upstream が skills/ 配下で公開している慣習
  UPSTREAM_SKILL_PATH="skills/${SKILL_NAME}"
  mkdir -p "${WORKDIR}/upstream/${UPSTREAM_SKILL_PATH}"
elif [[ -d ".agents/skills" ]]; then
  # upstream が .agents/skills/ 配下で公開している慣習
  UPSTREAM_SKILL_PATH=".agents/skills/${SKILL_NAME}"
  mkdir -p "${WORKDIR}/upstream/${UPSTREAM_SKILL_PATH}"
else
  echo "警告: upstream にスキルルートが見つかりません。skills/ を既定として新規追加します。"
  UPSTREAM_SKILL_PATH="skills/${SKILL_NAME}"
  mkdir -p "${WORKDIR}/upstream/${UPSTREAM_SKILL_PATH}"
fi

UPSTREAM_SKILL_PATH が確定したらコピーを実行します。

# LOCAL_SKILL_DIR は Step 1 で解決済み(skills/<name>/ または .agents/skills/<name>/)
# ORIG_DIR は Step 6 で cd する前に捕捉済み(cd - は stdout 汚染のため使用しない)
cp -R "${ORIG_DIR}/${LOCAL_SKILL_DIR}/." "${WORKDIR}/upstream/${UPSTREAM_SKILL_PATH}/"

Step 8: 差分を確認する

cd "$WORKDIR/upstream"
git status
git diff

ユーザーに差分を見せ、内容が意図通りか確認します。

Step 9: ブランチ作成・コミット

SLUG=$(date +%Y%m%d-%H%M%S)
git switch -c "contribute/<SKILL_NAME>-${SLUG}"
git add <変更パス>
git commit -m "$(cat <<'EOF'
<type>(<scope>): <subject>

ローカルの skills/<SKILL_NAME>/ からの貢献。

EOF
)"
  • Conventional Commits 形式
  • --no-verify は使用しない(pre-commit フックを通す)
  • co-author は付けない(ローカル規約に合わせる)

Step 10: push と PR 作成

git push -u origin "contribute/<SKILL_NAME>-${SLUG}"

gh pr create \
  --repo "${REPO_SLUG}" \
  --base "${DEFAULT_BRANCH:-main}" \
  --title "<type>(<scope>): <subject>" \
  --body "$(cat <<'EOF'
## Summary

- <SKILL_NAME> の改修内容(箇条書き)

## Source

ローカルの [ideas リポジトリ](../../) 側で改修後、`/contribute-skill <SKILL_NAME>` により投稿。

## Test plan

- [ ] SKILL.md を実際に Claude Code で実行
- [ ] Conventional Commits に沿ったメッセージ生成を確認
- [ ] エッジケース確認

EOF
)"

--repo には Step 2 で正規化した ${REPO_SLUG}OWNER/REPO 形式)を渡します。URL 形式から OWNER/REPO への変換は Step 2 の case 文で完了しています。

Draft PR を作成する場合は --draft を付けます(デフォルトはユーザー確認の上で決定)。

Step 11: PR URL を返す & 後処理案内

  • PR URL をユーザーに返す
  • 「マージされたら /sync-skills-lock を実行して skills-lock.jsoncomputedHash を更新してください」と案内
  • 作業用ディレクトリ $WORKDIR は残したまま(成否が確定するまで)

注意事項

  • SKILL_NAME は kebab-case のみ許可.. のような値によるパストラバーサルを防ぐため、空判定の直後・パス解決の前に ^[a-z][a-z0-9-]+$ で検証する(security.md A03/A01)
  • `skills/` と `.agents/skills/` の両方が存在する場合は中止:silently に skills/ を優先せず、環境変数 LOCAL_SKILL_DIR に改修対象パスを指定して再実行を求める。LOCAL_SKILL_DIRskills/<name>.agents/skills/<name> の2パスのみ受理し、任意パス指定によるパストラバーサルを防ぐ
  • source が Fandhe-AI org 以外の場合は中止Fandhe-AI/(短縮形)と https://github.com/Fandhe-AI/(URL 形式)のみを許可し、それ以外は意図しない外部リポジトリへの push を防ぐため中止する
  • セキュリティ問題が見つかった場合は中止:修正後に再実行
  • upstream の配置はクローンしたリポジトリのレイアウトで判定するskills-lock.jsonskillPath はローカル install パス(例: .agents/skills/github-docs/SKILL.md)であり、upstream リポジトリ内の配置ではない。skillPath の dirname を UPSTREAM_SKILL_PATH に採用してはならない。判定順は skills/<name> の存在 → .agents/skills/<name> の存在 → スキルルート親ディレクトリ(skills/ or .agents/skills/)の慣習 → 最終デフォルト skills/(より一般的な公開レイアウト)
  • 既に同名の branch がある場合:秒単位スラッグで通常は衝突しないが、万一の場合はユーザーに確認

sandbox 環境での実行

このスキルは sandbox 環境では実行できない。ネットワークアクセス・ファイルシステムへの書き込みが必要なため、通常の Claude Code セッションで実行すること。

検証

PR 作成後、以下で完了を確認する。

# PR が作成されたことを確認
gh pr view --repo "${REPO_SLUG}" --web

# または URL を直接確認(Step 11 で出力済み)
  • PR URL が返されること
  • PR のタイトル・差分が意図した内容であること
  • sync-skills-lock 実行案内が出力されていること

既存スキルとの関係

  • Step 4 のセキュリティチェック、Step 9 の Conventional Commits、Step 10 の PR body は create-pr/SKILL.md の流儀を踏襲
  • マージ後は sync-skills-lockskills-lock.jsoncomputedHash を更新

Related skills

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.