hop3-cli 0.5.0.dev3__tar.gz → 0.6.1__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 (62) hide show
  1. {hop3_cli-0.5.0.dev3 → hop3_cli-0.6.1}/PKG-INFO +13 -14
  2. {hop3_cli-0.5.0.dev3 → hop3_cli-0.6.1}/README.md +11 -13
  3. {hop3_cli-0.5.0.dev3 → hop3_cli-0.6.1}/pyproject.toml +2 -1
  4. {hop3_cli-0.5.0.dev3 → hop3_cli-0.6.1}/src/hop3_cli/commands/__init__.py +2 -0
  5. {hop3_cli-0.5.0.dev3 → hop3_cli-0.6.1}/src/hop3_cli/commands/arguments.py +291 -143
  6. {hop3_cli-0.5.0.dev3 → hop3_cli-0.6.1}/src/hop3_cli/commands/destructive.py +62 -78
  7. {hop3_cli-0.5.0.dev3 → hop3_cli-0.6.1}/src/hop3_cli/commands/flags.py +25 -12
  8. {hop3_cli-0.5.0.dev3 → hop3_cli-0.6.1}/src/hop3_cli/commands/help.py +134 -35
  9. {hop3_cli-0.5.0.dev3 → hop3_cli-0.6.1}/src/hop3_cli/commands/local/__init__.py +25 -14
  10. {hop3_cli-0.5.0.dev3 → hop3_cli-0.6.1}/src/hop3_cli/commands/local/aliases_cmd.py +2 -14
  11. hop3_cli-0.6.1/src/hop3_cli/commands/local/auth_cmd.py +60 -0
  12. {hop3_cli-0.5.0.dev3 → hop3_cli-0.6.1}/src/hop3_cli/commands/local/completion_cmd.py +8 -52
  13. hop3_cli-0.6.1/src/hop3_cli/commands/local/context_cmd.py +524 -0
  14. hop3_cli-0.6.1/src/hop3_cli/commands/local/help_text.py +285 -0
  15. {hop3_cli-0.5.0.dev3 → hop3_cli-0.6.1}/src/hop3_cli/commands/local/init_cmd.py +18 -35
  16. {hop3_cli-0.5.0.dev3 → hop3_cli-0.6.1}/src/hop3_cli/commands/local/login_cmd.py +129 -69
  17. {hop3_cli-0.5.0.dev3 → hop3_cli-0.6.1}/src/hop3_cli/commands/local/settings_cmd.py +19 -0
  18. {hop3_cli-0.5.0.dev3 → hop3_cli-0.6.1}/src/hop3_cli/commands/local/ssh_ops.py +30 -13
  19. hop3_cli-0.6.1/src/hop3_cli/commands/local/tunnel_cmd.py +187 -0
  20. {hop3_cli-0.5.0.dev3 → hop3_cli-0.6.1}/src/hop3_cli/commands/local/use_cmd.py +21 -28
  21. hop3_cli-0.6.1/src/hop3_cli/config.py +494 -0
  22. {hop3_cli-0.5.0.dev3 → hop3_cli-0.6.1}/src/hop3_cli/core/alias_registry.py +1 -0
  23. {hop3_cli-0.5.0.dev3 → hop3_cli-0.6.1}/src/hop3_cli/core/aliases.py +13 -9
  24. {hop3_cli-0.5.0.dev3 → hop3_cli-0.6.1}/src/hop3_cli/core/app_scope.py +46 -12
  25. hop3_cli-0.6.1/src/hop3_cli/core/config_migration.py +395 -0
  26. hop3_cli-0.6.1/src/hop3_cli/core/config_migration_v2.py +182 -0
  27. hop3_cli-0.6.1/src/hop3_cli/core/credential_store.py +156 -0
  28. {hop3_cli-0.5.0.dev3 → hop3_cli-0.6.1}/src/hop3_cli/core/deploy_preview.py +86 -82
  29. {hop3_cli-0.5.0.dev3 → hop3_cli-0.6.1}/src/hop3_cli/core/hop3_toml.py +2 -4
  30. {hop3_cli-0.5.0.dev3 → hop3_cli-0.6.1}/src/hop3_cli/core/local_overlay.py +31 -18
  31. hop3_cli-0.6.1/src/hop3_cli/core/paths.py +35 -0
  32. {hop3_cli-0.5.0.dev3 → hop3_cli-0.6.1}/src/hop3_cli/core/project_guard.py +5 -3
  33. hop3_cli-0.6.1/src/hop3_cli/core/resolution.py +566 -0
  34. {hop3_cli-0.5.0.dev3 → hop3_cli-0.6.1}/src/hop3_cli/exit_codes.py +2 -9
  35. {hop3_cli-0.5.0.dev3 → hop3_cli-0.6.1}/src/hop3_cli/main.py +241 -85
  36. {hop3_cli-0.5.0.dev3 → hop3_cli-0.6.1}/src/hop3_cli/rpc/__init__.py +1 -4
  37. {hop3_cli-0.5.0.dev3 → hop3_cli-0.6.1}/src/hop3_cli/rpc/client.py +4 -5
  38. {hop3_cli-0.5.0.dev3 → hop3_cli-0.6.1}/src/hop3_cli/rpc/responses.py +65 -87
  39. {hop3_cli-0.5.0.dev3 → hop3_cli-0.6.1}/src/hop3_cli/rpc/streaming.py +4 -1
  40. {hop3_cli-0.5.0.dev3 → hop3_cli-0.6.1}/src/hop3_cli/ui/__init__.py +1 -2
  41. {hop3_cli-0.5.0.dev3 → hop3_cli-0.6.1}/src/hop3_cli/ui/console.py +0 -5
  42. {hop3_cli-0.5.0.dev3 → hop3_cli-0.6.1}/src/hop3_cli/ui/messages.py +18 -0
  43. {hop3_cli-0.5.0.dev3 → hop3_cli-0.6.1}/src/hop3_cli/ui/rich_printer.py +35 -46
  44. hop3_cli-0.5.0.dev3/src/hop3_cli/commands/local/auth_cmd.py +0 -52
  45. hop3_cli-0.5.0.dev3/src/hop3_cli/commands/local/context_cmd.py +0 -563
  46. hop3_cli-0.5.0.dev3/src/hop3_cli/commands/local/help_text.py +0 -166
  47. hop3_cli-0.5.0.dev3/src/hop3_cli/commands/local/project_context_cmd.py +0 -776
  48. hop3_cli-0.5.0.dev3/src/hop3_cli/commands/local/server_cmd.py +0 -599
  49. hop3_cli-0.5.0.dev3/src/hop3_cli/config.py +0 -563
  50. hop3_cli-0.5.0.dev3/src/hop3_cli/core/cli_state.py +0 -117
  51. hop3_cli-0.5.0.dev3/src/hop3_cli/core/context_names.py +0 -72
  52. hop3_cli-0.5.0.dev3/src/hop3_cli/core/resolution.py +0 -930
  53. hop3_cli-0.5.0.dev3/src/hop3_cli/core/server_registry.py +0 -309
  54. hop3_cli-0.5.0.dev3/src/hop3_cli/rpc/tunnel.py +0 -177
  55. {hop3_cli-0.5.0.dev3 → hop3_cli-0.6.1}/src/hop3_cli/__init__.py +0 -0
  56. {hop3_cli-0.5.0.dev3 → hop3_cli-0.6.1}/src/hop3_cli/commands/local/version_cmd.py +0 -0
  57. {hop3_cli-0.5.0.dev3 → hop3_cli-0.6.1}/src/hop3_cli/core/__init__.py +0 -0
  58. {hop3_cli-0.5.0.dev3 → hop3_cli-0.6.1}/src/hop3_cli/core/suggest.py +0 -0
  59. {hop3_cli-0.5.0.dev3 → hop3_cli-0.6.1}/src/hop3_cli/exceptions.py +0 -0
  60. {hop3_cli-0.5.0.dev3 → hop3_cli-0.6.1}/src/hop3_cli/tokens.py +0 -0
  61. {hop3_cli-0.5.0.dev3 → hop3_cli-0.6.1}/src/hop3_cli/types.py +0 -0
  62. {hop3_cli-0.5.0.dev3 → hop3_cli-0.6.1}/src/hop3_cli/ui/prompts.py +0 -0
@@ -1,11 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hop3-cli
3
- Version: 0.5.0.dev3
3
+ Version: 0.6.1
4
4
  Summary:
5
5
  Author: Stefane Fermigier
6
6
  Author-email: Stefane Fermigier <sf@abilian.com>
7
7
  License-Expression: Apache-2.0
8
8
  Requires-Dist: toml>=0.10.2,<1.0.0
9
+ Requires-Dist: tomlkit>=0.13.0
9
10
  Requires-Dist: jsonrpcclient>=4.0.3,<5.0.0
10
11
  Requires-Dist: requests>=2.32.3,<3.0.0
11
12
  Requires-Dist: tabulate>=0.9.0,<1.0.0
@@ -57,29 +58,27 @@ hop3 apps
57
58
  hop3 use myapp
58
59
 
59
60
  # From here on, app-scoped commands resolve myapp automatically:
60
- hop3 logs
61
+ hop3 app logs
61
62
  hop3 config set KEY=value
62
- hop3 restart
63
+ hop3 app restart
63
64
  ```
64
65
 
65
66
  ## App Resolution
66
67
 
67
- Commands that act on a single app (`logs`, `restart`, `config set`, `run`, …) no longer take the app name as a positional argument. Instead the CLI resolves it from a layered chain, walking sources until one supplies a value (ADR 042 §Resolution chains; supersedes ADR 036 §D7):
68
+ Commands that act on a single app (`logs`, `restart`, `config set`, `run`, …) no longer take the app name as a positional argument. Instead the CLI resolves it from a layered chain, walking sources until one supplies a value (ADR 042 §Resolution; supersedes ADR 036 §D7):
68
69
 
69
70
  1. `--app <name>` / `-a <name>` — explicit flag, wins over everything.
70
71
  2. `$HOP3_APP` — environment variable for the current shell.
71
72
  3. `.hop3-app` — one-line file in CWD or any ancestor up to `$HOME`. Drop it in a project repo and `hop3` from inside picks up the right app.
72
73
  4. `hop3.toml [cli].app` — same search path as `.hop3-app`, lower priority.
73
- 5. `hop3.toml [contexts.<resolved-context>].app` — when a project context resolves (see below), its `app` field becomes the source. Lets one project map per-environment to different apps.
74
- 6. `hop3.toml [metadata].id` — the project's canonical name. The "I'm physically standing in this project" source; outranks any server-level default so being inside a project always wins over a sticky binding from elsewhere.
75
- 7. Git remote `hop3-<env>` parsed for an app name — supports `git push hop3-prod main` style deploys.
76
- 8. Active server's `default_app` from `~/.config/hop3-cli/servers.toml` — set via `hop3 server use --default-app <app>`. Lowest-priority fallback for single-app users.
74
+ 5. `hop3.toml [contexts.<resolved-context>].app` — when a project context resolves (see below), its `app` field becomes the source. Lets one project map per-environment to different apps. Trusted only when the context was selected CWD-rooted (`--context` or in-tree `.hop3-local.toml`); an ambiently-selected context still resolves but trips the project-mismatch guard.
75
+ 6. `hop3.toml [metadata].id` — the project's canonical name. The "I'm physically standing in this project" source, so being inside a project always wins over a sticky binding from elsewhere.
77
76
 
78
77
  Use `hop3 --why <command>` to print the full trace and see which source won. `--why` is diagnostic-only: the command itself is not executed (so `hop3 deploy --why` is safe to run).
79
78
 
80
79
  ```bash
81
80
  # Explicit (always works):
82
- hop3 logs --app myapp
81
+ hop3 app logs --app myapp
83
82
  hop3 config set --app myapp KEY=value
84
83
 
85
84
  # Per-shell:
@@ -98,12 +97,12 @@ echo myapp > .hop3-app
98
97
  hop3 --why logs
99
98
  ```
100
99
 
101
- The ADR 042 model splits the old "context" noun into two concepts:
100
+ The ADR 042 model has a single managed noun — the **context** — and a single selector, `--context <name>`, for every command (app-bound or not).
102
101
 
103
- - **Server records** — credentialed bindings to a Hop3 server. Live in `~/.config/hop3-cli/servers.toml`. Managed with `hop3 server` (`add` / `list` / `show` / `use` / `login` / `remove`).
104
- - **Project contexts** — environment-shaped overlays on a single project. Declared as `[contexts.<name>]` blocks inside `hop3.toml`. Managed with `hop3 context` from inside a project tree (`init` / `use` / `list` / `show` / `add` / `remove`). The currently-selected one is recorded in `.hop3-local.toml` (gitignored automatically).
102
+ - **Contexts** — a named target at two scopes. A **project** context (dev / staging / prod) is declared as a `[contexts.<name>]` block inside the committed `hop3.toml`: a non-secret bundle of server address + app + domains + env. A **global** context is a name bound to a server address in the per-developer `config.toml` (`[contexts.<name>].server`), so project-less commands (`hop3 apps --context prod`) can target a server by name. `--context` resolves project-first, then global; there is no `--server` flag. Managed with `hop3 context` (`add` / `use` / `list` / `show` / `remove` / `rename`) — project scope inside a project tree, global scope outside one (or with `--global`). The per-checkout project selection is recorded in `.hop3-local.toml` (gitignored automatically).
103
+ - **Credentials are invisible plumbing** — there is no "server" noun to manage. `hop3 login` stores a bearer token in the per-server credential store (`~/.config/hop3-cli/credentials.toml`, mode `0600`), keyed by the server's canonical address, and records that server as the default target; `hop3 login --context <name>` also names it as a global context and the default. `config.toml` stays secret-free (local preferences, global contexts, `[cli].default_context`).
105
104
 
106
- A `hop3 deploy` from a project tree resolves: server (which Hop3 to talk to) + context (which environment of this project) + app (which app on that server) — and shows a preview-and-confirm prompt with the plan before invoking the deploy RPC. `--dry-run` exits after printing the plan; `--force` bypasses the project-mismatch safety guard.
105
+ A `hop3 deploy` from a project tree resolves the context (which environment of this project, and therefore which server and app), and shows a preview-and-confirm prompt with the plan before invoking the deploy RPC. `--dry-run` exits after printing the plan; `--force` bypasses the project-mismatch safety guard.
107
106
 
108
107
  See [CLI Reference: App Resolution](../../docs/src/reference/cli.md#app-resolution) and [ADR 042](../../notes/adrs/042-cli-context-model.md) for the full specification.
109
108
 
@@ -131,7 +130,7 @@ hop3-cli/
131
130
  │ ├── rpc/
132
131
  │ │ └── client.py # JSON-RPC client with SSH tunnel
133
132
  │ ├── commands/
134
- │ │ ├── local.py # Local commands (init, login, settings)
133
+ │ │ ├── local/ # Local commands (init, login, settings, context)
135
134
  │ │ ├── flags.py # CLI flag parsing (--app, --why, --json, -y, …)
136
135
  │ │ └── destructive.py # Confirmation prompts
137
136
  │ └── ui/
@@ -37,29 +37,27 @@ hop3 apps
37
37
  hop3 use myapp
38
38
 
39
39
  # From here on, app-scoped commands resolve myapp automatically:
40
- hop3 logs
40
+ hop3 app logs
41
41
  hop3 config set KEY=value
42
- hop3 restart
42
+ hop3 app restart
43
43
  ```
44
44
 
45
45
  ## App Resolution
46
46
 
47
- Commands that act on a single app (`logs`, `restart`, `config set`, `run`, …) no longer take the app name as a positional argument. Instead the CLI resolves it from a layered chain, walking sources until one supplies a value (ADR 042 §Resolution chains; supersedes ADR 036 §D7):
47
+ Commands that act on a single app (`logs`, `restart`, `config set`, `run`, …) no longer take the app name as a positional argument. Instead the CLI resolves it from a layered chain, walking sources until one supplies a value (ADR 042 §Resolution; supersedes ADR 036 §D7):
48
48
 
49
49
  1. `--app <name>` / `-a <name>` — explicit flag, wins over everything.
50
50
  2. `$HOP3_APP` — environment variable for the current shell.
51
51
  3. `.hop3-app` — one-line file in CWD or any ancestor up to `$HOME`. Drop it in a project repo and `hop3` from inside picks up the right app.
52
52
  4. `hop3.toml [cli].app` — same search path as `.hop3-app`, lower priority.
53
- 5. `hop3.toml [contexts.<resolved-context>].app` — when a project context resolves (see below), its `app` field becomes the source. Lets one project map per-environment to different apps.
54
- 6. `hop3.toml [metadata].id` — the project's canonical name. The "I'm physically standing in this project" source; outranks any server-level default so being inside a project always wins over a sticky binding from elsewhere.
55
- 7. Git remote `hop3-<env>` parsed for an app name — supports `git push hop3-prod main` style deploys.
56
- 8. Active server's `default_app` from `~/.config/hop3-cli/servers.toml` — set via `hop3 server use --default-app <app>`. Lowest-priority fallback for single-app users.
53
+ 5. `hop3.toml [contexts.<resolved-context>].app` — when a project context resolves (see below), its `app` field becomes the source. Lets one project map per-environment to different apps. Trusted only when the context was selected CWD-rooted (`--context` or in-tree `.hop3-local.toml`); an ambiently-selected context still resolves but trips the project-mismatch guard.
54
+ 6. `hop3.toml [metadata].id` — the project's canonical name. The "I'm physically standing in this project" source, so being inside a project always wins over a sticky binding from elsewhere.
57
55
 
58
56
  Use `hop3 --why <command>` to print the full trace and see which source won. `--why` is diagnostic-only: the command itself is not executed (so `hop3 deploy --why` is safe to run).
59
57
 
60
58
  ```bash
61
59
  # Explicit (always works):
62
- hop3 logs --app myapp
60
+ hop3 app logs --app myapp
63
61
  hop3 config set --app myapp KEY=value
64
62
 
65
63
  # Per-shell:
@@ -78,12 +76,12 @@ echo myapp > .hop3-app
78
76
  hop3 --why logs
79
77
  ```
80
78
 
81
- The ADR 042 model splits the old "context" noun into two concepts:
79
+ The ADR 042 model has a single managed noun — the **context** — and a single selector, `--context <name>`, for every command (app-bound or not).
82
80
 
83
- - **Server records** — credentialed bindings to a Hop3 server. Live in `~/.config/hop3-cli/servers.toml`. Managed with `hop3 server` (`add` / `list` / `show` / `use` / `login` / `remove`).
84
- - **Project contexts** — environment-shaped overlays on a single project. Declared as `[contexts.<name>]` blocks inside `hop3.toml`. Managed with `hop3 context` from inside a project tree (`init` / `use` / `list` / `show` / `add` / `remove`). The currently-selected one is recorded in `.hop3-local.toml` (gitignored automatically).
81
+ - **Contexts** — a named target at two scopes. A **project** context (dev / staging / prod) is declared as a `[contexts.<name>]` block inside the committed `hop3.toml`: a non-secret bundle of server address + app + domains + env. A **global** context is a name bound to a server address in the per-developer `config.toml` (`[contexts.<name>].server`), so project-less commands (`hop3 apps --context prod`) can target a server by name. `--context` resolves project-first, then global; there is no `--server` flag. Managed with `hop3 context` (`add` / `use` / `list` / `show` / `remove` / `rename`) — project scope inside a project tree, global scope outside one (or with `--global`). The per-checkout project selection is recorded in `.hop3-local.toml` (gitignored automatically).
82
+ - **Credentials are invisible plumbing** — there is no "server" noun to manage. `hop3 login` stores a bearer token in the per-server credential store (`~/.config/hop3-cli/credentials.toml`, mode `0600`), keyed by the server's canonical address, and records that server as the default target; `hop3 login --context <name>` also names it as a global context and the default. `config.toml` stays secret-free (local preferences, global contexts, `[cli].default_context`).
85
83
 
86
- A `hop3 deploy` from a project tree resolves: server (which Hop3 to talk to) + context (which environment of this project) + app (which app on that server) — and shows a preview-and-confirm prompt with the plan before invoking the deploy RPC. `--dry-run` exits after printing the plan; `--force` bypasses the project-mismatch safety guard.
84
+ A `hop3 deploy` from a project tree resolves the context (which environment of this project, and therefore which server and app), and shows a preview-and-confirm prompt with the plan before invoking the deploy RPC. `--dry-run` exits after printing the plan; `--force` bypasses the project-mismatch safety guard.
87
85
 
88
86
  See [CLI Reference: App Resolution](../../docs/src/reference/cli.md#app-resolution) and [ADR 042](../../notes/adrs/042-cli-context-model.md) for the full specification.
89
87
 
@@ -111,7 +109,7 @@ hop3-cli/
111
109
  │ ├── rpc/
112
110
  │ │ └── client.py # JSON-RPC client with SSH tunnel
113
111
  │ ├── commands/
114
- │ │ ├── local.py # Local commands (init, login, settings)
112
+ │ │ ├── local/ # Local commands (init, login, settings, context)
115
113
  │ │ ├── flags.py # CLI flag parsing (--app, --why, --json, -y, …)
116
114
  │ │ └── destructive.py # Confirmation prompts
117
115
  │ └── ui/
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "hop3-cli"
3
- version = "0.5.0.dev3"
3
+ version = "0.6.1"
4
4
  authors = [
5
5
  {name = "Stefane Fermigier", email = "sf@abilian.com"},
6
6
  ]
@@ -9,6 +9,7 @@ requires-python = "<4.0,>=3.10"
9
9
  dependencies = [
10
10
  # Configuration
11
11
  "toml<1.0.0,>=0.10.2",
12
+ "tomlkit>=0.13.0", # comment-preserving TOML round-trip for hop3.toml edits
12
13
  # Communication
13
14
  "jsonrpcclient<5.0.0,>=4.0.3",
14
15
  "requests<3.0.0,>=2.32.3",
@@ -19,6 +19,7 @@ from .destructive import confirm_destructive_action, is_destructive_command
19
19
  from .flags import CliFlags, parse_flags
20
20
  from .help import (
21
21
  append_feedback_footer,
22
+ append_local_commands_full_help,
22
23
  emit_status_line,
23
24
  handle_help_flags,
24
25
  inject_local_commands_into_help,
@@ -36,6 +37,7 @@ __all__ = [
36
37
  "LOCAL_COMMANDS_INFO",
37
38
  "CliFlags",
38
39
  "append_feedback_footer",
40
+ "append_local_commands_full_help",
39
41
  "confirm_destructive_action",
40
42
  "emit_status_line",
41
43
  "generate_archive",