skillctl-secure 0.28.0__tar.gz → 0.28.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 (123) hide show
  1. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/PKG-INFO +21 -1
  2. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/README.md +20 -0
  3. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/pyproject.toml +1 -1
  4. skillctl_secure-0.28.2/skillctl/__init__.py +1 -0
  5. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/tui.py +5 -13
  6. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/tui_original.py +39 -64
  7. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/tui_refresh.py +6 -10
  8. skillctl_secure-0.28.0/skillctl/__init__.py +0 -1
  9. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/.gitignore +0 -0
  10. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/LICENSE +0 -0
  11. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/__main__.py +0 -0
  12. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/authcontrols.py +0 -0
  13. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/benchmark.py +0 -0
  14. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/browsercontrols.py +0 -0
  15. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/bulk_cli.py +0 -0
  16. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/bulk_plan.py +0 -0
  17. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/bulk_update.py +0 -0
  18. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/bulk_update_tui.py +0 -0
  19. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/cacheutil.py +0 -0
  20. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/candidates.py +0 -0
  21. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/catalog.py +0 -0
  22. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/catalog_discovery.py +0 -0
  23. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/catalog_index.py +0 -0
  24. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/catalog_schema.py +0 -0
  25. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/catalog_search_cli.py +0 -0
  26. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/catalog_search_tui.py +0 -0
  27. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/cicdflow.py +0 -0
  28. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/cli.py +0 -0
  29. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/cli_contract.py +0 -0
  30. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/compatibility.py +0 -0
  31. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/context_cost.py +0 -0
  32. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/context_tui.py +0 -0
  33. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/copilot_export.py +0 -0
  34. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/coverage.py +0 -0
  35. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/dedupe.py +0 -0
  36. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/doctor.py +0 -0
  37. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/entrypoint.py +0 -0
  38. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/environments.py +0 -0
  39. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/estimate.py +0 -0
  40. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/evidence.py +0 -0
  41. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/findings.py +0 -0
  42. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/flow.py +0 -0
  43. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/governor.py +0 -0
  44. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/hardening.py +0 -0
  45. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/history_tui.py +0 -0
  46. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/iac.py +0 -0
  47. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/install_intent.py +0 -0
  48. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/install_review.py +0 -0
  49. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/intent_diff.py +0 -0
  50. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/journal.py +0 -0
  51. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/journal_hooks.py +0 -0
  52. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/journal_operations.py +0 -0
  53. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/lockfile.py +0 -0
  54. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/manager.py +0 -0
  55. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/models.py +0 -0
  56. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/navigation_tui.py +0 -0
  57. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/operation_lock.py +0 -0
  58. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/packet.py +0 -0
  59. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/paths.py +0 -0
  60. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/permissions.py +0 -0
  61. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/policy.py +0 -0
  62. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/policy_editor.py +0 -0
  63. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/precision.py +0 -0
  64. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/profiles.py +0 -0
  65. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/publishers.py +0 -0
  66. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/ranking.py +0 -0
  67. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/recommendation.py +0 -0
  68. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/recommendation_tui.py +0 -0
  69. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/reconcile_cli.py +0 -0
  70. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/reconcile_recovery.py +0 -0
  71. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/reconcile_transaction.py +0 -0
  72. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/reconcile_tui.py +0 -0
  73. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/reconciliation.py +0 -0
  74. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/remote.py +0 -0
  75. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/resources/benchmarks/vulnlab/answer-key.yaml +0 -0
  76. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/resources/benchmarks/vulnlab/target/.env +0 -0
  77. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/resources/benchmarks/vulnlab/target/.github/workflows/build.yml +0 -0
  78. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/resources/benchmarks/vulnlab/target/README.md +0 -0
  79. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/resources/benchmarks/vulnlab/target/app.py +0 -0
  80. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/resources/benchmarks/vulnlab/target/openapi.yaml +0 -0
  81. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/resources/benchmarks/vulnlab/target/requirements.txt +0 -0
  82. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/resources/benchmarks/vulnlab/target/scripts/build.sh +0 -0
  83. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/resources/benchmarks/vulnlab/target/templates/payment.html +0 -0
  84. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/resources/benchmarks/vulnlab/target/trivy-results.json +0 -0
  85. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/resources/custom/.gitkeep +0 -0
  86. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/resources/custom/api-security-review/SKILL.md +0 -0
  87. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/resources/custom/api-security-review/references/inventory-template.md +0 -0
  88. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/resources/custom/api-security-review/references/output-template.md +0 -0
  89. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/resources/custom/biso-security-review/SKILL.md +0 -0
  90. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/resources/custom/biso-security-review/references/disposition.md +0 -0
  91. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/resources/custom/biso-security-review/references/orchestration.md +0 -0
  92. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/resources/custom/biso-security-review/references/output-template.md +0 -0
  93. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/resources/custom/biso-security-review/references/review-checklist.md +0 -0
  94. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/resources/custom/biso-security-review/references/risk-rating.md +0 -0
  95. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/resources/custom/cicd-security-review/SKILL.md +0 -0
  96. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/resources/custom/cicd-security-review/references/output-template.md +0 -0
  97. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/resources/custom/pci-architect/SKILL.md +0 -0
  98. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/resources/custom/pci-architect/references/control-matrix.md +0 -0
  99. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/resources/custom/pci-architect/references/output-template.md +0 -0
  100. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/resources/custom/threat-model/SKILL.md +0 -0
  101. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/resources/custom/threat-model/references/output-template.md +0 -0
  102. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/resources/custom/threat-model/references/risk-rating.md +0 -0
  103. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/resources/custom/vulnerability-manager/SKILL.md +0 -0
  104. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/resources/custom/vulnerability-manager/references/escalation.md +0 -0
  105. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/resources/custom/vulnerability-manager/references/output-template.md +0 -0
  106. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/resources/custom/vulnerability-manager/references/prioritization.md +0 -0
  107. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/resources/finding-schema.json +0 -0
  108. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/resources/skills.yaml +0 -0
  109. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/review.py +0 -0
  110. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/review_candidates.py +0 -0
  111. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/risk_acknowledgment.py +0 -0
  112. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/runtime_binding.py +0 -0
  113. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/safety_plan.py +0 -0
  114. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/section_navigation.py +0 -0
  115. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/stagecache.py +0 -0
  116. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/stateio.py +0 -0
  117. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/transactions.py +0 -0
  118. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/trust.py +0 -0
  119. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/tui_interaction.py +0 -0
  120. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/tui_progressive.py +0 -0
  121. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/update_intent_review.py +0 -0
  122. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/update_intent_tui.py +0 -0
  123. {skillctl_secure-0.28.0 → skillctl_secure-0.28.2}/skillctl/vulnnormalize.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: skillctl-secure
3
- Version: 0.28.0
3
+ Version: 0.28.2
4
4
  Summary: Package manager, trust layer, and portability layer for Agent Skills
5
5
  Project-URL: Homepage, https://github.com/brian-scardina/skillctl
6
6
  Project-URL: Repository, https://github.com/brian-scardina/skillctl
@@ -75,6 +75,26 @@ uv tool uninstall skillctl-secure
75
75
  Uninstalling the application leaves your skills and state intact. `pipx install
76
76
  skillctl-secure` is also supported if you already use pipx.
77
77
 
78
+ ### Install automatically and launch
79
+
80
+ Download `skillctl.sh` (macOS/Linux) or `skillctl.ps1` (Windows). Each launcher is
81
+ self-contained and can live outside the repository. On first use it installs uv,
82
+ Python, and skillctl as needed, then starts the application. Later runs start the
83
+ installed version without checking for updates or requiring an internet connection.
84
+
85
+ ```bash
86
+ sh ./skillctl.sh
87
+ sh ./skillctl.sh --version
88
+ ```
89
+
90
+ ```powershell
91
+ powershell -NoProfile -ExecutionPolicy Bypass -File .\skillctl.ps1
92
+ ```
93
+
94
+ Arguments are passed to skillctl. Run `uv tool upgrade skillctl-secure` when you want
95
+ to update. The launcher uses uv's tool directory, so it also works before opening a
96
+ new terminal to refresh PATH. `install.sh` and `install.ps1` remain install/update-only.
97
+
78
98
  ### Optional standalone executables
79
99
 
80
100
  Self-contained native executables remain an optional release channel, enabled by
@@ -51,6 +51,26 @@ uv tool uninstall skillctl-secure
51
51
  Uninstalling the application leaves your skills and state intact. `pipx install
52
52
  skillctl-secure` is also supported if you already use pipx.
53
53
 
54
+ ### Install automatically and launch
55
+
56
+ Download `skillctl.sh` (macOS/Linux) or `skillctl.ps1` (Windows). Each launcher is
57
+ self-contained and can live outside the repository. On first use it installs uv,
58
+ Python, and skillctl as needed, then starts the application. Later runs start the
59
+ installed version without checking for updates or requiring an internet connection.
60
+
61
+ ```bash
62
+ sh ./skillctl.sh
63
+ sh ./skillctl.sh --version
64
+ ```
65
+
66
+ ```powershell
67
+ powershell -NoProfile -ExecutionPolicy Bypass -File .\skillctl.ps1
68
+ ```
69
+
70
+ Arguments are passed to skillctl. Run `uv tool upgrade skillctl-secure` when you want
71
+ to update. The launcher uses uv's tool directory, so it also works before opening a
72
+ new terminal to refresh PATH. `install.sh` and `install.ps1` remain install/update-only.
73
+
54
74
  ### Optional standalone executables
55
75
 
56
76
  Self-contained native executables remain an optional release channel, enabled by
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "skillctl-secure"
3
- version = "0.28.0"
3
+ version = "0.28.2"
4
4
  description = "Package manager, trust layer, and portability layer for Agent Skills"
5
5
  readme = "README.md"
6
6
  license = "Apache-2.0"
@@ -0,0 +1 @@
1
+ __version__ = "0.28.2"
@@ -14,17 +14,6 @@ Profile = desired skill-set template
14
14
  Environment = isolated installed toolbox instance
15
15
  id="table-hosts"
16
16
 
17
- with Horizontal(id="nav-actions-primary"):
18
- yield Button("Help", id="btn-help")
19
- yield Button("Doctor", id="btn-doctor")
20
- yield Button("Policy", id="btn-policy")
21
- with Horizontal(id="nav-actions-secondary"):
22
- yield Button("Toolbox", id="btn-toolbox")
23
- yield Button("Permissions", id="btn-permissions")
24
- yield Button("Hosts", id="btn-hosts")
25
- with Horizontal(id="skill-actions"):
26
- with Horizontal(id="environment-actions-primary"):
27
- with Horizontal(id="environment-actions-secondary"):
28
17
  """
29
18
 
30
19
  from pathlib import Path
@@ -177,6 +166,10 @@ def _apply_responsive_pane_widths(self, width: int) -> None:
177
166
 
178
167
  def _responsive_on_resize(self, event) -> None:
179
168
  _apply_responsive_pane_widths(self, event.size.width)
169
+ try:
170
+ self.query_one("#navigation").set_class(event.size.width < 80, "narrow")
171
+ except (ScreenStackError, NoMatches):
172
+ return
180
173
 
181
174
 
182
175
  def _update_audit_activity(self, current: str | None = None) -> None:
@@ -186,8 +179,7 @@ def _update_audit_activity(self, current: str | None = None) -> None:
186
179
  done = self.auto_audit_done
187
180
  total = self.auto_audit_total
188
181
  frame = _spinner_frames[done % len(_spinner_frames)]
189
- current_text = f" • {current}" if current else ""
190
- self.sub_title = f"{_base_sub_title} | {frame} Auditing {done}/{total}{current_text} • background • UI interactive"
182
+ self.sub_title = f"{_base_sub_title} | {frame} Auditing {done}/{total}"
191
183
 
192
184
 
193
185
  @work(thread=True, exclusive=True, group="catalog-audit")
@@ -172,31 +172,33 @@ class HelpScreen(ModalScreen[None]):
172
172
 
173
173
  class SkillCtlTUI(App):
174
174
  TITLE = "skillctl"
175
- SUB_TITLE = f"Skills • Collections • Workbenches | v{__version__}"
175
+ SUB_TITLE = f"v{__version__}"
176
176
 
177
177
  CSS = """
178
- #summary { height: 3; padding: 0 2; border-bottom: solid $panel; }
179
- #search { margin: 0 2; }
180
- #sections { height: 2; }
178
+ #summary { height: auto; padding: 0 1; color: $text-muted; }
179
+ #navigation { height: 2; }
180
+ #search { width: 32; height: 1; min-height: 1; margin: 0 1 0 2; padding: 0 1; border: none; }
181
+ #search:focus { background: $boost; }
182
+ #sections { width: 1fr; height: 2; }
183
+ #navigation.narrow { layout: vertical; height: 4; }
184
+ #navigation.narrow #sections { width: 100%; }
185
+ #navigation.narrow #search { width: 1fr; margin: 0 1; }
181
186
  #body { height: 1fr; }
182
187
  #catalog { width: 2fr; }
183
188
  #detail-column { width: 3fr; display: none; }
184
189
  #detail-column.open { display: block; }
185
190
  #btn-close-detail { height: 3; width: 100%; }
186
- #global-actions { height: 6; }
187
- #global-actions > Horizontal { height: 3; }
188
- #global-actions > Horizontal > Horizontal { width: 1fr; }
191
+ #global-actions { height: 4; }
192
+ #global-actions > Horizontal { width: 1fr; height: 4; border-top: solid $panel; }
189
193
  #detail { height: 1fr; padding: 1 2; border: solid $accent; overflow-y: auto; }
190
- #nav-actions-primary, #nav-actions-secondary, #nav-actions-tertiary, #source-actions,
194
+ #manage-actions, #inspect-actions,
191
195
  #skill-actions, #environment-actions-primary, #environment-actions-secondary {
192
196
  height: 3;
193
197
  padding: 0 1;
194
198
  align-horizontal: left;
195
199
  }
196
200
  #skill-actions { border-bottom: solid $panel; height: 4; }
197
- #nav-actions-primary Button,
198
- #nav-actions-secondary Button,
199
- #nav-actions-tertiary Button, #source-actions Button,
201
+ #manage-actions Button, #inspect-actions Button,
200
202
  #skill-actions Button,
201
203
  #environment-actions-primary Button,
202
204
  #environment-actions-secondary Button { width: 1fr; min-width: 0; margin: 0; padding: 0 1; }
@@ -256,8 +258,9 @@ class SkillCtlTUI(App):
256
258
  def compose(self) -> ComposeResult:
257
259
  yield Header()
258
260
  yield Static("", id="summary", markup=True)
259
- yield Input(placeholder="Search skills, descriptions, categories, collections… [/]", id="search")
260
- yield Tabs(*(Tab(label, id="section-" + key) for key, label in (("home", "Home"), ("skills", "Skills"), ("reviews", "Reviews"), ("organize", "Organize"), ("system", "System"))), id="sections")
261
+ with Horizontal(id="navigation"):
262
+ yield Tabs(*(Tab(label, id="section-" + key) for key, label in (("home", "Home"), ("skills", "Skills"), ("reviews", "Reviews"), ("organize", "Organize"), ("system", "System"))), id="sections")
263
+ yield Input(placeholder="Search… [/]", id="search", tooltip="Search skills, descriptions, categories, and collections. Press / to focus.")
261
264
  with Horizontal(id="body"):
262
265
  with TabbedContent(id="catalog"):
263
266
  with TabPane("Home", id="home"):
@@ -310,25 +313,17 @@ class SkillCtlTUI(App):
310
313
  with Horizontal(id="environment-actions-secondary"):
311
314
  yield Button("Bind Runtime", id="btn-runtime-bind")
312
315
  yield Button("Unbind Runtime", id="btn-runtime-unbind")
313
- with Vertical(id="global-actions"):
314
- with Horizontal():
315
- with Horizontal(id="nav-actions-primary"):
316
- yield Button("Help", id="btn-help")
317
- yield Button("Doctor", id="btn-doctor")
318
- yield Button("Policy", id="btn-policy")
319
- with Horizontal(id="nav-actions-secondary"):
320
- yield Button("Toolbox", id="btn-toolbox")
321
- yield Button("Permissions", id="btn-permissions")
322
- yield Button("Hosts", id="btn-hosts")
323
- with Horizontal():
324
- with Horizontal(id="nav-actions-tertiary"):
325
- yield Button("Publishers", id="btn-publishers")
326
- yield Button("Environments", id="btn-environments")
327
- yield Button("Update all", id="btn-update-all", variant="success")
328
- with Horizontal(id="source-actions"):
329
- yield Button("New Env", id="btn-new-env")
330
- yield Button("Add Source", id="btn-add-source")
331
- yield Button("Pages", id="btn-pages")
316
+ with Horizontal(id="global-actions"):
317
+ with Horizontal(id="manage-actions") as manage:
318
+ manage.border_title = "Manage"
319
+ yield Button("Add Source", id="btn-add-source")
320
+ yield Button("New Env", id="btn-new-env")
321
+ yield Button("Update all", id="btn-update-all", variant="success")
322
+ with Horizontal(id="inspect-actions") as inspect:
323
+ inspect.border_title = "Inspect"
324
+ yield Button("Run checks", id="btn-doctor", tooltip="Rerun Doctor diagnostics")
325
+ yield Button("Context", id="btn-context", tooltip="Inspect installed skill token estimates")
326
+ yield Button("Help", id="btn-help")
332
327
  yield Log(id="log", highlight=True)
333
328
  yield Footer()
334
329
 
@@ -757,12 +752,6 @@ class SkillCtlTUI(App):
757
752
  uninstall=self.query_one("#btn-uninstall", Button)
758
753
  add_source=self.query_one("#btn-add-source", Button)
759
754
  doctor=self.query_one("#btn-doctor", Button)
760
- policy=self.query_one("#btn-policy", Button)
761
- toolbox=self.query_one("#btn-toolbox", Button)
762
- permissions=self.query_one("#btn-permissions", Button)
763
- hosts=self.query_one("#btn-hosts", Button)
764
- publishers=self.query_one("#btn-publishers", Button)
765
- environments=self.query_one("#btn-environments", Button)
766
755
  new_env=self.query_one("#btn-new-env", Button)
767
756
  help_btn=self.query_one("#btn-help", Button)
768
757
  env_activate=self.query_one("#btn-env-activate", Button)
@@ -774,12 +763,6 @@ class SkillCtlTUI(App):
774
763
  add_source.display=True
775
764
  add_source.disabled=False
776
765
  doctor.display=True; doctor.disabled=False
777
- policy.display=True; policy.disabled=False
778
- toolbox.display=True; toolbox.disabled=False
779
- permissions.display=True; permissions.disabled=False
780
- hosts.display=True; hosts.disabled=False
781
- publishers.display=True; publishers.disabled=False
782
- environments.display=True; environments.disabled=False
783
766
  new_env.display=True; new_env.disabled=False
784
767
  help_btn.display=True; help_btn.disabled=False
785
768
  for button in (env_activate,env_clone,env_rename,env_delete,runtime_bind,runtime_unbind):
@@ -787,11 +770,12 @@ class SkillCtlTUI(App):
787
770
  button.disabled = self.selected_kind != "environment"
788
771
  for row in ("environment-actions-primary", "environment-actions-secondary"):
789
772
  self.query_one(f"#{row}").display = self.selected_kind == "environment"
790
- self.query_one("#skill-actions").display = installed is not None or self.selected_kind == "skill"
773
+ reviewing = self.query_one("#catalog", TabbedContent).active == "reviews"
774
+ self.query_one("#skill-actions").display = not reviewing and (installed is not None or self.selected_kind == "skill")
791
775
  install.display=True; update.display=True; uninstall.display=True
792
- install.disabled = installed is not False
793
- update.disabled = installed is not True
794
- uninstall.disabled = installed is not True
776
+ install.disabled = reviewing or installed is not False
777
+ update.disabled = reviewing or installed is not True
778
+ uninstall.disabled = reviewing or installed is not True
795
779
 
796
780
  def _show_dashboard(self) -> None:
797
781
  self._update_skill_action_buttons(None)
@@ -1272,18 +1256,6 @@ class SkillCtlTUI(App):
1272
1256
  # Buttons inside modal screens are handled by their own screens.
1273
1257
  if event.button.id == "btn-doctor":
1274
1258
  self.action_doctor()
1275
- elif event.button.id == "btn-policy":
1276
- self.action_policy_view()
1277
- elif event.button.id == "btn-toolbox":
1278
- self.action_toolbox_lock()
1279
- elif event.button.id == "btn-permissions":
1280
- self.action_permissions_view()
1281
- elif event.button.id == "btn-hosts":
1282
- self.action_hosts_view()
1283
- elif event.button.id == "btn-publishers":
1284
- self.action_publishers_view()
1285
- elif event.button.id == "btn-environments":
1286
- self.action_environments_view()
1287
1259
  elif event.button.id == "btn-new-env":
1288
1260
  self.action_new_environment()
1289
1261
  elif event.button.id == "btn-help":
@@ -1302,8 +1274,8 @@ class SkillCtlTUI(App):
1302
1274
  self.action_unbind_runtime()
1303
1275
  elif event.button.id == "btn-add-source":
1304
1276
  self.action_add_catalog()
1305
- elif event.button.id == "btn-pages":
1306
- self.action_pages()
1277
+ elif event.button.id == "btn-context":
1278
+ self.action_context()
1307
1279
  elif event.button.id == "btn-install":
1308
1280
  self.action_install()
1309
1281
  elif event.button.id == "btn-update-all":
@@ -1323,6 +1295,10 @@ class SkillCtlTUI(App):
1323
1295
  from .section_navigation import activate_section
1324
1296
  activate_section(self, event)
1325
1297
 
1298
+ def action_context(self) -> None:
1299
+ from .context_tui import ContextScreen
1300
+ self.push_screen(ContextScreen(self.manager))
1301
+
1326
1302
  def action_pages(self) -> None:
1327
1303
  from .navigation_tui import PageChooser
1328
1304
  catalog = self.query_one('#catalog', TabbedContent)
@@ -1330,8 +1306,7 @@ class SkillCtlTUI(App):
1330
1306
  pages.insert(3, ('context-cost', 'Context — installed token estimates'))
1331
1307
  def navigate(page):
1332
1308
  if page == 'context-cost':
1333
- from .context_tui import ContextScreen
1334
- self.push_screen(ContextScreen(self.manager))
1309
+ self.action_context()
1335
1310
  elif page:
1336
1311
  self.query_one('#catalog', TabbedContent).active = page
1337
1312
  self.push_screen(PageChooser(pages), navigate)
@@ -48,20 +48,16 @@ def install_async_refresh(SkillCtlTUI, original_action_refresh) -> None:
48
48
  ready_collections = sum(1 for row in collection_status.values() if row["complete"])
49
49
  workbenches = m.workbenches()
50
50
 
51
- audit_progress = (
52
- f" Auto-audit [b]{self.auto_audit_done}/{self.auto_audit_total}[/b]"
53
- if self.auto_audit_running else ""
54
- )
55
51
  from .context_cost import installed_context, total_label
56
52
  context = installed_context(m)
57
53
  context_label = total_label(context)
58
54
  summary = (
59
- f"[b]skillctl[/b] Env [b]{m.active_environment}[/b] Installed [b]{installed_count}[/b] "
55
+ f"Env [b]{escape(str(m.active_environment))}[/b] Installed [b]{installed_count}[/b] "
60
56
  f"Available [b]{len(statuses)}[/b] Updates [b]{update_count}[/b] "
61
- f"Audit HIGH [b]{high_count}[/b] Collections [b]{ready_collections}/{len(collections)} fully installed[/b]"
62
- f"{audit_progress}\n"
63
- f"Skill metadata {context_label} tokens (est.) • Pages → Context"
64
- + (" • Filter active" if filter_text else "")
57
+ f"Audit HIGH [b]{high_count}[/b]\n"
58
+ f"[dim]Collections {ready_collections}/{len(collections)} fully installed • "
59
+ f"Skill metadata {context_label} tokens (est.) • Context[/dim]"
60
+ + (" [dim]• Filter active[/dim]" if filter_text else "")
65
61
  )
66
62
 
67
63
  home_rows = [("Action", "Add a skill", "ready", "Press n or click Add Source to inspect a Git skill source", "home:add")]
@@ -116,7 +112,7 @@ def install_async_refresh(SkillCtlTUI, original_action_refresh) -> None:
116
112
  dashboard = (
117
113
  "[b]Dashboard[/b]\n\n"
118
114
  f"Skills configured: {len(statuses)}\nInstalled: {installed_count}\nUpdates available: {update_count}\n"
119
- f"Installed skill metadata: {context_label} tokens (estimated; host-dependent)\nPages → Context shows the per-skill breakdown.\n"
115
+ f"Installed skill metadata: {context_label} tokens (estimated; host-dependent)\nContext shows the per-skill breakdown.\n"
120
116
  f"Custom/local: {sum(1 for s in statuses if s.custom)}\nAudit HIGH findings: {high_count}\n"
121
117
  f"Collections fully installed: {ready_collections}/{len(collections)}\nActive environment: {m.active_environment}\n\n"
122
118
  "[dim]Diagnostics, policy, permissions, publishers, hosts, profiles and environments hydrate when opened.[/dim]\n\n"
@@ -1 +0,0 @@
1
- __version__ = "0.28.0"