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.
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/dotfiles-<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.
curl -fsSL https://raw.githubusercontent.com/lumalabs/coder-skills/main/install.sh | bashDrops lumalabs-skills into /usr/local/bin. Depends on git, gh, aws, python3 (with boto3) — auto-installs boto3 if missing.
lumalabs-skills migrateWalks you through:
- 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/. git initon~/.claude/, writes.gitignore(creds + caches + scratch dirs all excluded).- Creates
lumalabs/dotfiles-<your-gh-username>private repo viagh repo create. Asks first. - Initial commit + push of skill code.
aws s3 sync ~/.coder-auth/ s3://<bucket>/<coder-user-id>/to seed the cred layer.
The migration is interactive — never moves anything without confirming.
# 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 statusFor 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.
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/dotfiles-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"
}
]
}In a Coder workspace, the agent's startup script:
git clone https://github.com/lumalabs/dotfiles-<your-username>.git ~/.claude/- Reads
~/.claude/.skills-vault.json - For each credential entry, symlinks
$HOME/<file>→$HOME/.coder-auth/<auth_blob> - 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.
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_DOTFILES_OWNER |
lumalabs |
GitHub org for the private repo |
CODER_DOTFILES_PREFIX |
dotfiles- |
Repo name prefix; final name = <owner>/<prefix><gh-username> |
- Credentials never enter chat or shell history.
rotateusesgetpass(input hidden, no echo). - The
~/.claude/git repo is.gitignore'd aggressively — caches, scratch dirs, and theauth_blobnames from the manifest. The migration tool generates a starting.gitignorebased 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.
- 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.gitignoremanually). - 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 pushfrom two laptops at the same time, vanilla git semantics apply.
MIT.