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
82 changes: 82 additions & 0 deletions .github/workflows/integration-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
name: Integration Test

on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]

permissions:
contents: read

jobs:
vhs-test:
runs-on: ubuntu-latest
env:
CGO_ENABLED: 0
AWS_ENDPOINT_URL: http://localhost:4566
AWS_ACCESS_KEY_ID: test
AWS_SECRET_ACCESS_KEY: test
AWS_DEFAULT_REGION: us-east-1
AWS_EC2_METADATA_DISABLED: "true"
steps:
- uses: actions/checkout@v6

- uses: actions/setup-go@v6
with:
go-version-file: 'go.mod'
cache: true

- name: Build
run: go build -o claws ./cmd/claws

- name: Start LocalStack
run: |
docker run -d --name localstack -p 4566:4566 localstack/localstack:4.12.0
echo "Waiting for LocalStack..."
for i in $(seq 1 30); do
if curl -s http://localhost:4566/_localstack/health | grep -qE '"s3": "(available|running)"'; then
echo "LocalStack is ready"
exit 0
fi
sleep 1
done
echo "LocalStack failed to start"
exit 1

- name: Setup demo data
timeout-minutes: 5
run: ./scripts/localstack-demo-setup.sh

- name: Create AWS config for demo
run: |
mkdir -p ~/.aws
cp scripts/demo-aws-config/config ~/.aws/config
cp scripts/demo-aws-config/credentials ~/.aws/credentials

- name: Run VHS tapes
run: |
set -e
for tape in docs/tapes/*.tape; do
echo "=========================================="
echo "Running: $tape"
echo "=========================================="
docker run --rm --network host \
-v "$(pwd)":/vhs \
-v ~/.aws:/root/.aws:ro \
-e AWS_ENDPOINT_URL=http://localhost:4566 \
-e AWS_EC2_METADATA_DISABLED=true \
ghcr.io/charmbracelet/vhs "$tape"
done

- name: Upload screenshots on failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: vhs-screenshots
path: docs/images/
retention-days: 7

- name: Cleanup LocalStack
if: always()
run: docker stop localstack || true
53 changes: 53 additions & 0 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,9 @@ tasks:
cmds:
- task: demo:record:gif
- task: demo:record:themes
- task: demo:record:theme-light
- task: demo:record:features
- task: demo:record:command-mode

demo:record:gif:
desc: Record demo.gif only
Expand Down Expand Up @@ -154,6 +156,57 @@ tasks:
-e AWS_EC2_METADATA_DISABLED=true \
ghcr.io/charmbracelet/vhs docs/tapes/features.tape

demo:record:theme-light:
desc: Record light theme screenshot (requires white terminal background)
deps: [build, localstack:start, localstack:demo-setup]
preconditions:
- sh: '[ "$(uname -s)" = "Linux" ]'
msg: "demo:record requires Linux (--network host not supported on macOS/Windows)"
cmds:
- |
docker run --rm --network host \
-v "$(pwd)":/vhs \
-v "$(pwd)/scripts/demo-aws-config:/root/.aws:ro" \
-e AWS_ENDPOINT_URL=http://localhost:4566 \
-e AWS_EC2_METADATA_DISABLED=true \
ghcr.io/charmbracelet/vhs docs/tapes/theme-light.tape

demo:record:command-mode:
desc: Record command mode suggestion/completion test
deps: [build, localstack:start, localstack:demo-setup]
preconditions:
- sh: '[ "$(uname -s)" = "Linux" ]'
msg: "demo:record requires Linux (--network host not supported on macOS/Windows)"
cmds:
- |
docker run --rm --network host \
-v "$(pwd)":/vhs \
-v "$(pwd)/scripts/demo-aws-config:/root/.aws:ro" \
-e AWS_ENDPOINT_URL=http://localhost:4566 \
-e AWS_EC2_METADATA_DISABLED=true \
ghcr.io/charmbracelet/vhs docs/tapes/command-mode.tape

test:vhs:
desc: Run all VHS tapes as integration tests
deps: [build, localstack:start, localstack:demo-setup]
preconditions:
- sh: '[ "$(uname -s)" = "Linux" ]'
msg: "test:vhs requires Linux (--network host not supported on macOS/Windows)"
cmds:
- |
set -e
for tape in docs/tapes/*.tape; do
echo "=========================================="
echo "Running: $tape"
echo "=========================================="
docker run --rm --network host \
-v "$(pwd)":/vhs \
-v "$(pwd)/scripts/demo-aws-config:/root/.aws:ro" \
-e AWS_ENDPOINT_URL=http://localhost:4566 \
-e AWS_EC2_METADATA_DISABLED=true \
ghcr.io/charmbracelet/vhs "$tape"
done

test-localstack:
desc: Run integration tests with LocalStack
deps: [localstack:start]
Expand Down
21 changes: 21 additions & 0 deletions cmd/claws/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,18 @@ func main() {

propagateAllProxy()

// Set custom config path (CLI flag > env var > default)
configPath := opts.configFile
if configPath == "" {
configPath = strings.TrimSpace(os.Getenv("CLAWS_CONFIG"))
}
if configPath != "" {
if err := config.SetConfigPath(configPath); err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
}

fileCfg := config.File()
cfg := config.Global()

Expand Down Expand Up @@ -110,6 +122,7 @@ type cliOptions struct {
envCreds bool
autosave *bool
logFile string
configFile string
service string
resourceID string
theme string
Expand Down Expand Up @@ -161,6 +174,11 @@ func parseFlagsFromArgs(args []string) cliOptions {
i++
opts.logFile = args[i]
}
case "-c", "--config":
if i+1 < len(args) {
i++
opts.configFile = args[i]
}
case "-s", "--service":
if i+1 < len(args) {
i++
Expand Down Expand Up @@ -221,6 +239,8 @@ func printUsage() {
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(" -c, --config <path>")
fmt.Println(" Use custom config file instead of ~/.config/claws/config.yaml")
fmt.Println(" -l, --log-file <path>")
fmt.Println(" Enable debug logging to specified file")
fmt.Println(" -t, --theme <name>")
Expand All @@ -242,6 +262,7 @@ func printUsage() {
fmt.Println(" claws -r us-east-1,ap-northeast-1 Query multiple regions")
fmt.Println()
fmt.Println("Environment Variables:")
fmt.Println(" CLAWS_CONFIG=<path> Use custom config file")
fmt.Println(" CLAWS_READ_ONLY=1|true Enable read-only mode")
fmt.Println(" ALL_PROXY Propagated to HTTP_PROXY/HTTPS_PROXY if not set")
}
Expand Down
22 changes: 22 additions & 0 deletions cmd/claws/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,25 @@ func TestParseFlags_Combined(t *testing.T) {
t.Error("readOnly should be true")
}
}

func TestParseFlags_ConfigFile(t *testing.T) {
tests := []struct {
name string
args []string
expected string
}{
{"short flag", []string{"-c", "/path/to/config.yaml"}, "/path/to/config.yaml"},
{"long flag", []string{"--config", "/custom/config.yaml"}, "/custom/config.yaml"},
{"with other flags", []string{"-p", "dev", "-c", "/config.yaml", "-r", "us-east-1"}, "/config.yaml"},
{"no config", []string{"-p", "dev"}, ""},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
opts := parseFlagsFromArgs(tt.args)
if opts.configFile != tt.expected {
t.Errorf("configFile = %q, want %q", opts.configFile, tt.expected)
}
})
}
}
24 changes: 23 additions & 1 deletion docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,29 @@ claws uses your standard AWS configuration:

## Configuration File

Optional settings can be stored in `~/.config/claws/config.yaml`:
Optional settings can be stored in `~/.config/claws/config.yaml`.

### Custom Config File Path

Use a custom config file instead of the default:

```bash
# Via CLI flag
claws -c /path/to/config.yaml
claws --config ~/work/claws-work.yaml

# Via environment variable
CLAWS_CONFIG=/path/to/config.yaml claws
```

**Precedence:** `-c` flag > `CLAWS_CONFIG` env var > default (`~/.config/claws/config.yaml`)

Use cases:
- Environment-specific configs (work/personal)
- CI/CD with project-specific settings
- Testing with different configurations

### Config File Format

```yaml
timeouts:
Expand Down
Binary file modified docs/images/actions-menu.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/cmd-suggest-ec.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/cmd-suggest-ec2-c.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/cmd-suggest-ec2-slash.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/cmd-suggest-ec2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/cmd-tab-completion.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/images/demo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/images/detail-view.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/images/multi-account-region.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/images/multi-profile.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/images/multi-region-data.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/images/multi-region.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/images/resource-browser.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed docs/images/test-diff-after-tab.png
Binary file not shown.
Binary file removed docs/images/test-diff-after-tab2.png
Binary file not shown.
Binary file removed docs/images/test-diff-before-tab.png
Binary file not shown.
Binary file removed docs/images/test-diff.gif
Binary file not shown.
Binary file modified docs/images/theme-catppuccin.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/images/theme-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/images/theme-dracula.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/images/theme-gruvbox.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/images/theme-light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/images/theme-nord.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 10 additions & 3 deletions docs/tapes/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ This directory contains [VHS](https://github.com/charmbracelet/vhs) tape files f
|------|---------|--------|
| `demo.tape` | Main demo GIF | `docs/images/demo.gif` |
| `themes.tape` | Theme screenshots | `docs/images/theme-*.png` |
| `theme-light.tape` | Light theme (white bg) | `docs/images/theme-light.png` |
| `features.tape` | Feature screenshots | `docs/images/*.png` |
| `command-mode.tape` | Command suggestions/completion | `docs/images/cmd-*.png` |

## Usage (Recommended)

Expand All @@ -19,9 +21,14 @@ Use task commands from project root (requires Docker + Linux):
task demo:record

# Record individual items
task demo:record:gif # Main demo GIF only
task demo:record:themes # Theme screenshots only
task demo:record:features # Feature screenshots only
task demo:record:gif # Main demo GIF only
task demo:record:themes # Theme screenshots only
task demo:record:theme-light # Light theme (requires white terminal bg)
task demo:record:features # Feature screenshots only
task demo:record:command-mode # Command mode tests

# Run all tapes as integration tests
task test:vhs
```

This automatically:
Expand Down
84 changes: 84 additions & 0 deletions docs/tapes/command-mode.tape
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Command Mode Suggestion & Completion Test
# Tests command mode navigation, suggestions, tab completion, and enter behavior

Set FontSize 16
Set Width 1200
Set Height 600
Set TypingSpeed 0.08

Type "./claws"
Enter
Sleep 2s
Require "Services"

# --- Suggestion Tests ---

# ec → ec2 | ecr | ecs
Type ":"
Sleep 300ms
Type "ec"
Sleep 500ms
Require "ec2"
Require "ecr"
Require "ecs"
Screenshot docs/images/cmd-suggest-ec.png

# ec2 → ec2 (resolved)
Type "2"
Sleep 500ms
Screenshot docs/images/cmd-suggest-ec2.png

# ec2/ → ec2 | ec2/capacity-reservations | ...
Type "/"
Sleep 500ms
Require "ec2/capacity"
Screenshot docs/images/cmd-suggest-ec2-slash.png

# ec2/c → ec2/capacity-reservations
Type "c"
Sleep 500ms
Require "capacity-reservations"
Screenshot docs/images/cmd-suggest-ec2-c.png

Escape
Sleep 300ms

# --- Enter Navigation Tests ---

# ec Enter → ec2 service
Type ":ec"
Sleep 300ms
Enter
Sleep 2s
Require "ec2"

# ec2/ Enter → ec2 service
Type ":ec2/"
Sleep 300ms
Enter
Sleep 2s
Require "ec2"

# ec2/c Enter → ec2/capacity-reservations
Type ":ec2/c"
Sleep 300ms
Enter
Sleep 2s
Require "Capacity"

# --- Tab Completion Test ---

# ec2/c Tab → completes to ec2/capacity-reservations
Type ":"
Sleep 300ms
Type "ec2/c"
Sleep 300ms
Tab
Sleep 500ms
Require "ec2/capacity-reservations"
Screenshot docs/images/cmd-tab-completion.png
Escape
Sleep 300ms

Type "q"
Sleep 500ms
Loading