Skip to content

Latest commit

 

History

History
133 lines (92 loc) · 7.49 KB

File metadata and controls

133 lines (92 loc) · 7.49 KB

coder-skills

Carry your personal Claude config (~/.claude/) into Coder workspaces.

The Coder workspace template at lumalabs/luma-core brings up Vespa for you on a remote pod. But your personal Claude setup — skill code, helper scripts, OAuth tokens, API keys — doesn't ride along. This tool fixes that.

What it does

Splits ~/.claude/ into two layers, each in the right storage for what it carries:

Layer Where Why
Personal skill code, helpers, CLAUDE.md, commands Per-engineer private GitHub repo lumalabs/claudefiles-<gh-username> Bidirectional via standard git push/pull. You see diffs, audit trail. Claude-as-agent edits land in the working tree → you commit when ready.
Credential files (~10 files: API keys, OAuth tokens, etc) Existing S3 auth-bucket (lumalabs-dev-oregon-coder-workspace-auth/<coder-user-id>/) Reuses the bucket Coder workspaces already use for ~/.claude/.credentials.json. KMS-encrypted, IRSA-scoped per-engineer, bidirectional sync daemon already runs.

After migrate, every Coder workspace claim auto-loads both layers — you SSH in and claude --version, linear-graphql, python3 ~/.claude/google_token.py all work.

Install

curl -fsSL https://raw.githubusercontent.com/lumalabs/coder-skills/main/install.sh | bash

Drops lumalabs-skills into /usr/local/bin. Depends on git, gh, aws, python3 (with boto3) — auto-installs boto3 if missing.

One-time setup

lumalabs-skills migrate

Walks you through:

  1. Scans ~/.claude/ for credential-shaped files. For each one, asks "is this a credential?" — confirmed creds get moved to ~/.coder-auth/, everything else stays in ~/.claude/.
  2. git init on ~/.claude/, writes .gitignore (creds + caches + scratch dirs all excluded).
  3. Creates lumalabs/claudefiles-<your-gh-username> private repo via gh repo create. Asks first.
  4. Initial commit + push of skill code.
  5. aws s3 sync ~/.coder-auth/ s3://<bucket>/<coder-user-id>/ to seed the cred layer.

The migration is interactive — never moves anything without confirming.

Already migrated under the old dotfiles-<user> naming?

The repo was previously named dotfiles-<user> and got renamed to claudefiles-<user> to avoid confusion with traditional Unix dotfiles (the .bashrc / .vimrc kind that Coder's separate dotfiles_uri module handles). One-time per-engineer migration:

lumalabs-skills migrate-to-claudefiles

Renames the GitHub repo, updates your local ~/.claude git remote URL, and rewrites the manifest. GitHub keeps the old URL as a redirect, so workspaces / laptops that haven't picked up the new manifest yet still work transparently.

Day-to-day

# Push laptop edits to cloud (force one-shot, don't wait for the daemon's 30s)
lumalabs-skills push

# Pull cloud edits to laptop (e.g., after working in a workspace)
lumalabs-skills pull

# Rotate a credential — input is hidden (no echo), no secret values in shell history
lumalabs-skills rotate linear_api_key

# Show current state
lumalabs-skills status

For workspace-side use: the same CLI is baked into the Coder workspace image, so lumalabs-skills works identically inside a workspace. You can rotate a credential from any workspace and all your other workspaces pick it up within ~30s.

What gets committed vs. what gets synced via S3

migrate writes ~/.claude/.skills-vault.json — a manifest mapping each credential file to its S3 blob name + permissions. The manifest itself is committed (no secret values, just the layout — the workspace startup uses it to know what symlinks to set up).

Example manifest:

{
  "version": 1,
  "dotfiles_repo": "lumalabs/claudefiles-sshumaker",
  "coder_user_id": "3c705ffc-48c6-4875-8e55-568d31ae7b6a",
  "credentials": [
    {
      "file": ".claude/google_oauth_token.json",
      "auth_blob": "claude-google-oauth-token-json",
      "mode": "0600"
    },
    {
      "file": ".claude/linear_api_key",
      "auth_blob": "claude-linear-api-key",
      "mode": "0600"
    }
  ]
}

Workspace-side integration

In a Coder workspace, the agent's startup script:

  1. git clone https://github.com/lumalabs/claudefiles-<your-username>.git ~/.claude/
  2. Reads ~/.claude/.skills-vault.json
  3. For each credential entry, symlinks $HOME/<file>$HOME/.coder-auth/<auth_blob>
  4. The existing 30s S3 sync daemon keeps ~/.coder-auth/ mirrored to your S3 prefix

Result: when you SSH into a fresh workspace, both your personal skill code AND your credentials are already in place.

Configuration

Override via env (or just set defaults that match your team):

Env Default What
CODER_AUTH_BUCKET lumalabs-dev-oregon-coder-workspace-auth S3 bucket for cred sync
CODER_AUTH_BUCKET_REGION us-west-2
CODER_AUTH_BUCKET_PROFILE luma-dev AWS profile to use
CODER_CLAUDEFILES_OWNER lumalabs GitHub org for the private repo (legacy: CODER_DOTFILES_OWNER)
CODER_CLAUDEFILES_PREFIX claudefiles- Repo name prefix; final name = <owner>/<prefix><gh-username> (legacy: CODER_DOTFILES_PREFIX)

Security

  • Credentials never enter chat or shell history. rotate uses getpass (input hidden, no echo).
  • The ~/.claude/ git repo is .gitignore'd aggressively — caches, scratch dirs, and the auth_blob names from the manifest. The migration tool generates a starting .gitignore based on what it migrated; review it before the first commit.
  • S3 bucket is IRSA-scoped per-engineer in the workspace pod (engineer can read/write their own <coder-user-id>/ prefix only). Laptop side uses the engineer's AWS SSO credentials directly.

Known limitations

  • Doesn't migrate node_modules/, cache/, etc. — those are explicitly excluded (commit them to the dotfiles repo only if you really want them, by removing from .gitignore manually).
  • Cred rotation is last-write-wins across concurrent workspaces. Acceptable for personal dev creds; fine in practice since the same engineer is the only writer.
  • No conflict-resolution UI for the git side; if you git push from two laptops at the same time, vanilla git semantics apply.

License

MIT.