Skip to content

feat: add Azure Blob Storage provider#37

Open
jimjawn wants to merge 12 commits into
tawanorg:mainfrom
jimjawn:main
Open

feat: add Azure Blob Storage provider#37
jimjawn wants to merge 12 commits into
tawanorg:mainfrom
jimjawn:main

Conversation

@jimjawn

@jimjawn jimjawn commented Jun 12, 2026

Copy link
Copy Markdown

Summary

  • Adds Azure Blob Storage as a new storage provider using a container-scoped SAS URL
  • Single credential — the full SAS URL (including account, container, and token) is stored in ~/.claude-sync/config.yaml and works identically on macOS, Linux, and Windows
  • Supports CLAUDE_SYNC_AZURE_URL env var as an alternative to --azure-url flag to keep the SAS token out of shell history and ps output

Implementation notes

Auth design: container-scoped SAS URL (sr=c). No Azure CLI, no managed identity, no account key stored — just a URL that can be generated once and reused across all devices. Long-lived SAS tokens (e.g. expiry 2099) are practical for personal sync use cases.

One gotcha worth knowing: GetContainerProperties is not authorized by a container-scoped SAS — it's a management-plane operation. BucketExists uses ListBlobs (authorized via the l permission) instead. This is verified against the Azure SDK error codes.

Windows relevance: this provider is pure Go with no OS-specific dependencies, so it works on windows-amd64 and windows-arm64 out of the box. For users on the Microsoft ecosystem (see #31), Azure is often already available — no new cloud account needed.

Files changed

  • internal/storage/azure/azure.go — new provider implementing the Storage interface
  • internal/storage/azure/azure_test.go — constructor tests
  • internal/storage/config.goAzureURL field, validateAzure(), bucket check exclusion
  • internal/storage/storage.goProviderAzure constant, NewAzure var, factory case
  • cmd/claude-sync/main.go — wizard, --azure-url flag, CLAUDE_SYNC_AZURE_URL env var, blank import
  • README.md — Azure setup section with az storage container generate-sas instructions

Test plan

  • go test ./... passes
  • claude-sync init → select Azure → paste SAS URL → connection test succeeds
  • claude-sync push uploads files to Azure container
  • claude-sync pull on a second device restores files
  • CLAUDE_SYNC_AZURE_URL=<url> claude-sync init --provider azure works without interactive prompt

jimjawn and others added 12 commits June 12, 2026 15:46
…ring

- Add ProviderAzure constant and NewAzure function var to storage.go
- Add AzureURL field to StorageConfig (yaml: azure_url)
- Exclude ProviderAzure from bucket-required check in Validate()
- Add validateAzure() enforcing non-empty https:// URL
- Wire ProviderAzure into Validate() switch and New() factory
- Add TestValidateAzure covering valid SAS URL, empty URL, http URL

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…rtions

- Add three Azure cases to TestStorageConfig_Validate (valid, empty URL,
  http URL) with errMsg assertions, testing through the public Validate()
  entry point instead of the unexported validateAzure()
- Remove standalone TestValidateAzure function
- Replace hand-rolled contains/findSubstring helpers with strings.Contains
  in both config_test.go and storage_test.go (same package, shared helpers)

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Implements the Storage interface using container-scoped SAS URLs via
azblob v1.5.0. Includes constructor tests for valid URL, missing
container, and invalid URL cases.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Add `claude-sync auto enable/disable/status` subcommands that install and
remove claude-sync pull/push hooks in ~/.claude/settings.json, merging with
existing hooks without clobbering them. Backed by new internal/claudesettings
package that round-trips the full settings file via a raw JSON map.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant