cloudx-proxy 0.17.0__tar.gz → 0.17.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. {cloudx_proxy-0.17.0 → cloudx_proxy-0.17.2}/.ai/context/development.md +1 -1
  2. {cloudx_proxy-0.17.0 → cloudx_proxy-0.17.2}/.ai/context/project-overview.md +3 -2
  3. cloudx_proxy-0.17.2/.github/workflows/test.yml +65 -0
  4. {cloudx_proxy-0.17.0 → cloudx_proxy-0.17.2}/.gitignore +1 -3
  5. {cloudx_proxy-0.17.0 → cloudx_proxy-0.17.2}/CHANGELOG.md +16 -0
  6. {cloudx_proxy-0.17.0 → cloudx_proxy-0.17.2}/CLAUDE.md +14 -1
  7. cloudx_proxy-0.17.2/CONTRIBUTING.md +57 -0
  8. {cloudx_proxy-0.17.0 → cloudx_proxy-0.17.2}/PKG-INFO +17 -3
  9. {cloudx_proxy-0.17.0 → cloudx_proxy-0.17.2}/README.md +16 -2
  10. cloudx_proxy-0.17.2/cloudx_proxy/__init__.py +31 -0
  11. cloudx_proxy-0.17.0/cloudx_proxy/_1password.py → cloudx_proxy-0.17.2/cloudx_proxy/_op.py +34 -42
  12. {cloudx_proxy-0.17.0 → cloudx_proxy-0.17.2}/cloudx_proxy/_version.py +2 -2
  13. {cloudx_proxy-0.17.0 → cloudx_proxy-0.17.2}/cloudx_proxy/cli.py +84 -57
  14. {cloudx_proxy-0.17.0 → cloudx_proxy-0.17.2}/cloudx_proxy/colors.py +1 -14
  15. {cloudx_proxy-0.17.0 → cloudx_proxy-0.17.2}/cloudx_proxy/core.py +42 -26
  16. {cloudx_proxy-0.17.0 → cloudx_proxy-0.17.2}/cloudx_proxy/setup.py +771 -338
  17. {cloudx_proxy-0.17.0 → cloudx_proxy-0.17.2}/cloudx_proxy.egg-info/PKG-INFO +17 -3
  18. {cloudx_proxy-0.17.0 → cloudx_proxy-0.17.2}/cloudx_proxy.egg-info/SOURCES.txt +10 -2
  19. {cloudx_proxy-0.17.0 → cloudx_proxy-0.17.2}/pyproject.toml +23 -0
  20. cloudx_proxy-0.17.2/tests/test_backward_compat.py +334 -0
  21. cloudx_proxy-0.17.2/tests/test_cli_options.py +65 -0
  22. cloudx_proxy-0.17.2/tests/test_config_safety.py +287 -0
  23. cloudx_proxy-0.17.2/tests/test_core.py +157 -0
  24. cloudx_proxy-0.17.2/tests/test_non_interactive.py +166 -0
  25. cloudx_proxy-0.17.2/tests/test_runtime_safety.py +263 -0
  26. {cloudx_proxy-0.17.0 → cloudx_proxy-0.17.2}/tests/test_setup.py +5 -5
  27. cloudx_proxy-0.17.2/tests/test_ssh_config.py +470 -0
  28. cloudx_proxy-0.17.2/tests/test_version.py +73 -0
  29. {cloudx_proxy-0.17.0 → cloudx_proxy-0.17.2}/uv.lock +30 -3
  30. cloudx_proxy-0.17.0/.github/workflows/test.yml +0 -39
  31. cloudx_proxy-0.17.0/CONTRIBUTING.md +0 -29
  32. cloudx_proxy-0.17.0/cloudx_proxy/__init__.py +0 -3
  33. {cloudx_proxy-0.17.0 → cloudx_proxy-0.17.2}/.ai/README.md +0 -0
  34. {cloudx_proxy-0.17.0 → cloudx_proxy-0.17.2}/.ai/context/README.md +0 -0
  35. {cloudx_proxy-0.17.0 → cloudx_proxy-0.17.2}/.ai/context/architecture.md +0 -0
  36. {cloudx_proxy-0.17.0 → cloudx_proxy-0.17.2}/.ai/context/commit-conventions.md +0 -0
  37. {cloudx_proxy-0.17.0 → cloudx_proxy-0.17.2}/.ai/context/ssh-config.md +0 -0
  38. {cloudx_proxy-0.17.0 → cloudx_proxy-0.17.2}/.ai/roadmap/architecture-review.md +0 -0
  39. {cloudx_proxy-0.17.0 → cloudx_proxy-0.17.2}/.ai/roadmap/documentation-findings.md +0 -0
  40. {cloudx_proxy-0.17.0 → cloudx_proxy-0.17.2}/.ai/roadmap/improvement-roadmap.md +0 -0
  41. {cloudx_proxy-0.17.0 → cloudx_proxy-0.17.2}/.clinerules +0 -0
  42. {cloudx_proxy-0.17.0 → cloudx_proxy-0.17.2}/.envrc +0 -0
  43. {cloudx_proxy-0.17.0 → cloudx_proxy-0.17.2}/.github/dependabot.yml +0 -0
  44. {cloudx_proxy-0.17.0 → cloudx_proxy-0.17.2}/.github/workflows/claude.yml +0 -0
  45. {cloudx_proxy-0.17.0 → cloudx_proxy-0.17.2}/.github/workflows/codeql.yml +0 -0
  46. {cloudx_proxy-0.17.0 → cloudx_proxy-0.17.2}/.github/workflows/release.yml +0 -0
  47. {cloudx_proxy-0.17.0 → cloudx_proxy-0.17.2}/.releaserc +0 -0
  48. {cloudx_proxy-0.17.0 → cloudx_proxy-0.17.2}/LICENSE +0 -0
  49. {cloudx_proxy-0.17.0 → cloudx_proxy-0.17.2}/NOTICE +0 -0
  50. {cloudx_proxy-0.17.0 → cloudx_proxy-0.17.2}/cloudx_proxy.egg-info/dependency_links.txt +0 -0
  51. {cloudx_proxy-0.17.0 → cloudx_proxy-0.17.2}/cloudx_proxy.egg-info/entry_points.txt +0 -0
  52. {cloudx_proxy-0.17.0 → cloudx_proxy-0.17.2}/cloudx_proxy.egg-info/requires.txt +0 -0
  53. {cloudx_proxy-0.17.0 → cloudx_proxy-0.17.2}/cloudx_proxy.egg-info/top_level.txt +0 -0
  54. {cloudx_proxy-0.17.0 → cloudx_proxy-0.17.2}/setup.cfg +0 -0
  55. {cloudx_proxy-0.17.0 → cloudx_proxy-0.17.2}/tests/__init__.py +0 -0
@@ -89,7 +89,7 @@ When working on this codebase, prioritize:
89
89
  1. **Type safety**: Add complete type hints to new code.
90
90
  2. **Single responsibility**: Keep classes and methods focused.
91
91
  3. **Error handling**: Use specific exceptions with context.
92
- 4. **Testing**: Write tests for new functionality (when framework exists).
92
+ 4. **Testing**: Write tests for new functionality. Run `uv run pytest` and `uv run ruff check cloudx_proxy tests`; both gate CI. `tests/test_backward_compat.py` holds SSH configs as earlier releases wrote them and must keep passing unchanged - a failure there means existing users would have to edit a file or re-run setup.
93
93
  5. **Security**: Validate all inputs and sanitize subprocess calls.
94
94
 
95
95
  ## Release Process
@@ -38,8 +38,9 @@ uvx cloudX-proxy setup [OPTIONS]
38
38
  - `--aws-env`: AWS environment directory.
39
39
  - `--instance`: EC2 instance ID (skips prompt).
40
40
  - `--hostname`: Hostname for SSH config.
41
- - `--yes`: Non-interactive mode.
42
- - `--dry-run`: Preview changes.
41
+ - `--environment`: cloudX environment (default: from the instance `Name` tag).
42
+ - `--yes`: Non-interactive mode; failures exit non-zero instead of being continued past.
43
+ - `--dry-run`: Preview changes; makes no AWS calls and writes no files.
43
44
 
44
45
  **What Setup Does:**
45
46
  1. **Configures AWS Profile**: Creates/validates profile for IAM user.
@@ -0,0 +1,65 @@
1
+ name: Test
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ - develop
8
+ pull_request:
9
+ branches:
10
+ - main
11
+ - develop
12
+
13
+ jobs:
14
+ lint:
15
+ name: Lint
16
+ runs-on: ubuntu-latest
17
+
18
+ steps:
19
+ - name: Checkout
20
+ uses: actions/checkout@v7
21
+
22
+ - name: Install uv
23
+ uses: astral-sh/setup-uv@v7
24
+ with:
25
+ python-version: "3.12"
26
+
27
+ - name: Install project and dev tools
28
+ run: uv sync --group dev
29
+
30
+ - name: Ruff
31
+ run: uv run ruff check --output-format=github cloudx_proxy tests
32
+
33
+ test:
34
+ name: Test (Python ${{ matrix.python-version }})
35
+ runs-on: ubuntu-latest
36
+ strategy:
37
+ fail-fast: false
38
+ matrix:
39
+ python-version:
40
+ - "3.10"
41
+ - "3.11"
42
+ - "3.12"
43
+ - "3.13"
44
+
45
+ steps:
46
+ - name: Checkout
47
+ uses: actions/checkout@v7
48
+
49
+ - name: Install uv
50
+ uses: astral-sh/setup-uv@v7
51
+ with:
52
+ python-version: ${{ matrix.python-version }}
53
+
54
+ - name: Install project and dev tools
55
+ run: uv sync --group dev
56
+
57
+ - name: Run tests
58
+ run: uv run pytest
59
+
60
+ - name: Check the package imports without being built
61
+ # cloudx_proxy/_version.py is generated by setuptools_scm and is not
62
+ # committed, so a plain source checkout must still import
63
+ run: |
64
+ rm -f cloudx_proxy/_version.py
65
+ uv run --no-sync python -c "import cloudx_proxy; print(cloudx_proxy.__version__)"
@@ -22,9 +22,6 @@ cloudx_proxy/_version.py
22
22
  .installed.cfg
23
23
  *.egg
24
24
 
25
- # Version file generated by setuptools_scm
26
- cloudx_client/_version.py
27
-
28
25
  # Virtual Environment
29
26
  .venv/
30
27
  env/
@@ -42,3 +39,4 @@ ENV/
42
39
  Thumbs.db
43
40
 
44
41
 
42
+ .claude/
@@ -1,3 +1,19 @@
1
+ ## [0.17.2](https://github.com/easytocloud/cloudX-proxy/compare/v0.17.1...v0.17.2) (2026-09-04)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * do not delete a live 1Password agent socket without asking ([5cd724c](https://github.com/easytocloud/cloudX-proxy/commit/5cd724c0cb25f02d440ecf792f54bc1efde557fd))
7
+ * harden the runtime paths around subprocesses ([5f69662](https://github.com/easytocloud/cloudX-proxy/commit/5f69662d6a7da586abc7ec7041c5660a80280297))
8
+ * make --yes and --dry-run report what actually happened ([9a6dcc2](https://github.com/easytocloud/cloudX-proxy/commit/9a6dcc28ecc4f2295aa41f3fedbe396399d52fc2))
9
+ * preserve top-level directives and stop banners accumulating ([ea89703](https://github.com/easytocloud/cloudX-proxy/commit/ea897034fd860a41c1dcf4340d5903244a29e320))
10
+ * repair unquoted IdentityFile paths in existing configs ([e2dc815](https://github.com/easytocloud/cloudX-proxy/commit/e2dc8151d1897236553e5b67ff08d3edf094a1d2))
11
+ * run the AWS CLI without a shell, and resolve CodeQL's import notes ([4962c2c](https://github.com/easytocloud/cloudX-proxy/commit/4962c2c20e5d2c98d13469d09a56430836de268d))
12
+ * stop SSH config rewrites from discarding configuration ([40b1d0f](https://github.com/easytocloud/cloudX-proxy/commit/40b1d0ff9b4c503df6d142b9d2baef6f34579011))
13
+ * validate and quote values written into the SSH config ([bf55191](https://github.com/easytocloud/cloudX-proxy/commit/bf551913be8057f3e1e58599a46b14b6f2d7422b))
14
+
15
+ ## [0.17.1](https://github.com/easytocloud/cloudX-proxy/compare/v0.17.0...v0.17.1) (2026-09-02)
16
+
1
17
  # [0.17.0](https://github.com/easytocloud/cloudX-proxy/compare/v0.16.15...v0.17.0) (2026-09-02)
2
18
 
3
19
 
@@ -26,6 +26,19 @@ python -m build
26
26
  pip install dist/cloudx_proxy-*.whl
27
27
  ```
28
28
 
29
+ ### Testing and Linting
30
+
31
+ ```bash
32
+ # Run the test suite
33
+ uv run pytest
34
+
35
+ # Lint (config in pyproject.toml under [tool.ruff])
36
+ uv run ruff check cloudx_proxy tests
37
+ ```
38
+
39
+ `tests/test_backward_compat.py` pins the behaviour existing installations
40
+ depend on; see CONTRIBUTING.md before changing those fixtures.
41
+
29
42
  ### Running the Application
30
43
 
31
44
  The application is designed to be run via `uvx` (from the `uv` package manager):
@@ -50,7 +63,7 @@ When working on this codebase, prioritize:
50
63
  1. **Type safety** - Add complete type hints to new code
51
64
  2. **Single responsibility** - Keep classes and methods focused
52
65
  3. **Error handling** - Use specific exceptions with context
53
- 4. **Testing** - Write tests for new functionality (when framework exists)
66
+ 4. **Testing** - Write tests for new functionality; run `uv run pytest` and `uv run ruff check`
54
67
  5. **Security** - Validate all inputs and sanitize subprocess calls
55
68
 
56
69
  ## Release Process
@@ -0,0 +1,57 @@
1
+ # Contributing to cloudX-proxy
2
+
3
+ ## Development Setup
4
+
5
+ 1. Clone the repository
6
+ 2. Install the project and development tools:
7
+ ```bash
8
+ uv sync --group dev
9
+ ```
10
+
11
+ ## Tests and Linting
12
+
13
+ Both run in CI on every pull request and must pass:
14
+
15
+ ```bash
16
+ # Run the test suite
17
+ uv run pytest
18
+
19
+ # Lint (configuration lives in pyproject.toml under [tool.ruff])
20
+ uv run ruff check cloudx_proxy tests
21
+
22
+ # Apply the fixes ruff can make safely
23
+ uv run ruff check --fix cloudx_proxy tests
24
+ ```
25
+
26
+ ### Backward compatibility
27
+
28
+ `uvx cloudX-proxy` resolves to the latest release every time it runs, so an
29
+ existing user's SSH config - written by an older version and never edited
30
+ again - is handed straight to new code. `tests/test_backward_compat.py` holds
31
+ configs exactly as earlier versions wrote them and asserts that `cleanup`
32
+ changes nothing in them but the version stamp, that they still parse, and that
33
+ every ProxyCommand shape those versions emitted is still accepted by `connect`.
34
+
35
+ Treat those fixtures as frozen. If a change makes one of them fail, the change
36
+ requires existing users to edit a file or re-run setup, which needs to be a
37
+ deliberate decision rather than a side effect.
38
+
39
+ ## Publishing to PyPI
40
+
41
+ The package is automatically published to PyPI via GitHub Actions when a new release is created. Setup:
42
+
43
+ 1. Register project on PyPI
44
+ 2. Generate API token in PyPI (Account Settings → API tokens)
45
+ 3. Add token as GitHub secret named `PYPI_TOKEN`
46
+
47
+ ## Versioning
48
+
49
+ The project uses semantic-release for versioning.
50
+ Version numbers are automatically determined based on commit messages following the conventional commits specification.
51
+
52
+ The GitHub Actions workflow will:
53
+
54
+ 1. Determine next version based on commits
55
+ 2. Update CHANGELOG.md
56
+ 3. Create GitHub release
57
+ 4. Publish to PyPI
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cloudx-proxy
3
- Version: 0.17.0
3
+ Version: 0.17.2
4
4
  Summary: SSH proxy command to connect VSCode with cloudX instance using AWS Systems Manager
5
5
  Author-email: easytocloud <info@easytocloud.com>
6
6
  License: MIT License
@@ -282,6 +282,14 @@ The setup command will:
282
282
  - Offers to wait for setup completion
283
283
  - Monitors setup progress
284
284
 
285
+ ### Prerequisites Check
286
+
287
+ `setup` first checks that the AWS CLI and the Session Manager plugin are on your
288
+ PATH. Both are invoked from inside the SSH ProxyCommand, where a missing binary
289
+ surfaces only as "Could not establish connection" in VSCode, so setup reports it
290
+ up front. Setup continues either way - writing the configuration is still useful -
291
+ but connections will fail until they are installed.
292
+
285
293
  ### SSH Configuration
286
294
 
287
295
  The setup command configures SSH to use cloudX-proxy as a ProxyCommand, enabling seamless connections through AWS Systems Manager. For example, running:
@@ -492,8 +500,9 @@ Options:
492
500
  - `--aws-env` (optional): AWS environment directory to use. If specified, AWS configuration and credentials will be read from ~/.aws/aws-envs/{env}/.
493
501
  - `--instance` (optional): EC2 instance ID to set up connection for. If provided, skips the instance ID prompt.
494
502
  - `--hostname` (optional): Hostname to use for SSH configuration. If not provided, a hostname will be generated from the instance ID in non-interactive mode or prompted for in interactive mode.
495
- - `--yes` (flag): Non-interactive mode, use default values for all prompts. Requires sufficient defaults or explicit parameters for all required values.
496
- - `--dry-run` (flag): Preview setup changes without actually executing them. Useful for testing configurations before applying them.
503
+ - `--environment` (optional): cloudX environment (e.g. `dev`, `pre-prod`). If not provided, it is taken from the instance's `Name` tag (`cloudX-{env}-{hostname}`), then from the AWS user name. Required with `--yes` when neither is available.
504
+ - `--yes` (flag): Non-interactive mode, use default values for all prompts. Requires sufficient defaults or explicit parameters for all required values. Unlike interactive mode, a failure is never continued past: setup reports the error and exits non-zero rather than carrying on.
505
+ - `--dry-run` (flag): Preview setup changes without actually executing them. Makes no AWS calls and writes no files, so it works without credentials.
497
506
 
498
507
  Example usage:
499
508
  ```bash
@@ -585,6 +594,11 @@ The cleanup command reorganizes and normalizes your SSH configuration file. It:
585
594
  - Reorganizes the config with proper structure and banners
586
595
  - Normalizes all `cloudX`/`cloudx` prefixes to match the command used
587
596
  - Rebuilds ProxyCommand entries to remove redundant flags
597
+ - Preserves entries it does not manage (your own `Host` and `Match` blocks,
598
+ with the comments above them) in a clearly marked section at the end
599
+ - Writes the previous contents to `<config>.bak` before rewriting
600
+
601
+ `cleanup` performs a full rewrite of the file, so the backup is your undo.
588
602
 
589
603
  Options:
590
604
  - `--ssh-config` (optional): Path to the SSH config file to use. If not specified, uses ~/.ssh/cloudX/config.
@@ -230,6 +230,14 @@ The setup command will:
230
230
  - Offers to wait for setup completion
231
231
  - Monitors setup progress
232
232
 
233
+ ### Prerequisites Check
234
+
235
+ `setup` first checks that the AWS CLI and the Session Manager plugin are on your
236
+ PATH. Both are invoked from inside the SSH ProxyCommand, where a missing binary
237
+ surfaces only as "Could not establish connection" in VSCode, so setup reports it
238
+ up front. Setup continues either way - writing the configuration is still useful -
239
+ but connections will fail until they are installed.
240
+
233
241
  ### SSH Configuration
234
242
 
235
243
  The setup command configures SSH to use cloudX-proxy as a ProxyCommand, enabling seamless connections through AWS Systems Manager. For example, running:
@@ -440,8 +448,9 @@ Options:
440
448
  - `--aws-env` (optional): AWS environment directory to use. If specified, AWS configuration and credentials will be read from ~/.aws/aws-envs/{env}/.
441
449
  - `--instance` (optional): EC2 instance ID to set up connection for. If provided, skips the instance ID prompt.
442
450
  - `--hostname` (optional): Hostname to use for SSH configuration. If not provided, a hostname will be generated from the instance ID in non-interactive mode or prompted for in interactive mode.
443
- - `--yes` (flag): Non-interactive mode, use default values for all prompts. Requires sufficient defaults or explicit parameters for all required values.
444
- - `--dry-run` (flag): Preview setup changes without actually executing them. Useful for testing configurations before applying them.
451
+ - `--environment` (optional): cloudX environment (e.g. `dev`, `pre-prod`). If not provided, it is taken from the instance's `Name` tag (`cloudX-{env}-{hostname}`), then from the AWS user name. Required with `--yes` when neither is available.
452
+ - `--yes` (flag): Non-interactive mode, use default values for all prompts. Requires sufficient defaults or explicit parameters for all required values. Unlike interactive mode, a failure is never continued past: setup reports the error and exits non-zero rather than carrying on.
453
+ - `--dry-run` (flag): Preview setup changes without actually executing them. Makes no AWS calls and writes no files, so it works without credentials.
445
454
 
446
455
  Example usage:
447
456
  ```bash
@@ -533,6 +542,11 @@ The cleanup command reorganizes and normalizes your SSH configuration file. It:
533
542
  - Reorganizes the config with proper structure and banners
534
543
  - Normalizes all `cloudX`/`cloudx` prefixes to match the command used
535
544
  - Rebuilds ProxyCommand entries to remove redundant flags
545
+ - Preserves entries it does not manage (your own `Host` and `Match` blocks,
546
+ with the comments above them) in a clearly marked section at the end
547
+ - Writes the previous contents to `<config>.bak` before rewriting
548
+
549
+ `cleanup` performs a full rewrite of the file, so the backup is your undo.
536
550
 
537
551
  Options:
538
552
  - `--ssh-config` (optional): Path to the SSH config file to use. If not specified, uses ~/.ssh/cloudX/config.
@@ -0,0 +1,31 @@
1
+ """cloudx-proxy - SSH proxy connecting VSCode Remote SSH to EC2 via AWS SSM."""
2
+
3
+
4
+ def _resolve_version() -> str:
5
+ """Determine the package version.
6
+
7
+ ``_version.py`` is written by setuptools_scm at build time and is not
8
+ committed, so it is absent in a plain source checkout. Fall back to the
9
+ installed distribution metadata, and finally to a sentinel, so importing
10
+ the package never fails merely because it has not been built.
11
+
12
+ Returns:
13
+ str: The package version
14
+ """
15
+ try:
16
+ from ._version import __version__ as scm_version
17
+ return scm_version
18
+ except ImportError:
19
+ pass
20
+
21
+ from importlib.metadata import PackageNotFoundError, version
22
+
23
+ try:
24
+ return version("cloudx-proxy")
25
+ except PackageNotFoundError:
26
+ return "0.0.0+unknown"
27
+
28
+
29
+ __version__ = _resolve_version()
30
+
31
+ __all__ = ['__version__']
@@ -1,8 +1,29 @@
1
- import os
1
+ """1Password integration, via 1Password's own CLI (`op`).
2
+
3
+ Naming rule: every identifier for this integration is `op_*`, after the `op`
4
+ CLI - never `use_1password`, `onepassword_agent_sock` or similar. User-facing
5
+ text still says "1Password"; only identifiers avoid the word.
6
+
7
+ That is not only style. CodeQL's py/clear-text-logging-sensitive-data query
8
+ decides whether a value is a credential from the name of the identifier that
9
+ produced it, and it matches "password" as a substring - which both "1password"
10
+ and "onepassword" contain. Naming things after the product therefore marked
11
+ vault names, the agent socket path and the `op --version` string as secrets,
12
+ and every status message printing one was reported as clear-text logging of a
13
+ password: high severity, and wrong every time. Renaming to `op_*` describes
14
+ the values accurately and stops the misclassification at its source.
15
+ """
16
+
2
17
  import json
18
+ import os
3
19
  import subprocess
4
20
 
5
- def check_1password_cli() -> tuple:
21
+ # The 1Password CLI can block on an interactive unlock (biometrics, or a
22
+ # device prompt). Output is captured here, so that prompt would be invisible
23
+ # and the call would hang; fail after a bounded wait instead.
24
+ OP_TIMEOUT = 30
25
+
26
+ def check_op_cli() -> tuple:
6
27
  """Check if 1Password CLI is installed and authenticated.
7
28
 
8
29
  Returns:
@@ -14,7 +35,8 @@ def check_1password_cli() -> tuple:
14
35
  ['op', '--version'],
15
36
  capture_output=True,
16
37
  text=True,
17
- check=False
38
+ check=False,
39
+ timeout=OP_TIMEOUT
18
40
  )
19
41
 
20
42
  if result.returncode != 0:
@@ -27,7 +49,8 @@ def check_1password_cli() -> tuple:
27
49
  ['op', 'account', 'list'],
28
50
  capture_output=True,
29
51
  text=True,
30
- check=False
52
+ check=False,
53
+ timeout=OP_TIMEOUT
31
54
  )
32
55
 
33
56
  if result.returncode != 0:
@@ -40,40 +63,6 @@ def check_1password_cli() -> tuple:
40
63
  except Exception:
41
64
  return False, False, ""
42
65
 
43
- def check_ssh_agent(agent_sock_path: str) -> bool:
44
- """Check if 1Password SSH agent is running.
45
-
46
- Args:
47
- agent_sock_path: Path to the SSH agent socket
48
-
49
- Returns:
50
- bool: True if agent is running
51
- """
52
- try:
53
- # Check if the socket file exists
54
- if not os.path.exists(agent_sock_path):
55
- return False
56
-
57
- # Check if agent is active
58
- env = os.environ.copy()
59
- env['SSH_AUTH_SOCK'] = agent_sock_path
60
-
61
- result = subprocess.run(
62
- ['ssh-add', '-l'],
63
- env=env,
64
- capture_output=True,
65
- text=True,
66
- check=False
67
- )
68
-
69
- if "Could not open a connection to your authentication agent" in result.stderr:
70
- return False
71
-
72
- return True
73
-
74
- except Exception:
75
- return False
76
-
77
66
  def list_ssh_keys() -> list:
78
67
  """List SSH keys stored in 1Password.
79
68
 
@@ -86,7 +75,8 @@ def list_ssh_keys() -> list:
86
75
  ['op', 'item', 'list', '--categories', 'SSH Key', '--format=json'],
87
76
  capture_output=True,
88
77
  text=True,
89
- check=False
78
+ check=False,
79
+ timeout=OP_TIMEOUT
90
80
  )
91
81
 
92
82
  if result.returncode != 0:
@@ -119,7 +109,8 @@ def create_ssh_key(title: str, vault: str) -> tuple:
119
109
  ],
120
110
  capture_output=True,
121
111
  text=True,
122
- check=False
112
+ check=False,
113
+ timeout=OP_TIMEOUT
123
114
  )
124
115
 
125
116
  if result.returncode != 0:
@@ -130,7 +121,7 @@ def create_ssh_key(title: str, vault: str) -> tuple:
130
121
  item_id = ""
131
122
  public_key = ""
132
123
 
133
- for idx, line in enumerate(output_lines):
124
+ for _idx, line in enumerate(output_lines):
134
125
  if line.startswith("ID:"):
135
126
  item_id = line.split(":", 1)[1].strip()
136
127
 
@@ -166,7 +157,8 @@ def get_vaults() -> list:
166
157
  ['op', 'vault', 'list', '--format=json'],
167
158
  capture_output=True,
168
159
  text=True,
169
- check=False
160
+ check=False,
161
+ timeout=OP_TIMEOUT
170
162
  )
171
163
 
172
164
  if result.returncode != 0:
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '0.17.0'
22
- __version_tuple__ = version_tuple = (0, 17, 0)
21
+ __version__ = version = '0.17.2'
22
+ __version_tuple__ = version_tuple = (0, 17, 2)
23
23
 
24
24
  __commit_id__ = commit_id = None