Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 26 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,8 @@ Selected profiles are queried in parallel; resources display with Profile and Ac
| `:tag <filter>` | Filter by tag |
| `:diff <name>` | Compare current row with named resource |
| `:diff <n1> <n2>` | Compare two named resources |
| `:theme <name>` | Change color theme (saved if persistence enabled) |
| `:autosave on/off` | Enable/disable config autosave (always saved) |

**Login Details:**
- `:login` runs `aws login --remote` using `claws-login` profile
Expand Down Expand Up @@ -413,19 +415,39 @@ concurrency:
cloudwatch:
window: 15m # Metrics data window period (default: 15m)

persistence:
enabled: true # Save region/profile on change (default: false)
autosave:
enabled: true # Save region/profile/theme on change (default: false)

startup: # Applied on launch if present
profile: production
profiles: # Multiple profiles supported
- production
regions:
- us-east-1
- us-west-2

theme: nord # Preset: dark, light, nord, dracula, gruvbox, catppuccin

# Or use preset with custom overrides:
# theme:
# preset: dracula
# primary: "#ff79c6"
# danger: "#ff5555"
```

**Available Theme Presets:**

| Preset | Description |
|--------|-------------|
| `dark` | Default dark theme (pink/magenta accents) |
| `light` | For light-background terminals |
| `nord` | Nordic, calm blue palette |
| `dracula` | Popular dark theme (purple/pink) |
| `gruvbox` | Retro, warm earth tones |
| `catppuccin` | Modern pastel (Mocha variant) |

The config file is **not created automatically**. Create it manually if needed.

CLI flags (`-p`, `-r`, `--persist`, `--no-persist`) override config file settings.
CLI flags (`-p`, `-r`, `-t`, `--autosave`, `--no-autosave`) override config file settings.

For required IAM permissions, see [docs/iam-permissions.md](docs/iam-permissions.md).

Expand Down
54 changes: 31 additions & 23 deletions cmd/claws/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/clawscli/claws/internal/config"
"github.com/clawscli/claws/internal/log"
"github.com/clawscli/claws/internal/registry"
"github.com/clawscli/claws/internal/ui"
)

// version is set by ldflags during build
Expand All @@ -27,9 +28,8 @@ func main() {
fileCfg := config.File()
cfg := config.Global()

// CLI persistence flags override config file
if opts.persist != nil {
fileCfg.SetPersistenceEnabled(*opts.persist)
if opts.autosave != nil {
fileCfg.SetPersistenceEnabled(*opts.autosave)
}

// Check environment variables (CLI flags take precedence)
Expand All @@ -53,6 +53,8 @@ func main() {

applyStartupConfig(opts, fileCfg, cfg)

ui.ApplyConfigWithOverride(fileCfg.GetTheme(), opts.theme)

// Validate and resolve startup service/resource
var startupPath *app.StartupPath
if opts.service != "" {
Expand Down Expand Up @@ -101,10 +103,11 @@ type cliOptions struct {
region string
readOnly bool
envCreds bool
persist *bool // nil = use config, true = enable, false = disable
autosave *bool
logFile string
service string // startup service (e.g., "ec2", "rds/snapshots", "cfn")
resourceID string // startup resource ID for direct DetailView navigation
service string
resourceID string
theme string
}

// parseFlags parses command line flags and returns options
Expand All @@ -130,12 +133,12 @@ func parseFlags() cliOptions {
opts.readOnly = true
case "-e", "--env":
opts.envCreds = true
case "--persist":
case "--autosave":
t := true
opts.persist = &t
case "--no-persist":
opts.autosave = &t
case "--no-autosave":
f := false
opts.persist = &f
opts.autosave = &f
case "-l", "--log-file":
if i+1 < len(args) {
i++
Expand All @@ -151,6 +154,11 @@ func parseFlags() cliOptions {
i++
opts.resourceID = args[i]
}
case "-t", "--theme":
if i+1 < len(args) {
i++
opts.theme = args[i]
}
case "-h", "--help":
showHelp = true
case "-v", "--version":
Expand Down Expand Up @@ -191,12 +199,14 @@ func printUsage() {
fmt.Println(" Useful for instance profiles, ECS task roles, Lambda, etc.")
fmt.Println(" -ro, --read-only")
fmt.Println(" Run in read-only mode (disable dangerous actions)")
fmt.Println(" --persist")
fmt.Println(" Enable saving region/profile selection to config file")
fmt.Println(" --no-persist")
fmt.Println(" Disable saving region/profile selection to config file")
fmt.Println(" --autosave")
fmt.Println(" Enable saving region/profile/theme to config file")
fmt.Println(" --no-autosave")
fmt.Println(" Disable saving region/profile/theme to config file")
fmt.Println(" -l, --log-file <path>")
fmt.Println(" Enable debug logging to specified file")
fmt.Println(" -t, --theme <name>")
fmt.Println(" Color theme: dark, light, nord, dracula, gruvbox, catppuccin")
fmt.Println(" -v, --version")
fmt.Println(" Show version")
fmt.Println(" -h, --help")
Expand All @@ -213,23 +223,21 @@ func printUsage() {
fmt.Println(" ALL_PROXY Propagated to HTTP_PROXY/HTTPS_PROXY if not set")
}

// applyStartupConfig applies profile/region config with precedence:
// 1. CLI flags (-p, -r, -e) - highest priority
// 2. Config file startup section
// 3. AWS SDK defaults
func applyStartupConfig(opts cliOptions, fileCfg *config.FileConfig, cfg *config.Config) {
startupRegions, startupProfile := fileCfg.GetStartup()
startupRegions, startupProfiles := fileCfg.GetStartup()

// Apply profile: CLI > startup config
if opts.envCreds {
cfg.UseEnvOnly()
} else if opts.profile != "" {
cfg.UseProfile(opts.profile)
} else if startupProfile != "" {
cfg.UseProfile(startupProfile)
} else if len(startupProfiles) > 0 {
sels := make([]config.ProfileSelection, len(startupProfiles))
for i, id := range startupProfiles {
sels[i] = config.ProfileSelectionFromID(id)
}
cfg.SetSelections(sels)
}

// Apply region: CLI > startup config
if opts.region != "" {
cfg.SetRegion(opts.region)
} else if len(startupRegions) > 0 {
Expand Down
2 changes: 1 addition & 1 deletion custom/cloudformation/events/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,6 @@ func cfnResourceStatusColorer(status string) render.Style {
case strings.Contains(status, "DELETE_COMPLETE") || strings.Contains(status, "SKIPPED"):
return ui.DimStyle()
default:
return render.DefaultStyle()
return ui.NoStyle()
}
}
4 changes: 2 additions & 2 deletions custom/cloudformation/resources/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ func cfnResourceStatusColorer(status string) render.Style {
case strings.Contains(status, "DELETE_COMPLETE") || strings.Contains(status, "SKIPPED"):
return ui.DimStyle()
default:
return render.DefaultStyle()
return ui.NoStyle()
}
}

Expand All @@ -171,7 +171,7 @@ func driftColorer(status string) render.Style {
case "NOT_CHECKED":
return ui.DimStyle()
default:
return render.DefaultStyle()
return ui.NoStyle()
}
}

Expand Down
4 changes: 2 additions & 2 deletions custom/cloudformation/stacks/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ func cfnStateColorer(status string) render.Style {
case strings.Contains(status, "DELETE_COMPLETE"):
return ui.DimStyle()
default:
return render.DefaultStyle()
return ui.NoStyle()
}
}

Expand All @@ -267,7 +267,7 @@ func driftColorer(status string) render.Style {
case "NOT_CHECKED":
return ui.DimStyle()
default:
return render.DefaultStyle()
return ui.NoStyle()
}
}

Expand Down
7 changes: 6 additions & 1 deletion docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,12 @@ Some views (Help, Region Selector, Profile Selector, Action Menu) display as mod
Application configuration is stored in `~/.config/claws/config.yaml`:

```yaml
profile: my-aws-profile
startup:
profiles:
- my-aws-profile
regions:
- us-east-1
theme: nord
```

AWS credentials and config are read from standard locations:
Expand Down
Loading