Claude Code Plugins

Community-maintained marketplace

Feedback

android-keystore-generation

@hitoshura25/claude-devtools
0
0

Generate production and local development keystores for Android release signing

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name android-keystore-generation
description Generate production and local development keystores for Android release signing
category android
version 1.0.0
inputs [object Object], [object Object], [object Object]
outputs keystores/production-release.jks, keystores/local-dev-release.jks, keystores/KEYSTORE_INFO.txt
verify ls keystores/*.jks && cat keystores/KEYSTORE_INFO.txt

Android Keystore Generation

Generates dual keystores for Android release signing: production (CI/CD only) and local development.

Prerequisites

  • JDK installed (keytool command available)
  • Write access to project directory

Inputs

Input Required Default Description
project_path Yes . Android project root
organization Yes - Organization name for certificate DN
country_code No US 2-letter country code

Process

Organization Name

ALWAYS prompt the user, but provide the auto-detected value as default.

Step 1: Detect organization from package name

# Extract package name from build.gradle.kts
PACKAGE=$(grep "applicationId" app/build.gradle.kts | sed 's/.*"\(.*\)".*/\1/')
echo "Package: $PACKAGE"

# Extract second segment: com.{ORG}.app → ORG
ORG=$(echo $PACKAGE | cut -d. -f2)
echo "Detected organization: $ORG"

Step 2: MANDATORY - Ask the user for confirmation

DO NOT SKIP THIS PROMPT

Ask the user:

"The detected organization name is {ORG}. Press Enter to use this, or type a different name:"

Wait for user response. Use their input if provided, otherwise use the detected default.

Step 3: Store the confirmed organization name

ORGANIZATION="{confirmed_org_name}"
echo "Using organization: $ORGANIZATION"

Why this matters: The organization appears in the certificate's Distinguished Name. While it doesn't affect app functionality, users may want to customize it.

Password Generation Options

Choose one option for keystore passwords:

Option 1 (Recommended): User-Provided Password

Ask the user to provide a password for the production keystore:

"Please enter a password for the production keystore (minimum 12 characters, mix of letters, numbers, and symbols):"

Security benefits:

  • Password never visible to the agent during the conversation
  • User has complete control over password strength and storage
  • Reduces risk of password exposure in logs or conversation history

Instructions for user:

# User will run keytool command manually with their chosen password
# Example:
keytool -genkeypair -v \
  -keystore keystores/production-release.jks \
  -storetype PKCS12 \
  -alias upload \
  -keyalg RSA \
  -keysize 2048 \
  -validity 10000 \
  -storepass "YOUR_PASSWORD_HERE" \
  -keypass "YOUR_PASSWORD_HERE" \
  -dname "CN=Android Release, OU=Android, O={ORGANIZATION}, C=US"

Option 2: Generated Password

If the user prefers a generated password, use the automated generation steps below.

Note: The agent will have access to this password during the session. The password will be stored in temporary files and KEYSTORE_INFO.txt.

"Would you like me to generate a secure password? (The agent will see this password during generation)"

If yes, proceed with the automated generation steps.

Step 1: Create Keystores Directory

mkdir -p keystores

Step 2: Generate Production Keystore

SECURITY: This keystore is for CI/CD only. Never use locally.

⚠️ IMPORTANT: Run each command in a SEPARATE bash call. Do NOT combine commands.

Step 2a: Generate password and save to file

openssl rand -base64 24 | tr -d '/+=' | head -c 24 > /tmp/prod_password.txt

Step 2b: Read and display the password

cat /tmp/prod_password.txt

📝 Copy this password now - you'll need it for the keytool command and KEYSTORE_INFO.txt

Step 2c: Generate the keystore

Replace {PASSWORD} with the password from Step 2b, and {ORGANIZATION} with the confirmed organization name:

keytool -genkeypair -v \
  -keystore keystores/production-release.jks \
  -storetype PKCS12 \
  -alias upload \
  -keyalg RSA \
  -keysize 2048 \
  -validity 10000 \
  -storepass "{PASSWORD}" \
  -keypass "{PASSWORD}" \
  -dname "CN=Android Release, OU=Android, O={ORGANIZATION}, C=US"

If keytool prompts for confirmation, type yes and press Enter.

Step 2d: Verify keystore was created

ls -la keystores/production-release.jks

Expected output:

-rw-------  1 user  staff  2557 Dec 11 10:30 keystores/production-release.jks

Step 3: Generate Local Development Keystore

⚠️ IMPORTANT: Run each command in a SEPARATE bash call. Do NOT combine commands.

Step 3a: Generate password and save to file

openssl rand -base64 24 | tr -d '/+=' | head -c 24 > /tmp/local_password.txt

Step 3b: Read and display the password

cat /tmp/local_password.txt

📝 Copy this password now - you'll need it for the keytool command and KEYSTORE_INFO.txt

Step 3c: Generate the keystore

Replace {PASSWORD} with the password from Step 3b:

keytool -genkeypair -v \
  -keystore keystores/local-dev-release.jks \
  -storetype PKCS12 \
  -alias local-dev \
  -keyalg RSA \
  -keysize 2048 \
  -validity 10000 \
  -storepass "{PASSWORD}" \
  -keypass "{PASSWORD}" \
  -dname "CN=Local Development, OU=Development, O=Local, C=US"

If keytool prompts for confirmation, type yes and press Enter.

Step 3d: Verify keystore was created

ls -la keystores/local-dev-release.jks

Expected output:

-rw-------  1 user  staff  2557 Dec 11 10:30 keystores/local-dev-release.jks

Step 4: Create Credentials File

cat > keystores/KEYSTORE_INFO.txt << EOF
Production Keystore
===================
File: production-release.jks
Alias: upload
Store Password: $PROD_PASSWORD
Key Password: $PROD_PASSWORD (same as store - PKCS12 requirement)

⚠️ SECURITY: CI/CD ONLY - Never use on developer machines

GitHub Secrets:
  SIGNING_KEY_STORE_BASE64: $(base64 -w 0 keystores/production-release.jks 2>/dev/null || base64 -i keystores/production-release.jks)
  SIGNING_KEY_ALIAS: upload
  SIGNING_STORE_PASSWORD: $PROD_PASSWORD
  SIGNING_KEY_PASSWORD: $PROD_PASSWORD

---

Local Development Keystore
==========================
File: local-dev-release.jks
Alias: local-dev
Store Password: $LOCAL_PASSWORD
Key Password: $LOCAL_PASSWORD

Add to ~/.gradle/gradle.properties:
  SIGNING_KEY_STORE_PATH=$(pwd)/keystores/local-dev-release.jks
  SIGNING_KEY_ALIAS=local-dev
  SIGNING_STORE_PASSWORD=$LOCAL_PASSWORD
  SIGNING_KEY_PASSWORD=$LOCAL_PASSWORD
EOF

Step 5: Update .gitignore

# Add to .gitignore if not present
grep -q "keystores/" .gitignore 2>/dev/null || echo "keystores/" >> .gitignore
grep -q "*.jks" .gitignore 2>/dev/null || echo "*.jks" >> .gitignore

Verification

MANDATORY: Run these commands:

# Verify keystores exist
ls -la keystores/*.jks

# Verify credentials documented
cat keystores/KEYSTORE_INFO.txt

# Verify gitignored
grep "keystores" .gitignore

Expected output:

  • Two .jks files in keystores/
  • KEYSTORE_INFO.txt with passwords
  • keystores/ in .gitignore

Outputs

Output Location Description
Production keystore keystores/production-release.jks For CI/CD only
Local keystore keystores/local-dev-release.jks For local testing
Credentials keystores/KEYSTORE_INFO.txt Passwords and setup info

Troubleshooting

"keytool: command not found"

Cause: JDK not installed or not in PATH Fix: Install JDK 17: brew install openjdk@17 (macOS) or apt install openjdk-17-jdk (Linux)

"openssl: command not found"

Cause: OpenSSL not installed Fix: Use alternative password generation: head -c 24 /dev/urandom | base64

Completion Criteria

  • keystores/production-release.jks exists
  • keystores/local-dev-release.jks exists
  • keystores/KEYSTORE_INFO.txt exists with passwords
  • keystores/ is in .gitignore