A lightweight tool to sync your AI CLI skills library to Google Shared Drive — enabling cross-tool compatibility, cross-machine portability, and access from the Gemini web app.
Before you continue: This tool requires a Google Workspace account (paid). Shared Drives are not available on free Gmail. If you only have a personal Google account, this won't work without code changes.
If you use Claude Code and Gemini CLI seriously, you build up a library of skills — reusable context files that shape how the AI behaves on specific tasks. The problem is three-fold:
- Cross-tool — Claude Code and Gemini CLI both support skills but don't share them. A skill refined for Claude isn't available to Gemini, and vice versa.
- Cross-machine — Your skills library lives on one machine. Set up a new laptop and you start from scratch.
- Web app access — The Gemini web app and Custom Gems can reference Google Drive files as context. If your skills live on Drive, they're available there too.
A single sync script writing to Google Shared Drive solves all three at once.
~/.local/share/sync-skills/skills/
│
▼ skills-sync (push)
Google Shared Drive ◄──────────────────────────────────┐
│ │
├──▶ Machine 2 (pull on setup) │
├──▶ Machine 3 (pull on setup) │
└──▶ Gemini App / Custom Gem (references Drive) │
│
SA Key (scoped to this Shared Drive only) ───────┘
- Push (default) — incremental, only uploads files changed since last sync
- Push --full — forces re-upload of everything
- Pull — downloads the full skills library from Drive to local
- Python 3.8+
- A Google Cloud project with a Service Account and Google Drive API enabled
- Google Workspace account — Shared Drives are a Workspace feature (not available on free Gmail). If you only have a personal Google account, this tool won't work without code changes to target a regular My Drive folder instead.
- A Google Shared Drive
- The SA granted
Content Manageraccess on the Shared Drive only - D2 (open source, terrastruct/d2) — installed automatically by
install.shvia the official install script. Required for diagram generation. Self-contained Go binary, no runtime dependencies. For secure environments where piping curl to sh is not acceptable, download and verify a release binary directly from the D2 releases page.
- Go to Google Cloud Console → IAM & Admin → Service Accounts
- Create a new SA (e.g.
skills-sync) - Create and download a JSON key (treat it like a password — it grants write access to your Shared Drive)
- In Google Drive, open your Shared Drive → Manage members → add the SA email with
Content Managerrole
Open the Shared Drive in your browser. The URL will look like:
https://drive.google.com/drive/folders/0AALIUj_e6cRVUk9PVA
^^^^^^^^^^^^^^^^^^^^
this is your DRIVE_ID
Security note: Grant
Content Manageron the target Shared Drive only — not your personal Drive or GCP project broadly. A compromised key with this scope can only read/write one folder.
Step 1 — Clone this repo (or download the files from your Shared Drive if you stored them there):
git clone https://github.com/curtiskrygier/skills-sync.git
cd skills-syncStep 2 — Place your SA key .json file in the same folder as install.sh.
Step 3 — Run the installer:
bash install.shThe script detects your key file automatically and prompts for your Drive ID. That's it.
If you store your key base64-encoded in a password manager rather than as a file, pass everything via heredoc instead:
Shell history: The heredoc passes your SA key through the terminal and may be saved to
.bash_history/.zsh_history. Rununset HISTFILEbefore pasting to prevent this, then restoreHISTFILEto its previous value afterwards.
bash install.sh << 'EOF'
DRIVE_ID=YOUR_SHARED_DRIVE_ID
SA_NAME=your-sa-key-filename.json
SA_KEY_B64=YOUR_BASE64_ENCODED_SA_KEY
DRIVE_FOLDER=skills # optional subfolder within the Shared Drive
EOF- Writes and secures the SA key (
chmod 600) in~/.local/share/sync-skills/ - Sets up a Python venv at
~/.local/share/sync-skills/venv/ - Installs
sync_skills.pyand dependencies - Pulls your full skills library from Drive into
~/.local/share/sync-skills/skills/ - Installs a
skills-syncwrapper command to~/.local/bin/ - Symlinks
~/.gemini/skills → skills/for Gemini CLI - Symlinks
~/.claude/skills → skills/for Claude Code - Adds a skills reference to
~/.claude/CLAUDE.mdfor Claude Code context
One script, fully bootstrapped.
On your existing machine, encode the key:
# Linux
base64 -w 0 path/to/your-sa-key.json
# macOS (no -w flag — wraps at 76 chars, handled automatically by install.sh)
base64 path/to/your-sa-key.jsonStore the output in your password manager (Bitwarden, 1Password, etc.). On a new machine, decode it directly to a file:
# Linux
echo "PASTE_BASE64_HERE" | base64 -d > your-sa-key.json
# macOS
echo "PASTE_BASE64_HERE" | base64 -D > your-sa-key.jsonNote:
base64is encoding, not encryption. Your password manager's own security (ideally with 2FA) is the lock on this credential.
After install:
~/.local/share/sync-skills/ ← all tool infrastructure
├── sync_skills.py
├── venv/ ← Python venv
├── YOUR_SA_KEY.json ← never committed, never synced
├── .config ← Drive ID and folder, written by install.sh
├── .last_sync ← timestamp of last successful push
└── skills/ ← your skills library
├── example/
│ └── SKILL.md ← copy this as a starting point for new skills
├── my-skill/
│ └── SKILL.md
└── ...
~/.gemini/skills → ~/.local/share/sync-skills/skills ← Gemini CLI
~/.claude/skills → ~/.local/share/sync-skills/skills ← Claude Code
~/.local/bin/skills-sync ← wrapper command
Both tools point at the same skills directory. A skill added in Claude Code is immediately visible in Gemini CLI and vice versa — no sync step needed between tools.
skills-sync # push changes to Drive (incremental)
skills-sync --full # push everything
skills-sync --dry-run # preview push (no credentials needed)
skills-sync --pull # pull latest from Drive
skills-sync --pull --dry-run # preview pullPATH:
~/.local/binmust be in your PATH forskills-syncto work. Most Linux distributions include this by default. If not, addexport PATH="$HOME/.local/bin:$PATH"to your shell profile.
DRIVE_FOLDER and SHARED_DRIVE_ID can also be passed as environment variables at runtime:
SHARED_DRIVE_ID=your_id DRIVE_FOLDER=skills skills-syncNote: Incremental push tracks changes using a
.last_synctimestamp. If you restore files from a backup or clone the skills directory from git (which resets file modification times), use--fullon the first push to ensure everything uploads correctly.
Both Claude Code and Gemini CLI use markdown-based skill files:
| Tool | Format | Location |
|---|---|---|
| Gemini CLI | SKILL.md inside a named folder |
~/.gemini/skills/skill-name/SKILL.md |
| Claude Code | SKILL.md inside a named folder, invoked with /skill-name |
~/.claude/skills/skill-name/SKILL.md |
Since both paths symlink to the same directory, the same files work in both tools automatically.
To verify skills are working after install, type / in Claude Code — your skills should appear in the menu. For Gemini CLI, ask it to use the example skill.
With Gemini Advanced (included with most Google Workspace plans), you can create a Custom Gem that references your Shared Drive folder directly as its knowledge base. Your skills become available in the Gemini web app without any extra steps.
- The SA key is never synced to Drive — it lives in
~/.local/share/sync-skills/which is never uploaded - The SA should have
Content Manageraccess on the target Shared Drive only base64is transport encoding, not encryption — use a properly secured password manager- The install directory is
chmod 700; the key file and config arechmod 600 - A
.gitignorecovering*.jsonand.last_syncis written at install time
Act immediately — the key grants persistent write access to your Shared Drive until explicitly revoked:
- Fastest: Open Google Drive → your Shared Drive → Manage members → remove the SA email. This cuts access instantly without needing GCP access.
- Go to Google Cloud Console → IAM & Admin → Service Accounts
- Find your
skills-syncSA → Keys tab → delete the compromised key - Create a new key, re-encode it, and update your password manager
- Re-run
install.shon each machine to deploy the new key - Review your Shared Drive activity log (Drive → your Shared Drive → Activity panel) for unexpected changes
Revoking the key in GCP is instant — the old key stops working immediately regardless of where copies exist.
For shared machines or environments where you want zero local credential footprint, pass the SA key as an environment variable. The key lives only in memory for the duration of the script.
export SHARED_DRIVE_ID="YOUR_SHARED_DRIVE_ID"
# Linux
export SA_KEY_JSON=$(echo "YOUR_BASE64_ENCODED_SA_KEY" | base64 -d)
# macOS
export SA_KEY_JSON=$(echo "YOUR_BASE64_ENCODED_SA_KEY" | base64 -D)
skills-syncNothing is written to disk. The credentials exist only for the life of the shell session.
Git-based sync is the obvious alternative and worth considering seriously:
- Full version history on every skill change
- Works with any Google account (no Workspace required)
- Most developers already have the tooling set up
However, it doesn't solve all three problems without additional work:
- Cross-machine ✓ — git handles this well
- Cross-tool ✓ — same repo, different local paths
- Gemini app / Custom Gems ✗ — Drive access still requires a sync step (e.g. GitHub Actions), which means storing a service account key in GitHub Secrets anyway
On the security side, git introduces its own risks for credential-adjacent workflows: accidental commits of key files are permanent in history (even after removal), and a public repo is one bad .gitignore away from exposure. With this tool, the credential never touches a repo — it lives in your password manager and on disk with 600 permissions, scoped to a single Shared Drive.
If you're already Workspace-native and want Gemini app access without extra automation, Drive sync is the simpler path. If you're Git-first and don't need the Gemini web app integration, a private repo is a perfectly valid choice.
requirements.lock pins all dependencies to exact versions with SHA256 hashes. When you want to update:
# Install pip-tools into the venv if not already present
~/.local/share/sync-skills/venv/bin/pip install pip-tools
# Regenerate the lockfile from requirements.txt
~/.local/share/sync-skills/venv/bin/pip-compile --generate-hashes requirements.txt --output-file requirements.lock
# Review what changed before committing
git diff requirements.lockTreat the lockfile diff like a dependency PR — check what changed and why before committing. After regenerating, re-run install.sh on each machine to apply the updated packages.
MIT
