Skip to content

Fix no instances error#28

Merged
ivyleavedtoadflax merged 1 commit intomainfrom
fix-no-instances-bug
Jan 12, 2023
Merged

Fix no instances error#28
ivyleavedtoadflax merged 1 commit intomainfrom
fix-no-instances-bug

Conversation

@nsorros
Copy link
Collaborator

@nsorros nsorros commented Dec 2, 2022

Fixes #3

@nsorros nsorros changed the title Remove width calculation and rely on default auto Fix no instances error Dec 2, 2022
@nsorros
Copy link
Collaborator Author

nsorros commented Jan 9, 2023

@ivyleavedtoadflax can you have a look here?

@ivyleavedtoadflax ivyleavedtoadflax merged commit e1b0ce9 into main Jan 12, 2023
@ivyleavedtoadflax ivyleavedtoadflax deleted the fix-no-instances-bug branch January 12, 2023 11:43
ivyleavedtoadflax pushed a commit that referenced this pull request Jan 18, 2026
- Add epilog with usage hint to main Typer app
- Fix empty description for `type` command
- Improve and standardize docstrings across all modules
- Add examples to complex commands (connect, launch, ami create, etc.)
- Standardize docstring format: brief one-line description followed by details
- Update issue-28 and issue-29 spec files with completed status

Closes #28

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
ivyleavedtoadflax added a commit that referenced this pull request Jan 18, 2026
* docs: Add v0.4.0 remaining work spec

Track open GitHub issues and remaining work after v0.3.0 release:
- Critical bugs: read_config parameter, create-snapshot validation
- Security: SSH StrictHostKeyChecking
- Code quality: type hints, pagination, dependency injection

* fix: Use config_path parameter in read_config() (#51)

Previously read_config() ignored the config_path parameter and always
used the global CONFIG_PATH. This fix ensures the function uses the
provided parameter, allowing custom config paths to work correctly.

- Changed CONFIG_PATH to config_path in read_config()
- Updated test to verify the parameter is used

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: Add input validation for create-snapshot command (#15)

The create-snapshot command previously crashed with ParamValidationError
when required options were missing. This fix:

- Makes --volume-id and --name required options (using typer.Option(...))
- Sets description default to empty string instead of None
- Adds short aliases -v, -n, -d for the options
- Adds tests to verify missing required options produce helpful errors

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* security: Change SSH default to StrictHostKeyChecking=accept-new (#54)

The previous default of StrictHostKeyChecking=no was vulnerable to
MITM attacks. This fix:

- Changes default to accept-new (accepts new keys, rejects changed keys)
- Adds --no-strict-host-key flag for legacy behavior when needed
- Adds tests for both default and flag behaviors

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs: Update v0.4.0 spec with completed items

Mark the following issues as completed:
- Issue #51 (partial): read_config() parameter bug fixed
- Issue #15: create-snapshot input validation completed
- Issue #54 (partial): SSH StrictHostKeyChecking=accept-new implemented

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat: Add comprehensive type hints and mypy configuration (#52)

- Add mypy configuration to pyproject.toml with strict type checking
- Add boto3-stubs for EC2/ECS/STS type annotations
- Add type hints to all functions and methods
- Fix type compatibility issues with boto3 typed responses
- Add mypy type checking to CI pipeline
- Update AMI create to provide sensible defaults when name/description not provided
- Use typing.cast for wasabi.table aligns parameter (no proper stubs)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat: Implement AWS API pagination for list operations

- Add pagination support to get_instances() in utils.py
- Add pagination support to get_all_clusters() in ecs.py
- Add pagination support to get_all_services() in ecs.py
- Use boto3 paginators to handle >100 items
- Update tests to mock paginators

This allows the CLI to handle accounts with large numbers of
instances, clusters, or services without missing results.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor: Implement dependency injection for AWS clients (#53)

- Add get_ec2_client() function with lru_cache for lazy initialization
- Add get_sts_client() function with lru_cache for lazy initialization
- Add get_ecs_client() function with lru_cache for lazy initialization
- Add TYPE_CHECKING imports for type annotations
- Keep backwards compatible ec2_client/ecs_client aliases

This allows for:
- Lazy initialization of AWS clients (deferred until first use)
- Easier testing by allowing function-level mocking
- Cached clients for reuse across multiple calls

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs: Update spec with review findings and fix lazy client initialization

- Updated v0.4.0 spec to mark completed items (type hints, pagination, DI)
- Added 8 new issues discovered during code review:
  - HIGH: Logic bug in get_instance_by_name(), SSH subprocess error handling,
    unvalidated array index in AMI launch
  - MEDIUM: Deprecated datetime API, inconsistent output/exit patterns
  - LOW: Function shadowing builtin, test coverage improvements

- Implemented lazy client initialization using module __getattr__ for
  backwards compatibility with ec2_client and ecs_client module-level
  attributes
- Updated all source code to use get_ec2_client() and get_ecs_client()
  directly for consistent behavior
- Fixed all test mocks to properly patch getter functions where they are
  used, not where they are defined
- Added AWS_DEFAULT_REGION environment variable in conftest.py to enable
  boto3 client creation during test collection

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs: Refactor specs into modular issue files

- Replace monolithic v0.4.0-remaining-work.md with index and individual specs
- Create specs/readme.md as simple instruction index
- Create separate spec files for each remaining issue (13-20)
- Organize by priority (High/Medium/Low)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs: Add issue-21 spec to replace wasabi with rich

- Add spec for replacing wasabi table formatting with rich library
- Include table styling guidelines and status color coding
- Update specs/readme.md index

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs: Add v0.5.0 feature specs

- issue-22: Instance pricing with AWS Price List API
- issue-23: Package rename from remotepy to remote
- issue-24: Pydantic config validation with env var support
- issue-25: Contributing guide with PR/issue templates

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* chore: Remove accidental swap file

* docs: Add issue-26 spec for template workflow improvements

Analyzes current template workflow in ami.py and instance.py.
Proposes improvements including:
- Moving list_launch_templates() to utils.py (DRY)
- Adding default_launch_template config option
- Enhanced template listing with filtering and details
- New commands: list-templates, template-versions, template-info
- Better interactive selection UX

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs: Add specs for config, help, and subcommand structure

- issue-27: Config workflow improvements (set/get/unset commands, init wizard)
- issue-28: CLI help documentation improvements
- issue-29: Subcommand compartmentalization (remote instance prefix)
- Updated readme with recommended issue order by phase

Also fixed lazy client initialization in snapshot.py and volume.py
to use get_ec2_client() instead of ec2_client module attribute.
Updated corresponding test files with proper mock patterns.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: Change break to continue in get_instance_info() to prevent early loop exit

Previously, when encountering an instance without a Name tag in
get_instance_info(), the code would break out of the loop entirely,
preventing subsequent named instances in the same reservation from
being found. This changes the break to continue so all instances
are properly checked.

Added regression test to verify nameless instances don't block
finding valid instances that come after them in the same reservation.

Fixes #13

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: Add error handling for SSH subprocess in connect command

Add try-except block around subprocess.run() for SSH connections to:
- Report non-zero exit codes from SSH
- Handle FileNotFoundError when SSH client is not installed
- Handle OSError for connection issues

Also adds 4 new tests covering these SSH failure scenarios.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: Add bounds checking for array access in AMI launch template selection

Validate user input when selecting launch templates by number to prevent
IndexError. Uses validate_array_index() from validation module to ensure
the selection is within valid bounds.

Closes #15

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs: Mark issue-15 as completed

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: Replace deprecated datetime.utcfromtimestamp() with timezone-aware alternative

Use datetime.fromtimestamp(..., tz=timezone.utc) instead of the deprecated
utcfromtimestamp() method which will be removed in a future Python version.

Closes #16

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs: Mark issue-16 as completed

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor: Standardize exit patterns to use typer.Exit

- Replace sys.exit(1) with raise typer.Exit(1) in instance.py
- Remove unused sys import
- Remove dead typer.Exit(0) code in __main__.py version command

Closes #18

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs: Mark issue-18 as completed

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor: Rename list functions to avoid shadowing Python builtin

Rename list functions to more descriptive names while keeping CLI
command names as "list" and "ls":
- instance.py: list -> list_instances
- ami.py: list -> list_amis
- snapshot.py: list -> list_snapshots
- volume.py: list -> list_volumes

Closes #19

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs: Mark issue-19 as completed

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor: Replace wasabi with rich for table formatting

- Remove wasabi dependency, add rich
- Update all table formatting to use rich.Table
- Add status color coding (running=green, stopped=red, etc.)
- Use Console with wide width to prevent truncation in tests
- Convert datetime objects to strings for rich rendering

Closes #21

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs: Mark issue-21 as completed

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor: Replace print() with typer.secho() in config.py for consistent output

Use typer.secho() with yellow color for warning messages to match
the output patterns used in the rest of the codebase.

Closes #17

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs: Mark issue-17 as completed

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs: Add help text to subcommand groups in CLI

Add descriptive help text to all subcommand groups (ami, config,
snapshot, volume, ecs) to improve discoverability and user experience.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat: Add instance subcommand group with backward compatibility

- Create new main Typer app instead of using instance_app directly
- Copy instance commands to root level for backward compatibility
- Register instance_app as explicit 'instance' subcommand
- Add tests for both command paths (root and instance prefix)

Both `remote start` and `remote instance start` now work.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* chore: Update ralph prompt

* docs: Add issue-30 for removing root-level instance commands

Breaking change planned for v1.0.0 to clean up the CLI help output
by requiring the `instance` prefix for all instance commands.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat: Improve CLI help documentation

- Add epilog with usage hint to main Typer app
- Fix empty description for `type` command
- Improve and standardize docstrings across all modules
- Add examples to complex commands (connect, launch, ami create, etc.)
- Standardize docstring format: brief one-line description followed by details
- Update issue-28 and issue-29 spec files with completed status

Closes #28

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat: Improve config workflow with new commands

Add new config management commands:
- set: Set configuration values with validation
- get: Get single values (script-friendly, no formatting)
- unset: Remove configuration values
- init: Guided first-time setup wizard
- validate: Validate config file and check SSH key paths
- keys: List all valid configuration keys

Also adds:
- VALID_KEYS constant with supported config options
- Generic get_value/set_value/remove_value methods in ConfigManager
- Comprehensive tests for all new commands (12 new tests)

Closes #27

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat: Improve launch template workflow with better commands and DRY code

- Move get_launch_templates() to utils.py to remove duplication
- Add get_launch_template_versions() utility function
- Add --filter and --details options to list-templates command
- Add template-versions command to show version history
- Add template-info command to show detailed template configuration
- Update launch commands to use default_launch_template from config
- Update tests to use new utility function mocking

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* test: Add edge case tests for pagination and client caching

- Add TestPaginationEdgeCases class with tests for:
  - Empty pagination responses
  - Multiple pages of results
  - Multiple empty pages
  - Mixed empty and populated pages
  - Pagination with exclude_terminated filter
- Add TestClientCaching class with tests for:
  - EC2 client caching behavior
  - STS client caching behavior
  - Cache clearing creates new client

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs: Add contributing guide and GitHub templates

- Add CONTRIBUTING.md with development setup, code style, and PR process
- Add PR template with checklist for tests, linting, and types
- Add issue templates for bug reports and feature requests
- Add badges to README (tests, Python version, license)
- Mark issue-25 as COMPLETED

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* test: Add tests for ami.py to reach 85% coverage

- Add tests for list-templates with --details flag
- Add tests for launch with default template from config
- Add tests for launch when no templates found
- Add tests for template-versions command
- Add tests for template-info command
- Remove unrecognized coverage_thresholds config

Coverage increased from 78.8% to 85.2%

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat: Add instance pricing to list command (#22)

Add pricing information (hourly and monthly estimates) to the `remote list`
command output using the AWS Pricing API.

Changes:
- Add new `remotepy/pricing.py` module with AWS Pricing API integration
- Cache pricing data using lru_cache to minimize API calls
- Add `--no-pricing` flag to skip pricing lookup for faster listing
- Handle unavailable pricing gracefully (shows "-" when price unknown)
- Support 17 common AWS regions with location name mapping

The pricing API is queried from us-east-1 (only available region) and
prices are cached per instance type/region combination.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor: Rename package from remotepy to remote (#23)

Rename the package directory from `remotepy/` to `remote/` to match the CLI
command name. This eliminates confusion between the package name and the
CLI command.

Changes:
- Rename `remotepy/` directory to `remote/`
- Update all imports in source files (from remotepy.* to remote.*)
- Update all imports in test files
- Update pyproject.toml entry points and build configuration
- Update coverage configuration

The PyPI distribution name remains "remotepy" for backwards compatibility.
All 314 tests pass after the rename.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* test: Update mypy and pytest targets

* docs: Add status columns to spec tables and issue 31

- Add status column to all tables in specs/readme.md
- Add issue-31 spec for SSH key config not used by connect command
- Add coverage reporting to pytest pre-push hook (--cov with skip-covered)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs: Add v1.0.0 release specs (issues 32, 33, 34)

- Issue 32: Rich output enhancements (tables, panels for ECS, config)
- Issue 33: v1.0.0 release preparation checklist
- Issue 34: Comprehensive security review
- Add Phase 7 (v1.0.0 Release) to recommended order
- Update priority index with new issues

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* chore: Add security checks to pre-push hooks

- Add mypy for type checking
- Add bandit for static security analysis (skip B311, B404, B603)
- Add pip-audit for dependency vulnerability scanning
- Fix vulnerable deps: filelock, urllib3, virtualenv
- Update package path from remotepy/ to remote/

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* specs: Update specs to include security scans

* feat: Connect command uses ssh_key from config

The connect command now checks for a configured ssh_key value when
the --key option is not provided. This allows users to set a default
SSH key in their config file that will be used automatically.

- Add config fallback for ssh_key in connect()
- Update help text to mention config fallback
- Add tests for config ssh_key usage
- Fix pre-push coverage config to use correct package name

Closes #31

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat: Enhance output with Rich formatting

Add Rich tables and panels for improved UX in several areas:

- ECS: cluster and service selection now uses Rich tables with
  extracted names from ARNs
- Config: validation results displayed in Rich panel with colored
  status indicators
- Instance/AMI: launch summary displayed in Rich panel with
  instance details

Updated tests to account for new Rich formatting output.

Closes #32

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs: Complete security review for v1.0.0

Conduct comprehensive security review covering:
- Credential handling: Uses boto3 credential chain, no hardcoded secrets
- Input validation: Array bounds checking, path sanitization
- SSH security: No shell injection, proper subprocess handling
- File system security: Config in ~/.config/, proper path handling
- Subprocess security: List arguments, no shell=True
- Dependency security: pip-audit and bandit pass
- Error handling: No sensitive data in error messages

Add SECURITY.md with:
- Security reporting process
- Security measures documentation
- Accepted risks with justification

Closes #34

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat!: Remove root-level instance commands (BREAKING CHANGE)

Remove backwards compatibility for root-level instance commands.
Instance commands now require the 'instance' prefix:

- `remote start` -> `remote instance start`
- `remote stop` -> `remote instance stop`
- `remote connect` -> `remote instance connect`
- `remote list` -> `remote instance list`

This provides a cleaner CLI structure with no duplicate commands
in the help output.

BREAKING CHANGE: Root-level instance commands removed. Use
`remote instance <command>` instead.

Closes #30

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* chore: Prepare v1.0.0 release

- Bump version to 1.0.0
- Update development status to Production/Stable
- Add CHANGELOG.md with complete version history
- Update README with migration guide and v1.0.0 command syntax
- Update test count references to 317+

This marks the first stable release with:
- Complete security review
- All planned features implemented
- Breaking change to require 'instance' prefix for commands
- Comprehensive test coverage

Closes #33

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Ubuntu <ubuntu@ip-172-31-41-169.eu-west-1.compute.internal>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
ivyleavedtoadflax added a commit that referenced this pull request Jan 18, 2026
The loop index was unused, making enumerate() unnecessary.
Simplified to a plain for loop over reservations.

Co-authored-by: Claude <noreply@anthropic.com>
ivyleavedtoadflax added a commit that referenced this pull request Jan 18, 2026
The loop index was unused, making enumerate() unnecessary.
Simplified to a plain for loop over reservations.

Co-authored-by: Claude <noreply@anthropic.com>
(cherry picked from commit b37effb)
ivyleavedtoadflax added a commit that referenced this pull request Jan 18, 2026
* feat: Add Pydantic config validation with environment variable support

- Add pydantic-settings dependency for config validation
- Create RemoteConfig Pydantic model with field validators:
  - instance_name: alphanumeric, hyphens, underscores, dots
  - ssh_user: alphanumeric, hyphens, underscores
  - ssh_key_path: expands ~ to home directory
  - aws_region: validates AWS region format (e.g., us-east-1)
- Support environment variable overrides (REMOTE_ prefix)
- Create ConfigValidationResult for structured validation output
- Update ConfigManager to use Pydantic validation internally
- Enhance 'remote config validate' command with Pydantic validation
- Add 25 new tests for Pydantic config features
- Fix specs/readme.md: mark issue-23 as COMPLETED, update mypy path

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
(cherry picked from commit 1f56cba)

* feat: Add built-in watch mode for instance status command

Add --watch/-w and --interval/-i flags to the status command to enable
continuous monitoring of instance status using Rich's Live display.
This resolves garbled output issues when using the external `watch`
command with Rich formatting.

- Add _build_status_table helper function for reusable table generation
- Add _watch_status function using Rich Live display with screen mode
- Validate interval must be at least 1 second
- Handle Ctrl+C gracefully to exit watch mode
- Add comprehensive tests for watch mode functionality

Closes #35

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
(cherry picked from commit d2ccacc)

* refactor: Remove unused cfg parameter from get_instance_name()

- Remove unused `cfg: ConfigParser | None = None` parameter from get_instance_name()
- Remove corresponding docstring documentation for the parameter
- Remove now-unused `from configparser import ConfigParser` import

The parameter was marked as "for backward compatibility" but was never used
in the function body (it always used config_manager instead), and none of
the 8 call sites passed any arguments.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
(cherry picked from commit 24a886a)

* fix: Use correct config key ssh_key_path in connect()

The connect() function was using "ssh_key" as the config key when
retrieving the SSH key path, but the valid config key is "ssh_key_path".
This caused the SSH key configuration to fail silently.

- Fix get_value() call to use "ssh_key_path" instead of "ssh_key"
- Update help text to reference the correct config key name

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
(cherry picked from commit d9b35f5)

* docs: Add issue 36 for config validate panel width

Panel stretches beyond console width and has redundant messaging.

(cherry picked from commit 9f3116b)

* refactor: Remove unnecessary builtins import from instance.py (#18)

The builtins module was imported only to use builtins.list for a type
annotation. In Python 3.9+, list can be used directly in type annotations
without the builtins prefix. This change removes the unnecessary import
and simplifies the type annotation.

Co-authored-by: Claude <noreply@anthropic.com>
(cherry picked from commit 1fc7119)

* refactor: Remove unused Typer app instance from utils.py

The utils.py module defined `app = typer.Typer()` but this app instance
was never used - no commands were registered to it and no other modules
imported it. The typer import itself is still needed for other uses
(typer.Exit, typer.secho, typer.colors).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
(cherry picked from commit f57850d)

* refactor: Use cached get_sts_client() in get_account_id()

The get_sts_client() function was defined as a cached client factory but
was never used. The get_account_id() function created a new STS client
directly with boto3.client("sts") instead.

This change makes the code consistent with the EC2 client pattern where
get_ec2_client() is used throughout the codebase, and utilizes the
caching provided by @lru_cache.

Also updates tests to mock get_sts_client instead of boto3.client.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
(cherry picked from commit 8daac71)

* docs: Add issues 37-38 for pricing improvements

- Issue 37: Fallback to us-east-1 for pricing API in other regions
- Issue 38: Add command to show instance cost based on uptime

(cherry picked from commit 55af72a)

* fix: Remove hardcoded console width and simplify validate output

- Remove width=200 from Console initialization in config.py to use
  terminal's actual width instead of stretching beyond it
- Simplify validation output to show single status message instead
  of redundant "All checks passed" + "Status: Valid"
- Update test assertion to match new output message

Closes #36

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
(cherry picked from commit acd655a)

* docs: Add issue 39 for scheduled instance shutdown

Add spec for feature to schedule instance stops after a duration,
e.g., `remote instance stop --in 3h`

(cherry picked from commit 01adf6b)

* docs: Update issue 39 to use remote shutdown command

Use SSH to run `shutdown -h +N` on the instance instead of a
local subprocess. This is simpler and survives local disconnects.

(cherry picked from commit f474c02)

* feat: Add region fallback for pricing API (#22)

When a user's region is not in the region-to-location mapping, pricing
lookups now fall back to us-east-1 instead of returning None. This
provides users in less common regions with an estimated price rather
than no price at all.

- Add get_instance_price_with_fallback() function that returns (price, fallback_used)
- Update get_instance_pricing_info() to include fallback_used indicator
- Update instance list command to use fallback pricing
- Add comprehensive tests for fallback behavior

Closes #37

Co-authored-by: Claude <noreply@anthropic.com>
(cherry picked from commit 875cc9d)

* feat: Add scheduled instance shutdown via SSH

Add --in option to stop command to schedule shutdown after duration
Add --stop-in option to start command to auto-stop after duration
Add --cancel flag to cancel scheduled shutdowns

Features:
- Parse duration strings (e.g., 3h, 30m, 1h30m)
- SSH to instance and run 'shutdown -h +N'
- Uses ssh_user and ssh_key_path from config
- Handles SSH errors gracefully

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
(cherry picked from commit 32d8144)

* docs: Add issue 40 for console output consistency

Standardize all command output styles around `config show` format.

(cherry picked from commit a8bb264)

* feat: Standardize console output styles for ECS commands

Update ECS list commands to use Rich Tables instead of plain line-by-line
output, matching the consistent style used across other modules.

Changes:
- list-clusters: Now displays clusters in a Rich Table with name and ARN
- list-services: Now displays services in a Rich Table with name and ARN
- prompt_for_cluster_name: Changed typer.echo to typer.secho for consistency
- prompt_for_services_name: Changed typer.echo to typer.secho for consistency

Closes #40

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
(cherry picked from commit 8adb22f)

* feat: Add instance cost command to show estimated cost based on uptime (#25)

Adds a new `remote instance cost` command that displays the estimated cost
of a running instance based on its uptime and hourly pricing rate.

Features:
- Shows instance ID, type, status, launch time, and uptime
- Calculates estimated cost using hourly rate × uptime hours
- Uses fallback to us-east-1 pricing for unsupported regions
- Handles non-running instances and unavailable pricing gracefully

Closes #38

Co-authored-by: Claude <noreply@anthropic.com>
(cherry picked from commit ab6e4f9)

* docs: Add issues 41-42 for cost fixes and ls/status clarification

Issue 41: Fix instance cost (not displaying, panel too wide, integrate into ls)
Issue 42: Evaluate overlap between instance ls and status commands

(cherry picked from commit 7c6af04)

* docs: Add testing requirements for issue 41

Emphasize need for Typer CLI tests to catch cost display issues.

(cherry picked from commit 88852c7)

* feat: Integrate cost columns into instance ls with --cost flag (#41)

- Add --cost/-c flag to instance ls to show cost columns
- Add Uptime, $/hr, and Est. Cost columns when --cost is used
- Remove separate instance cost command (functionality now in ls)
- Remove _get_instance_details helper (no longer needed)
- Add _get_raw_launch_times helper for extracting launch times
- Add comprehensive tests for cost flag functionality
- Update plan.md and spec status to COMPLETED

The cost information is now opt-in rather than shown by default,
which improves performance since pricing API calls are skipped
unless explicitly requested.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
(cherry picked from commit 3980be0)

* docs: Reopen issue 41 - cost still not displaying

PR #26 did not fix the pricing lookup issue. Cost shows "-" in
real usage despite tests passing. Need to investigate mismatch
between mocked tests and actual AWS pricing API behavior.

(cherry picked from commit fccab83)

* feat: Differentiate instance ls and status commands (#42) (#27)

Clarify the distinct purposes of instance ls (summary view of all instances)
vs instance status (detailed view of one instance).

Changes:
- Enhanced instance status to show comprehensive details including network
  config, security groups, key pair, tags, and health status
- Updated help text for both commands to clearly indicate when to use each
- instance status now uses a Rich Panel instead of Table for better formatting
- Health status section only shown for running instances

Co-authored-by: Claude <noreply@anthropic.com>
(cherry picked from commit d3093e7)

* refactor: Remove unnecessary enumerate() in get_instance_ids() (#28)

The loop index was unused, making enumerate() unnecessary.
Simplified to a plain for loop over reservations.

Co-authored-by: Claude <noreply@anthropic.com>
(cherry picked from commit b37effb)

* refactor: Remove unused drop_nameless parameter from get_instance_info()

The drop_nameless parameter was defined but never used - the function
always skips instances without a Name tag regardless of its value.
This was misleading since the default value of False implied nameless
instances would be included.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
(cherry picked from commit 0d14e97)

* refactor: Remove deprecated ec2_client backwards compatibility shim

The module-level `ec2_client` attribute was deprecated and scheduled
for removal in v0.5.0. After scanning the codebase, no code uses this
deprecated attribute - all modules use `get_ec2_client()` directly.

Remove:
- Deprecation comment block
- `__getattr__` function providing lazy access to `ec2_client`

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
(cherry picked from commit c8885ac)

* refactor: Remove deprecated ecs_client backwards compatibility shim

The __getattr__ function providing lazy access to ecs_client as a
module-level attribute was dead code. All ECS functions use
get_ecs_client() directly, and no imports of ecs_client exist in
the codebase.

Also removes the unused Any type import.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
(cherry picked from commit c361dcb)

* refactor: Remove unused ENV_PREFIX constant from config.py (#32)

The ENV_PREFIX constant was defined but never used. The actual env
prefix is hardcoded in RemoteConfig.model_config as env_prefix="REMOTE_".

Co-authored-by: Claude <noreply@anthropic.com>
(cherry picked from commit aae94bd)

* refactor: Rename in_duration parameter to stop_in for consistency (#33)

The stop() function used parameter name 'in_duration' while the start()
function used 'stop_in' for the same purpose (scheduling automatic
shutdown). This inconsistency created cognitive overhead.

Renamed the parameter to 'stop_in' to match the pattern used in start().
The CLI flag '--in' remains unchanged for backwards compatibility.

Co-authored-by: Claude <noreply@anthropic.com>
(cherry picked from commit 5e34587)

* docs: Add issue 43 for Rich Panel width fix

Recurring issue: Panels expand to full terminal width.
Audit all Panel usage and set expand=False globally.

(cherry picked from commit 209b796)

* refactor: Rename type function and parameter to avoid shadowing built-in (#34)

Rename the `type()` command function to `instance_type()` with
`@app.command("type")` decorator to preserve CLI command name.
Rename the `type` parameter to `new_type` to avoid shadowing
Python's built-in type() function.

Co-authored-by: Claude <noreply@anthropic.com>
(cherry picked from commit 89b9939)

* refactor: Add missing width=200 to Console initialization in config.py

The config module's Console initialization was inconsistent with all other
modules, which specify width=200. This ensures consistent output formatting
across all CLI commands.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
(cherry picked from commit bf38a96)

* refactor: Remove unused is_instance_stopped() function (#36)

The function was defined but never called in production code.
It only had test coverage but no actual usage in the codebase.

Co-authored-by: Claude <noreply@anthropic.com>
(cherry picked from commit 915ec2f)

* fix: Correct EU region location names in pricing API

The AWS Pricing API uses "EU (...)" format for European regions,
not "Europe (...)". This was causing pricing lookups to fail for
all EU regions (eu-west-1, eu-west-2, etc.).

Fixes:
- eu-west-1: "Europe (Ireland)" -> "EU (Ireland)"
- eu-west-2: "Europe (London)" -> "EU (London)"
- eu-west-3: "Europe (Paris)" -> "EU (Paris)"
- eu-central-1: "Europe (Frankfurt)" -> "EU (Frankfurt)"
- eu-north-1: "Europe (Stockholm)" -> "EU (Stockholm)"
- Added eu-south-1: "EU (Milan)"

(cherry picked from commit ae9f89a)

* docs: Update issue 41 with root cause and fix details

Root cause: EU region location names in REGION_TO_LOCATION mapping
used "Europe (...)" format but AWS Pricing API expects "EU (...)".

(cherry picked from commit 9fafbad)

* docs: Add issue 44 for test API validation

Mocked tests can pass while real API fails. Add validation to
ensure test parameters match what AWS actually accepts.

(cherry picked from commit 5ab30ef)

* refactor: Remove duplicate list_launch_templates() from instance.py

The list_launch_templates() function was duplicated in both instance.py
and ami.py. The ami.py version is feature-rich with --filter and
--details options, while the instance.py version was a basic subset.

Remove the duplicate from instance.py as users can use
`remote ami list-templates` which provides the same functionality
plus additional filtering and detailed output capabilities.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
(cherry picked from commit 6712c6a)

* docs: Add issue 45 for v1.1.0 release preparation

Includes checklist for new features (watch mode, scheduled shutdown,
cost display), bug fixes, and release process.

(cherry picked from commit 9a10b7e)

* fix: Set expand=False on all Rich Panels to prevent full-width expansion

All Panel components in the codebase were expanding to fill the terminal
width instead of fitting their content. This fixes recurring issues with
overly wide panels in instance status, config validate, and launch commands.

Changes:
- instance.py: Fixed _build_status_table and launch panels
- config.py: Fixed validate command panel
- ami.py: Fixed launch command panel
- Added test for panel expand=False property

Fixes #43

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
(cherry picked from commit f02aff2)

* test: Add AWS API contract validation tests (#39)

Add validation layer to ensure mocked tests use parameter values that
the real AWS APIs would accept. This prevents situations where tests
pass but real API calls fail (as happened with issue #41 where
"Europe (Ireland)" was used instead of "EU (Ireland)").

Changes:
- Add tests/fixtures/aws_api_contracts.py with known-good AWS values
- Add tests/test_api_contracts.py with 18 contract validation tests
- Document API contract in remote/pricing.py
- Add integration marker to pyproject.toml for optional real API tests

Co-authored-by: Claude <noreply@anthropic.com>
(cherry picked from commit cdb30fe)

* release: Prepare v1.1.0 release (#40)

- Update version in pyproject.toml to 1.1.0
- Add CHANGELOG.md entry for v1.1.0 with new features, fixes, and changes
- Mark issue 45 as COMPLETED in plan.md and spec file

New in v1.1.0:
- Built-in watch mode for status command (--watch flag)
- Scheduled instance shutdown (--in flag for stop, --stop-in for start)
- Cost information in instance list (--cost flag)
- AWS API contract validation tests

Co-authored-by: Claude <noreply@anthropic.com>
(cherry picked from commit 2d72873)

* refactor: Remove unused ConfigurationError exception class (#41)

The ConfigurationError exception class was defined but never raised or
caught anywhere in the codebase. This dead code added unnecessary lines
to the exceptions module with no functional purpose.

Co-authored-by: Claude <noreply@anthropic.com>
(cherry picked from commit 50886f1)

* refactor: Remove unused InvalidInstanceStateError exception class (#42)

Co-authored-by: Claude <noreply@anthropic.com>
(cherry picked from commit 311197f)

* refactor: Extract _build_ssh_command() helper to reduce duplication

The SSH argument building code was duplicated in _schedule_shutdown()
and _cancel_scheduled_shutdown(). Both functions built identical SSH
argument lists with the same options (StrictHostKeyChecking, BatchMode,
ConnectTimeout).

This change extracts the common logic into a new _build_ssh_command()
helper function that:
- Takes dns, key, and user parameters
- Returns a list of SSH command arguments ready for subprocess
- Is reused by both shutdown-related functions

Reduces code duplication by ~14 lines and ensures any future changes
to SSH options only need to be made in one place.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
(cherry picked from commit 62dc280)

* refactor: Consolidate datetime imports to module level in instance.py (#44)

Move datetime imports from inside functions to module level for consistency
with other modules like utils.py. Removes three inline imports from
_get_raw_launch_times, list_instances, and _schedule_shutdown functions.

Co-authored-by: Claude <noreply@anthropic.com>
(cherry picked from commit 9660259)

* refactor: Centralize console initialization in utils.py

Move the shared Console instance to utils.py and have all other modules
import it instead of creating their own instances. This reduces code
duplication and ensures consistent console configuration across all
modules.

Files modified:
- remote/ami.py - Import console from utils
- remote/config.py - Import console from utils
- remote/ecs.py - Import console from utils
- remote/instance.py - Import console from utils (kept Console import
  for _watch_status local usage)
- remote/snapshot.py - Import console from utils
- remote/volume.py - Import console from utils

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
(cherry picked from commit 879337e)

* refactor: Remove redundant Console creation in _watch_status() (#46)

The _watch_status() function created its own Console instance when the
module already imports console from remote.utils. This change:

- Removes local watch_console = Console() in _watch_status()
- Uses the shared console instance from utils instead
- Removes now-unused Console import from rich.console
- Updates test to mock console instead of Console

This completes the console centralization refactor - all modules now
use the shared console instance from remote/utils.py.

Co-authored-by: Claude <noreply@anthropic.com>
(cherry picked from commit 7d639db)

* chore: Add gitleaks to pre-commit hooks for secret detection

Complements existing security tools (bandit, pip-audit) by scanning
for hardcoded secrets before push.

(cherry picked from commit 9843b70)

* refactor: Remove redundant get_instance_type() call in instance_type()

The instance_type() function called get_instance_type() twice to fetch
the same value - once at function start (stored in current_type) and
again in the else branch (stored in current_instance_type). This made
an unnecessary AWS API call since current_type was already available.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
(cherry picked from commit 470c984)

* refactor: Replace overly broad exception handling in list_launch_templates() (#48)

The exception handler `except (ResourceNotFoundError, Exception)` was
catching all exceptions silently, which could mask bugs. Changed to
`except (ResourceNotFoundError, AWSServiceError)` to match the documented
exceptions that get_launch_template_versions() can raise.

Co-authored-by: Claude <noreply@anthropic.com>
(cherry picked from commit c3074d4)

* refactor: Remove misleading return type from list_launch_templates() Typer command (#49)

The function returned a list value that was never consumed by callers since
it's a Typer CLI command. Changed return type to None and removed unused
Any import.

Co-authored-by: Claude <noreply@anthropic.com>
(cherry picked from commit 9816412)

* refactor: Replace overly broad exception handling in config.py (#50)

Replace `except Exception` with `except ValueError` in three locations:
- ConfigValidationResult.validate_config()
- ConfigManager.get_instance_name()
- ConfigManager.get_value()

Pydantic's ValidationError inherits from ValueError, so this catches
validation errors while avoiding the antipattern of catching all
exceptions indiscriminately.

Updated test to use ValueError instead of generic Exception.

Co-authored-by: Claude <noreply@anthropic.com>
(cherry picked from commit c32ab4f)

* refactor: Replace silent exception handler in list_launch_templates()

Changed exception handling in ami.py's list_launch_templates() to display
a warning message instead of silently ignoring errors when fetching
launch template version details.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
(cherry picked from commit bc7a4b5)

* refactor: Extract duplicated launch() logic into shared utility function (#52)

The launch() function was duplicated nearly identically (~130 lines) in both
ami.py and instance.py. This refactor:

- Adds launch_instance_from_template() to utils.py with all common logic
- Simplifies both launch() commands to thin wrappers calling shared function
- Updates test mocks to patch correct modules (remote.utils, remote.config)

Net change: -58 lines of code, single source of truth for launch logic.

Co-authored-by: Claude <noreply@anthropic.com>
(cherry picked from commit 1cff43a)

* refactor: Add explicit exit codes to typer.Exit() calls in ecs.py

Two typer.Exit() calls lacked explicit exit codes:
- prompt_for_cluster_name(): when no clusters found
- prompt_for_services_name(): when no services found

While typer.Exit() defaults to exit code 0, being explicit about
exit codes is best practice and consistent with other exit calls
in the codebase. Exit code 0 is correct here as these are
informational cases, not errors.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
(cherry picked from commit 4b564d6)

* refactor: Standardize docstring formatting in ecs.py

Fix inconsistent docstring formatting to match the style used in
utils.py and other modules:

- Move descriptions to same line as opening triple quotes
- Add proper 4-space indentation to Args/Returns sections
- Remove redundant type annotations from docstrings (types are in
  function signatures)
- Remove type prefixes from Returns sections

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
(cherry picked from commit 27cd751)

* refactor: Standardize Typer parameter style in status() command (#55)

The status() command in instance.py used the Annotated[] style for
parameter type hints while all other commands used the simpler inline
style. This inconsistency made the codebase harder to read and created
confusion about which style to follow.

Changes:
- Convert status() parameters from Annotated[] to inline style
- Remove unused Annotated import from typing

Co-authored-by: Claude <noreply@anthropic.com>
(cherry picked from commit 15b75b6)

* refactor: Remove unused get_instance_pricing_info() function (#56)

The function was dead code - only exercised by tests, never used in
application code. The instance list command uses get_instance_price_with_fallback()
directly rather than this higher-level wrapper.

- Remove get_instance_pricing_info() from remote/pricing.py
- Remove TestGetInstancePricingInfo from tests/test_pricing.py
- Update specs to reflect actual implementation

Co-authored-by: Claude <noreply@anthropic.com>
(cherry picked from commit a50adcf)

* refactor: Standardize ConfigParser variable naming in config.py (#57)

Renamed `cfg` to `config` throughout the file for consistency.
The codebase mixed both names for ConfigParser objects - now
standardized on `config` which is more descriptive and matches
the pattern used in ConfigManager class methods.

Co-authored-by: Claude <noreply@anthropic.com>
(cherry picked from commit 252f41d)

* refactor: Remove unused if __name__ == "__main__" blocks

Remove dead code from five modules that contained unused main blocks:
- remote/ami.py
- remote/config.py
- remote/instance.py
- remote/snapshot.py
- remote/volume.py

These modules are library code imported into __main__.py, not executed
directly. The blocks were never executed since users run `remote <cmd>`
not `python -m remote.instance` etc.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
(cherry picked from commit a618fe7)

* refactor: Remove unused return value from write_config() function

The write_config() function returned its input ConfigParser object,
but no caller ever used the return value. Changed return type to None
and updated the corresponding test.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
(cherry picked from commit 9800551)

* refactor: Remove unused get_snapshot_status() function

The function was defined in utils.py but never called by any production
code. It was only exercised by tests. Removes dead code and associated
tests.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
(cherry picked from commit b06bf72)

* refactor: Remove unused validate_snapshot_id() function

The validate_snapshot_id() function was defined in validation.py but
never called anywhere in the application. Remove this dead code along
with its associated tests to keep the codebase clean.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
(cherry picked from commit fe92d81)

* refactor: Move Terraform comment to be adjacent to its code

Move the "# If the instance is managed by Terraform, warn user" comment
from line 963 to line 981, placing it directly above the terraform_managed
assignment it describes. The comment was previously orphaned from its
relevant code by 20 lines of unrelated confirmation prompts.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
(cherry picked from commit 8a7eb0d)

* refactor: Use config_manager.remove_value() in unset_value command (#63)

The unset_value() CLI command was directly manipulating the config file
instead of using the ConfigManager.remove_value() method like other
similar commands (set_value, add). This violated encapsulation and
missed proper state management (cache invalidation).

Also fixed ConfigManager.remove_value() to read from the specified
config_path parameter instead of the default path.

Co-authored-by: Claude <noreply@anthropic.com>
(cherry picked from commit 8c0f8ca)

* refactor: Simplify config path assignment with ternary operators

Replace verbose if-else blocks with ternary operators in
RemoteConfig.from_ini_file() and ConfigValidationResult.validate_config()
for cleaner, more idiomatic code (SIM108).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
(cherry picked from commit 190b0f5)

* refactor: Remove unused get_monthly_estimate() function and HOURS_PER_MONTH constant (#65)

The function and constant were defined but never used in production code:
- No code called get_monthly_estimate()
- HOURS_PER_MONTH was only used by get_monthly_estimate()
- Similar to previous removal of get_instance_pricing_info()

The application displays hourly prices directly without converting
to monthly estimates.

Co-authored-by: Claude <noreply@anthropic.com>
(cherry picked from commit b55caaf)

* refactor: Extract duplicate exception handling to helper method in ConfigManager (#66)

The get_instance_name() and get_value() methods had identical exception
handling blocks that displayed warnings for various config-related errors.
This duplicated ~12 lines of code.

Changes:
- Add _handle_config_error() helper method to centralize error handling
- Update both methods to use a single except clause delegating to helper
- Use union type syntax (X | Y) in isinstance checks per UP038 lint rule

Co-authored-by: Claude <noreply@anthropic.com>
(cherry picked from commit dc66c51)

* refactor: Fix inconsistent filtering in get_instance_ids()

The get_instance_ids() function had inconsistent filtering behavior
compared to get_instance_info():

- get_instance_info() iterates through ALL instances and filters out
  those without a Name tag
- get_instance_ids() only took the FIRST instance from each reservation
  and did NOT filter by Name tag

This could cause array length mismatches when used together. The code
worked around this with strict=False in zip() calls, silently truncating
to the shortest array.

Changes:
- Update get_instance_ids() to iterate all instances and filter by Name tag
- Change strict=False to strict=True in zip calls in instance.py and config.py
- Add test for the new filtering behavior

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
(cherry picked from commit 16147a7)

* refactor: Fix get_value CLI command to use ConfigManager consistently (#68)

The get_value() CLI command bypassed ConfigManager.get_value() and read
directly from config file. This was inconsistent with other CLI commands
(set_value, add, unset_value) which properly use ConfigManager.

Changes:
- Renamed function to get_value_cmd to avoid shadowing
- Added key validation against VALID_KEYS (consistent with set_value)
- For default path: delegate to config_manager.get_value()
- For custom paths: continue reading directly from file

Benefits:
- Pydantic validation for config values
- REMOTE_* environment variable override support
- Key validation (rejects unknown keys)
- Consistent API with other config commands

Co-authored-by: Claude <noreply@anthropic.com>
(cherry picked from commit 3bec8ed)

* refactor: Extract hardcoded time constants in instance.py (#69)

Replace magic numbers with named constants for better readability:
- SECONDS_PER_MINUTE, SECONDS_PER_HOUR, MINUTES_PER_DAY
- MAX_STARTUP_WAIT_SECONDS, STARTUP_POLL_INTERVAL_SECONDS
- CONNECTION_RETRY_SLEEP_SECONDS, MAX_CONNECTION_ATTEMPTS

Co-authored-by: Claude <noreply@anthropic.com>
(cherry picked from commit f4640f9)

* refactor: Add MINUTES_PER_HOUR constant for semantic correctness

The _format_uptime() function used SECONDS_PER_MINUTE (60) to perform
arithmetic on values measured in minutes. While mathematically correct,
this was semantically misleading. Added MINUTES_PER_HOUR constant and
updated MINUTES_PER_DAY to use it for consistency.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
(cherry picked from commit 9144511)

* refactor: Extract SSH readiness sleep to constant (#71)

Add SSH_READINESS_WAIT_SECONDS constant (10s) for the hardcoded
sleep times used when waiting for SSH to become ready after
instance startup. This follows the established pattern of
extracting time-related magic numbers to named constants.

Co-authored-by: Claude <noreply@anthropic.com>
(cherry picked from commit ef46b1a)

* refactor: Extract type change polling magic numbers to constants

Add TYPE_CHANGE_MAX_POLL_ATTEMPTS and TYPE_CHANGE_POLL_INTERVAL_SECONDS
constants to replace hardcoded `5` values in instance_type() function.
This follows the established pattern for time-related constants.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
(cherry picked from commit 468117d)

* docs: Add issue 46 for connect stopped instance behavior (GitHub #73)

(cherry picked from commit 8c0b1bf)

* feat: Add --start and --no-start flags to connect command (GitHub #73)

When connecting to a stopped instance:
- --start: Automatically starts the instance without prompting
- --no-start: Fails immediately with a helpful message
- Non-interactive mode (no TTY): Fails with helpful message

Also:
- Refactored start command to extract _start_instance() internal function
- Added comprehensive tests for new behavior
- Fixed typo: "trying to starting" -> "trying to start"

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
(cherry picked from commit 48f9a1d)

---------

Co-authored-by: Claude <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.

Error if no aws profile (i think)

2 participants