oasr 0.4.1__tar.gz → 0.5.0__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 (150) hide show
  1. {oasr-0.4.1 → oasr-0.5.0}/CHANGELOG.md +50 -0
  2. {oasr-0.4.1 → oasr-0.5.0}/PKG-INFO +1 -1
  3. {oasr-0.4.1 → oasr-0.5.0}/docs/commands/.INDEX.md +4 -2
  4. oasr-0.5.0/docs/commands/CLEAN.md +13 -0
  5. {oasr-0.4.1 → oasr-0.5.0}/docs/commands/CONFIG.md +57 -0
  6. {oasr-0.4.1 → oasr-0.5.0}/docs/commands/EXEC.md +172 -0
  7. {oasr-0.4.1 → oasr-0.5.0}/docs/commands/REGISTRY.md +36 -0
  8. oasr-0.5.0/docs/config.example.toml +220 -0
  9. {oasr-0.4.1 → oasr-0.5.0}/pyproject.toml +1 -1
  10. {oasr-0.4.1 → oasr-0.5.0}/src/cli.py +1 -1
  11. oasr-0.5.0/src/commands/clean.py +30 -0
  12. {oasr-0.4.1 → oasr-0.5.0}/src/commands/exec.py +46 -0
  13. {oasr-0.4.1 → oasr-0.5.0}/src/commands/registry.py +144 -0
  14. {oasr-0.4.1 → oasr-0.5.0}/src/config/__init__.py +10 -0
  15. oasr-0.5.0/src/config/defaults.py +40 -0
  16. oasr-0.5.0/src/config/schema.py +73 -0
  17. oasr-0.5.0/src/policy/__init__.py +50 -0
  18. oasr-0.5.0/src/policy/defaults.py +27 -0
  19. oasr-0.5.0/src/policy/enforcement.py +98 -0
  20. oasr-0.5.0/src/policy/profile.py +185 -0
  21. {oasr-0.4.1 → oasr-0.5.0}/tests/test_config.py +121 -0
  22. {oasr-0.4.1 → oasr-0.5.0}/tests/test_exec.py +44 -4
  23. oasr-0.5.0/tests/test_policy_enforcement.py +158 -0
  24. oasr-0.5.0/tests/test_policy_profile.py +184 -0
  25. {oasr-0.4.1 → oasr-0.5.0}/uv.lock +1 -1
  26. oasr-0.4.1/docs/commands/CLEAN.md +0 -11
  27. oasr-0.4.1/doctor/SKILL.md +0 -35
  28. oasr-0.4.1/doctor/assets/schemas/session.schema.yaml +0 -87
  29. oasr-0.4.1/doctor/assets/schemas/treatment.schema.yaml +0 -70
  30. oasr-0.4.1/doctor/references/00_ROUTER.md +0 -104
  31. oasr-0.4.1/doctor/references/01_SUMMARY.md +0 -44
  32. oasr-0.4.1/doctor/references/02_TRIGGERS.md +0 -40
  33. oasr-0.4.1/doctor/references/03_ALWAYS.md +0 -43
  34. oasr-0.4.1/doctor/references/04_NEVER.md +0 -45
  35. oasr-0.4.1/doctor/references/05_PROCEDURE.md +0 -99
  36. oasr-0.4.1/doctor/references/06_FAILURES.md +0 -77
  37. oasr-0.4.1/doctor/scripts/include/.doctor/session.yaml +0 -11
  38. oasr-0.4.1/doctor/scripts/include/doctor_cli.py +0 -357
  39. oasr-0.4.1/doctor/scripts/include/doctor_parse.py +0 -348
  40. oasr-0.4.1/doctor/scripts/include/pyproject.toml +0 -12
  41. oasr-0.4.1/doctor/scripts/include/uv.lock +0 -78
  42. oasr-0.4.1/doctor/scripts/router_checks.sh +0 -87
  43. oasr-0.4.1/doctor/scripts/skill.ps1 +0 -65
  44. oasr-0.4.1/doctor/scripts/skill.sh +0 -57
  45. oasr-0.4.1/src/commands/clean.py +0 -155
  46. oasr-0.4.1/src/config/defaults.py +0 -16
  47. oasr-0.4.1/src/config/schema.py +0 -36
  48. {oasr-0.4.1 → oasr-0.5.0}/.gitignore +0 -0
  49. {oasr-0.4.1 → oasr-0.5.0}/CONTRIBUTING.md +0 -0
  50. {oasr-0.4.1 → oasr-0.5.0}/LICENSE +0 -0
  51. {oasr-0.4.1 → oasr-0.5.0}/NOTICE +0 -0
  52. {oasr-0.4.1 → oasr-0.5.0}/README.md +0 -0
  53. {oasr-0.4.1 → oasr-0.5.0}/docs/.INDEX.md +0 -0
  54. {oasr-0.4.1 → oasr-0.5.0}/docs/.images/adapter.png +0 -0
  55. {oasr-0.4.1 → oasr-0.5.0}/docs/.images/add-glob.png +0 -0
  56. {oasr-0.4.1 → oasr-0.5.0}/docs/.images/add-remote.png +0 -0
  57. {oasr-0.4.1 → oasr-0.5.0}/docs/.images/add.png +0 -0
  58. {oasr-0.4.1 → oasr-0.5.0}/docs/.images/find-add.png +0 -0
  59. {oasr-0.4.1 → oasr-0.5.0}/docs/.images/find.png +0 -0
  60. {oasr-0.4.1 → oasr-0.5.0}/docs/.images/help.png +0 -0
  61. {oasr-0.4.1 → oasr-0.5.0}/docs/.images/info.png +0 -0
  62. {oasr-0.4.1 → oasr-0.5.0}/docs/.images/list.png +0 -0
  63. {oasr-0.4.1 → oasr-0.5.0}/docs/.images/rm-glob.png +0 -0
  64. {oasr-0.4.1 → oasr-0.5.0}/docs/.images/rm.png +0 -0
  65. {oasr-0.4.1 → oasr-0.5.0}/docs/.images/status.png +0 -0
  66. {oasr-0.4.1 → oasr-0.5.0}/docs/.images/sync-update.png +0 -0
  67. {oasr-0.4.1 → oasr-0.5.0}/docs/.images/sync.png +0 -0
  68. {oasr-0.4.1 → oasr-0.5.0}/docs/.images/use.png +0 -0
  69. {oasr-0.4.1 → oasr-0.5.0}/docs/QUICKSTART.md +0 -0
  70. {oasr-0.4.1 → oasr-0.5.0}/docs/commands/ADAPTER.md +0 -0
  71. {oasr-0.4.1 → oasr-0.5.0}/docs/commands/ADD.md +0 -0
  72. {oasr-0.4.1 → oasr-0.5.0}/docs/commands/CLONE.md +0 -0
  73. {oasr-0.4.1 → oasr-0.5.0}/docs/commands/DIFF.md +0 -0
  74. {oasr-0.4.1 → oasr-0.5.0}/docs/commands/FIND.md +0 -0
  75. {oasr-0.4.1 → oasr-0.5.0}/docs/commands/HELP.md +0 -0
  76. {oasr-0.4.1 → oasr-0.5.0}/docs/commands/INFO.md +0 -0
  77. {oasr-0.4.1 → oasr-0.5.0}/docs/commands/LIST.md +0 -0
  78. {oasr-0.4.1 → oasr-0.5.0}/docs/commands/RM.md +0 -0
  79. {oasr-0.4.1 → oasr-0.5.0}/docs/commands/ROOT.md +0 -0
  80. {oasr-0.4.1 → oasr-0.5.0}/docs/commands/STATUS.md +0 -0
  81. {oasr-0.4.1 → oasr-0.5.0}/docs/commands/SYNC.md +0 -0
  82. {oasr-0.4.1 → oasr-0.5.0}/docs/commands/UPDATE.md +0 -0
  83. {oasr-0.4.1 → oasr-0.5.0}/docs/commands/USE.md +0 -0
  84. {oasr-0.4.1 → oasr-0.5.0}/docs/commands/VALIDATE.md +0 -0
  85. {oasr-0.4.1 → oasr-0.5.0}/docs/validation/.INDEX.md +0 -0
  86. {oasr-0.4.1 → oasr-0.5.0}/docs/validation/ERRORS.md +0 -0
  87. {oasr-0.4.1 → oasr-0.5.0}/docs/validation/INFO.md +0 -0
  88. {oasr-0.4.1 → oasr-0.5.0}/docs/validation/RULES.md +0 -0
  89. {oasr-0.4.1 → oasr-0.5.0}/docs/validation/WARNINGS.md +0 -0
  90. {oasr-0.4.1 → oasr-0.5.0}/install.ps1 +0 -0
  91. {oasr-0.4.1 → oasr-0.5.0}/install.sh +0 -0
  92. {oasr-0.4.1 → oasr-0.5.0}/llms.txt +0 -0
  93. {oasr-0.4.1 → oasr-0.5.0}/scripts/README.md +0 -0
  94. {oasr-0.4.1 → oasr-0.5.0}/scripts/fix.sh +0 -0
  95. {oasr-0.4.1 → oasr-0.5.0}/scripts/lint.sh +0 -0
  96. {oasr-0.4.1 → oasr-0.5.0}/scripts/test.sh +0 -0
  97. {oasr-0.4.1 → oasr-0.5.0}/src/__init__.py +0 -0
  98. {oasr-0.4.1 → oasr-0.5.0}/src/__main__.py +0 -0
  99. {oasr-0.4.1 → oasr-0.5.0}/src/adapter.py +0 -0
  100. {oasr-0.4.1 → oasr-0.5.0}/src/adapters/__init__.py +0 -0
  101. {oasr-0.4.1 → oasr-0.5.0}/src/adapters/base.py +0 -0
  102. {oasr-0.4.1 → oasr-0.5.0}/src/adapters/claude.py +0 -0
  103. {oasr-0.4.1 → oasr-0.5.0}/src/adapters/codex.py +0 -0
  104. {oasr-0.4.1 → oasr-0.5.0}/src/adapters/copilot.py +0 -0
  105. {oasr-0.4.1 → oasr-0.5.0}/src/adapters/cursor.py +0 -0
  106. {oasr-0.4.1 → oasr-0.5.0}/src/adapters/windsurf.py +0 -0
  107. {oasr-0.4.1 → oasr-0.5.0}/src/agents/__init__.py +0 -0
  108. {oasr-0.4.1 → oasr-0.5.0}/src/agents/base.py +0 -0
  109. {oasr-0.4.1 → oasr-0.5.0}/src/agents/claude.py +0 -0
  110. {oasr-0.4.1 → oasr-0.5.0}/src/agents/codex.py +0 -0
  111. {oasr-0.4.1 → oasr-0.5.0}/src/agents/copilot.py +0 -0
  112. {oasr-0.4.1 → oasr-0.5.0}/src/agents/opencode.py +0 -0
  113. {oasr-0.4.1 → oasr-0.5.0}/src/agents/registry.py +0 -0
  114. {oasr-0.4.1 → oasr-0.5.0}/src/commands/__init__.py +0 -0
  115. {oasr-0.4.1 → oasr-0.5.0}/src/commands/adapter.py +0 -0
  116. {oasr-0.4.1 → oasr-0.5.0}/src/commands/add.py +0 -0
  117. {oasr-0.4.1 → oasr-0.5.0}/src/commands/clone.py +0 -0
  118. {oasr-0.4.1 → oasr-0.5.0}/src/commands/config.py +0 -0
  119. {oasr-0.4.1 → oasr-0.5.0}/src/commands/diff.py +0 -0
  120. {oasr-0.4.1 → oasr-0.5.0}/src/commands/find.py +0 -0
  121. {oasr-0.4.1 → oasr-0.5.0}/src/commands/help.py +0 -0
  122. {oasr-0.4.1 → oasr-0.5.0}/src/commands/info.py +0 -0
  123. {oasr-0.4.1 → oasr-0.5.0}/src/commands/list.py +0 -0
  124. {oasr-0.4.1 → oasr-0.5.0}/src/commands/rm.py +0 -0
  125. {oasr-0.4.1 → oasr-0.5.0}/src/commands/status.py +0 -0
  126. {oasr-0.4.1 → oasr-0.5.0}/src/commands/sync.py +0 -0
  127. {oasr-0.4.1 → oasr-0.5.0}/src/commands/update.py +0 -0
  128. {oasr-0.4.1 → oasr-0.5.0}/src/commands/use.py +0 -0
  129. {oasr-0.4.1 → oasr-0.5.0}/src/commands/validate.py +0 -0
  130. {oasr-0.4.1 → oasr-0.5.0}/src/discovery.py +0 -0
  131. {oasr-0.4.1 → oasr-0.5.0}/src/manifest.py +0 -0
  132. {oasr-0.4.1 → oasr-0.5.0}/src/registry.py +0 -0
  133. {oasr-0.4.1 → oasr-0.5.0}/src/remote.py +0 -0
  134. {oasr-0.4.1 → oasr-0.5.0}/src/skillcopy/__init__.py +0 -0
  135. {oasr-0.4.1 → oasr-0.5.0}/src/skillcopy/local.py +0 -0
  136. {oasr-0.4.1 → oasr-0.5.0}/src/skillcopy/remote.py +0 -0
  137. {oasr-0.4.1 → oasr-0.5.0}/src/tracking.py +0 -0
  138. {oasr-0.4.1 → oasr-0.5.0}/src/validate.py +0 -0
  139. {oasr-0.4.1 → oasr-0.5.0}/tests/conftest.py +0 -0
  140. {oasr-0.4.1 → oasr-0.5.0}/tests/test_adapters.py +0 -0
  141. {oasr-0.4.1 → oasr-0.5.0}/tests/test_agents.py +0 -0
  142. {oasr-0.4.1 → oasr-0.5.0}/tests/test_clone.py +0 -0
  143. {oasr-0.4.1 → oasr-0.5.0}/tests/test_config_command.py +0 -0
  144. {oasr-0.4.1 → oasr-0.5.0}/tests/test_copy.py +0 -0
  145. {oasr-0.4.1 → oasr-0.5.0}/tests/test_help.py +0 -0
  146. {oasr-0.4.1 → oasr-0.5.0}/tests/test_list.py +0 -0
  147. {oasr-0.4.1 → oasr-0.5.0}/tests/test_multi_skill.py +0 -0
  148. {oasr-0.4.1 → oasr-0.5.0}/tests/test_remote.py +0 -0
  149. {oasr-0.4.1 → oasr-0.5.0}/tests/test_tracking.py +0 -0
  150. {oasr-0.4.1 → oasr-0.5.0}/tests/test_use_glob.py +0 -0
@@ -4,6 +4,56 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
5
5
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [0.5.0] - 2026-02-02
8
+
9
+ ### Added
10
+ - **🔒 Execution Policy System** — Host-level security boundaries for `oasr exec`
11
+ - Policy profiles define what agents can and cannot do
12
+ - Conservative safe defaults (fail closed)
13
+ - User-defined custom profiles in `config.toml`
14
+ - Pre-execution confirmation for risky operations
15
+ - Risk triggers: stdin, file prompts, non-safe profiles, network/env/shell access
16
+ - **New CLI flags for `oasr exec`**:
17
+ - `--profile <name>` — Choose execution policy profile
18
+ - `-y/--yes` — Skip confirmation prompt
19
+ - `--confirm` — Force confirmation even for safe operations
20
+ - **Configuration support for policies**:
21
+ - `[oasr]` section with `default_profile` setting
22
+ - `[profiles.<name>]` tables for custom profiles
23
+ - Policy field validation in config schema
24
+ - Built-in "safe" profile with conservative defaults
25
+
26
+ ### Changed
27
+ - **Security model**: `oasr exec` now requires explicit confirmation for risky execution contexts
28
+ - **Config schema**: Extended to support execution policy profiles
29
+
30
+ ### Security
31
+ - **Prompt injection mitigation**: Policy enforcement reduces impact of malicious skill instructions
32
+ - **Sensitive file protection**: Default deny list includes `~/.ssh`, `~/.aws`, `~/.gnupg`, `.env`, etc.
33
+ - **Execution boundaries**: Clear limits on filesystem access, network, environment variables, and shell commands
34
+ - **User awareness**: Policy summary shown before risky executions
35
+ - **Fail-closed design**: Missing/malformed config falls back to safe defaults
36
+
37
+ ### Documentation
38
+ - **[EXEC.md](docs/commands/EXEC.md)**: Added comprehensive Security Model section
39
+ - **[CONFIG.md](docs/commands/CONFIG.md)**: Added Execution Policy Profiles documentation
40
+ - **Policy examples**: Multiple profile configurations for different use cases
41
+
42
+ ### Technical
43
+ - **New module**: `src/policy/` subpackage with clean API (Profile, load, assess_risk, prompt_confirmation)
44
+ - **41 new tests**: 30 policy tests + 11 config profile tests
45
+ - **Test coverage**: 187 total tests passing (all existing tests still pass)
46
+ - **Backward compatible**: No breaking changes to existing commands
47
+
48
+ ## [0.4.2] - 2026-02-01
49
+
50
+ ### Added
51
+ - **registry prune subcommand**: Added `oasr registry prune` to align with registry command taxonomy
52
+
53
+ ### Changed
54
+ - **clean command**: Deprecated `oasr clean` in favor of `oasr registry prune` (will be removed in v0.6.0)
55
+ - **documentation**: Updated REGISTRY.md with prune subcommand documentation and usage examples
56
+
7
57
  ## [0.4.1] - 2026-02-01
8
58
 
9
59
  ### Fixed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: oasr
3
- Version: 0.4.1
3
+ Version: 0.5.0
4
4
  Summary: CLI for managing agent skills across IDE integrations
5
5
  Project-URL: Homepage, https://github.com/jgodau/asr
6
6
  Project-URL: Repository, https://github.com/jgodau/asr
@@ -3,7 +3,7 @@
3
3
  ## Core Commands (v0.4.0)
4
4
 
5
5
  - [oasr](ROOT.md) - Global flags and options
6
- - [oasr registry](REGISTRY.md) - Manage skill registry (validate, add, remove, list, sync)
6
+ - [oasr registry](REGISTRY.md) - Manage skill registry (validate, add, remove, list, sync, prune)
7
7
  - [oasr diff](DIFF.md) - Show status of tracked skills
8
8
  - [oasr sync](SYNC.md) - Refresh outdated tracked skills
9
9
  - [oasr config](CONFIG.md) - Manage configuration (NEW in v0.4.0)
@@ -11,7 +11,6 @@
11
11
  - [oasr exec](EXEC.md) - Execute skills as CLI tools (NEW in v0.4.0)
12
12
  - [oasr find](FIND.md) - Find/discover skills in your file system
13
13
  - [oasr validate](VALIDATE.md) - Validate a skill
14
- - [oasr clean](CLEAN.md) - Clean up the registry
15
14
  - [oasr adapter](ADAPTER.md) - Generate IDE/Tooling adapters
16
15
  - [oasr update](UPDATE.md) - Update the `oasr` CLI
17
16
  - [oasr info](INFO.md) - Show detailed information about a skill
@@ -19,6 +18,9 @@
19
18
 
20
19
  ## Deprecated Commands
21
20
 
21
+ ### v0.4.1 Deprecations
22
+ - [oasr clean](CLEAN.md) - **Deprecated**, use `oasr registry prune` instead (will be removed in v0.6.0)
23
+
22
24
  ### v0.4.0 Deprecations
23
25
  - [oasr use](USE.md) - **Deprecated**, use `oasr clone` instead (will be removed in v0.5.0)
24
26
 
@@ -0,0 +1,13 @@
1
+ # `oasr clean` (DEPRECATED)
2
+
3
+ > **⚠️ Warning: This command is deprecated and will be removed in v0.6.0.**
4
+ > Use `oasr registry prune` instead.
5
+
6
+ Remove orphaned manifests and entries for missing skills.
7
+
8
+ ```bash
9
+ oasr clean # Shows deprecation warning
10
+ oasr registry prune # New command (recommended)
11
+ ```
12
+
13
+ This command now delegates to `oasr registry prune`. See [REGISTRY.md](./REGISTRY.md#oasr-registry-prune) for full documentation.
@@ -241,6 +241,63 @@ Configure a different agent:
241
241
  oasr config set agent copilot
242
242
  ```
243
243
 
244
+ ## Execution Policy Profiles (v0.5.0+)
245
+
246
+ Policy profiles define security boundaries for `oasr exec`. They control what agents can do during skill execution.
247
+
248
+ ### Default Profile
249
+
250
+ Set the default execution policy profile:
251
+
252
+ ```bash
253
+ oasr config set oasr.default_profile safe
254
+ ```
255
+
256
+ This determines which profile is used unless overridden with `--profile`.
257
+
258
+ ### Defining Custom Profiles
259
+
260
+ Add custom profiles to `~/.oasr/config.toml`:
261
+
262
+ ```toml
263
+ [oasr]
264
+ default_profile = "safe"
265
+
266
+ # Conservative default
267
+ [profiles.safe]
268
+ fs_read_roots = ["./"]
269
+ fs_write_roots = ["./out", "./.oasr"]
270
+ deny_paths = ["~/.ssh", "~/.aws", "~/.gnupg", ".env"]
271
+ allowed_commands = ["rg", "fd", "jq", "cat"]
272
+ deny_shell = true
273
+ network = false
274
+ allow_env = false
275
+
276
+ # Development profile (more permissive)
277
+ [profiles.dev]
278
+ fs_read_roots = ["./", "~/projects"]
279
+ fs_write_roots = ["./", "~/projects/output"]
280
+ deny_paths = ["~/.ssh", "~/.aws"]
281
+ allowed_commands = ["bash", "curl", "git", "python"]
282
+ deny_shell = false
283
+ network = true
284
+ allow_env = true
285
+ ```
286
+
287
+ ### Profile Settings Reference
288
+
289
+ | Setting | Type | Description |
290
+ |---------|------|-------------|
291
+ | `fs_read_roots` | list[string] | Allowed filesystem read locations |
292
+ | `fs_write_roots` | list[string] | Allowed filesystem write locations |
293
+ | `deny_paths` | list[string] | Explicitly denied paths |
294
+ | `allowed_commands` | list[string] | Permitted shell commands |
295
+ | `deny_shell` | bool | Deny all shell execution |
296
+ | `network` | bool | Allow network access |
297
+ | `allow_env` | bool | Allow environment variable access |
298
+
299
+ See [`oasr exec` documentation](EXEC.md#security-model) for detailed security model explanation.
300
+
244
301
  ## Advanced Usage
245
302
 
246
303
  ### Direct Config File Editing
@@ -2,6 +2,8 @@
2
2
 
3
3
  Execute skills as CLI tools from anywhere on your system. Run skills with agent-driven execution without needing to clone them first.
4
4
 
5
+ > **🔒 Security Note**: As of v0.5.0, `oasr exec` includes host-level execution policy enforcement to protect against prompt injection and unsafe agent behavior. See [Security Model](#security-model) below.
6
+
5
7
  ## Usage
6
8
 
7
9
  ```bash
@@ -13,6 +15,9 @@ oasr exec <skill-name> [options]
13
15
  - `-p, --prompt TEXT` — Inline prompt/instructions for the agent
14
16
  - `-i, --instructions FILE` — Read prompt from a file
15
17
  - `-a, --agent AGENT` — Override the default agent (codex, copilot, claude, opencode)
18
+ - `--profile PROFILE` — Use a specific execution policy profile (default: from config)
19
+ - `-y, --yes` — Skip confirmation prompt for risky operations
20
+ - `--confirm` — Force confirmation even for safe operations
16
21
 
17
22
  ## Features
18
23
 
@@ -311,6 +316,173 @@ This allows skills to:
311
316
  - Tracking skill versions
312
317
  - Working offline
313
318
 
319
+ ## Security Model
320
+
321
+ ### Overview
322
+
323
+ OASR enforces **host-level execution policies** to reduce the impact of prompt injection and unsafe agent behavior. Policies define what agents can and cannot do, protecting sensitive files and preventing unauthorized actions.
324
+
325
+ **Key Principles:**
326
+ - OASR does not judge skills
327
+ - OASR enforces user-defined host policy (execution ceilings)
328
+ - Skills and agents cannot override policy
329
+ - Policies stored in `~/.oasr/config.toml`
330
+ - Conservative defaults (fail closed)
331
+
332
+ ### Policy Profiles
333
+
334
+ Execution policies are organized into profiles. Each profile defines:
335
+
336
+ | Setting | Description | Safe Default |
337
+ |---------|-------------|--------------|
338
+ | `fs_read_roots` | Allowed read locations | `["./"]` |
339
+ | `fs_write_roots` | Allowed write locations | `["./out", "./.oasr"]` |
340
+ | `deny_paths` | Explicitly denied paths | `["~/.ssh", "~/.aws", "~/.gnupg", ".env"]` |
341
+ | `allowed_commands` | Permitted shell commands | `["rg", "fd", "jq", "cat"]` |
342
+ | `deny_shell` | Block shell execution | `true` |
343
+ | `network` | Allow network access | `false` |
344
+ | `allow_env` | Allow environment access | `false` |
345
+
346
+ ### Risk Triggers
347
+
348
+ OASR requires explicit confirmation when:
349
+
350
+ 1. **Input from stdin** (non-interactive/piped)
351
+ 2. **Prompt from file** (`-i/--instructions`)
352
+ 3. **Non-safe profile** in use
353
+ 4. **Environment access** enabled
354
+ 5. **Network access** enabled
355
+ 6. **Shell execution** allowed
356
+ 7. **Force confirmation** flag (`--confirm`)
357
+
358
+ ### Confirmation Flow
359
+
360
+ When risk triggers are detected:
361
+
362
+ ```
363
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
364
+ EXECUTION POLICY REVIEW
365
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
366
+ Skill: csv-analyzer
367
+ Agent: codex
368
+ Profile: safe
369
+ Network: denied
370
+ Environment: denied
371
+ Shell: denied
372
+ Allowed commands: rg, fd, jq, cat
373
+ Read roots: ./
374
+ Write roots: ./out, ./.oasr
375
+ Deny paths: ~/.ssh, ~/.aws, ~/.gnupg, ~/.config, .env
376
+
377
+ ⚠ This execution requires confirmation due to:
378
+ - Input from stdin (non-interactive)
379
+
380
+ Proceed? [y/N]
381
+ ```
382
+
383
+ **Default answer is No** (safe).
384
+
385
+ ### Configuration
386
+
387
+ Define profiles in `~/.oasr/config.toml`:
388
+
389
+ ```toml
390
+ [oasr]
391
+ default_profile = "safe"
392
+
393
+ [profiles.safe]
394
+ fs_read_roots = ["./"]
395
+ fs_write_roots = ["./out", "./.oasr"]
396
+ deny_paths = ["~/.ssh", "~/.aws", "~/.gnupg", "~/.config", ".env"]
397
+ allowed_commands = ["rg", "fd", "jq", "cat"]
398
+ deny_shell = true
399
+ network = false
400
+ allow_env = false
401
+
402
+ [profiles.dev]
403
+ # More permissive for development
404
+ network = true
405
+ allow_env = true
406
+ deny_shell = false
407
+ allowed_commands = ["bash", "curl", "git", "python", "node"]
408
+ ```
409
+
410
+ ### Usage Examples
411
+
412
+ #### Safe Default (No Confirmation)
413
+ ```bash
414
+ # Interactive prompt, safe profile
415
+ oasr exec csv-analyzer -p "Analyze data"
416
+ # No confirmation needed
417
+ ```
418
+
419
+ #### Stdin Triggers Confirmation
420
+ ```bash
421
+ # Non-interactive input
422
+ echo "data" | oasr exec csv-analyzer
423
+ # Requires confirmation (unless --yes)
424
+ ```
425
+
426
+ #### Skip Confirmation
427
+ ```bash
428
+ # Use --yes to bypass (use carefully!)
429
+ echo "data" | oasr exec csv-analyzer --yes
430
+ ```
431
+
432
+ #### Use Different Profile
433
+ ```bash
434
+ # Use 'dev' profile with more permissions
435
+ oasr exec api-tester -p "Run tests" --profile dev
436
+ ```
437
+
438
+ #### Force Confirmation
439
+ ```bash
440
+ # Force confirmation even if safe
441
+ oasr exec data-processor -p "Process" --confirm
442
+ ```
443
+
444
+ ### Best Practices
445
+
446
+ 1. **Use safe defaults**: Start with the built-in safe profile
447
+ 2. **Create custom profiles**: Define profiles for different trust levels
448
+ 3. **Be explicit with --yes**: Only skip confirmation when you understand the risks
449
+ 4. **Review policy before confirming**: Read the summary carefully
450
+ 5. **Protect sensitive paths**: Always include `~/.ssh`, `~/.aws`, etc. in `deny_paths`
451
+ 6. **Limit commands**: Only allow necessary commands in `allowed_commands`
452
+ 7. **Use profiles per context**: Different profiles for dev/prod/testing
453
+
454
+ ### What This Protects Against
455
+
456
+ ✅ **Prompt injection attempts** that try to access sensitive files
457
+ ✅ **Unsafe agent behavior** (network calls, shell execution)
458
+ ✅ **Accidental exposure** of credentials or secrets
459
+ ✅ **Unauthorized file access** outside allowed roots
460
+ ✅ **Malicious skill instructions** that exceed policy
461
+
462
+ ### What This Does NOT Do
463
+
464
+ ❌ NLP-based prompt injection detection
465
+ ❌ Prompt rewriting or sanitization
466
+ ❌ Skill correctness validation
467
+ ❌ Agent-specific permission models
468
+ ❌ Plan-gated execution (staged for future)
469
+
470
+ ### Limitations
471
+
472
+ - **Confirmation is on execution, not per-action**: Policy is checked before running, not during
473
+ - **Agent behavior is not monitored**: Once confirmed, agent runs with specified permissions
474
+ - **Trust required**: You must trust the agent CLI itself
475
+ - **File-level enforcement not yet implemented**: Path checks are advisory in v0.5.0
476
+
477
+ ### Future Enhancements
478
+
479
+ Planned for future releases:
480
+ - Plan-gated execution (structured plan approval)
481
+ - Runtime file access enforcement
482
+ - Command allowlist enforcement via executor
483
+ - Network access controls
484
+ - Real-time policy violations monitoring
485
+
314
486
  ## Configuration
315
487
 
316
488
  ### Set Default Agent
@@ -105,6 +105,40 @@ Syncing remote skills...
105
105
  Synced: 2 skills
106
106
  ```
107
107
 
108
+ ### `oasr registry prune`
109
+
110
+ Clean up corrupted/missing skills and orphaned artifacts:
111
+
112
+ ```bash
113
+ oasr registry prune # Interactive cleanup
114
+ oasr registry prune -y # Skip confirmation
115
+ oasr registry prune --dry-run # Show what would be cleaned
116
+ oasr registry prune --json # JSON output
117
+ ```
118
+
119
+ This command:
120
+ - Removes skills whose source files/URLs are no longer accessible
121
+ - Removes orphaned manifest files not in the registry
122
+ - Requires confirmation unless `-y` flag is used
123
+
124
+ **Example output:**
125
+ ```bash
126
+ $ oasr registry prune
127
+ Checking 3 remote skill(s)...
128
+ ↓ python-analyzer (checking GitHub...)
129
+ ✓ python-analyzer (checked)
130
+
131
+ The following will be cleaned:
132
+
133
+ Skills with missing sources:
134
+ ✗ old-skill (/path/to/missing)
135
+
136
+ Proceed with cleanup? [y/N] y
137
+ Removed skill: old-skill
138
+
139
+ Cleaned 1 skill(s), 0 manifest(s)
140
+ ```
141
+
108
142
  ## Migration from v0.2.0
109
143
 
110
144
  The v0.3.0 CLI taxonomy reorganizes commands under the `registry` subcommand:
@@ -117,3 +151,5 @@ The v0.3.0 CLI taxonomy reorganizes commands under the `registry` subcommand:
117
151
  | `oasr status` | `oasr registry -v` |
118
152
  | `oasr sync` (manifest validation) | `oasr registry` |
119
153
  | `oasr sync --update` (remote sync) | `oasr registry sync` |
154
+
155
+ **v0.4.1 update:** `oasr clean` → `oasr registry prune`
@@ -0,0 +1,220 @@
1
+ # OASR Configuration Example
2
+ # Location: ~/.oasr/config.toml
3
+ #
4
+ # This file demonstrates the configuration options for OASR v0.5.0+
5
+ # Copy relevant sections to your own config file.
6
+
7
+ # =============================================================================
8
+ # OASR Settings
9
+ # =============================================================================
10
+ [oasr]
11
+ # Default execution policy profile for 'oasr exec'
12
+ # Options: "safe" (default), or any custom profile name defined below
13
+ default_profile = "safe"
14
+
15
+ # =============================================================================
16
+ # Agent Configuration
17
+ # =============================================================================
18
+ [agent]
19
+ # Default agent for 'oasr exec' command
20
+ # Options: "codex", "copilot", "claude", "opencode", or null
21
+ default = "codex"
22
+
23
+ # =============================================================================
24
+ # Validation Settings
25
+ # =============================================================================
26
+ [validation]
27
+ # Maximum lines to show in skill reference output
28
+ reference_max_lines = 500
29
+
30
+ # Strict validation mode (fail on warnings)
31
+ strict = false
32
+
33
+ # =============================================================================
34
+ # Adapter Settings
35
+ # =============================================================================
36
+ [adapter]
37
+ # Default targets for 'oasr adapter' command
38
+ default_targets = ["cursor", "windsurf"]
39
+
40
+ # =============================================================================
41
+ # Execution Policy Profiles (v0.5.0+)
42
+ # =============================================================================
43
+ # Policy profiles define security boundaries for 'oasr exec'.
44
+ # They control what agents can do during skill execution.
45
+
46
+ # -----------------------------------------------------------------------------
47
+ # Safe Profile (Built-in Default)
48
+ # -----------------------------------------------------------------------------
49
+ # Conservative default with minimal permissions
50
+ [profiles.safe]
51
+ fs_read_roots = ["./"] # Only read from current directory
52
+ fs_write_roots = ["./out", "./.oasr"] # Limited write locations
53
+ deny_paths = [ # Always deny these paths
54
+ "~/.ssh",
55
+ "~/.aws",
56
+ "~/.gnupg",
57
+ "~/.config",
58
+ ".env",
59
+ "~/.bashrc",
60
+ "~/.zshrc",
61
+ "~/.profile",
62
+ ]
63
+ allowed_commands = ["rg", "fd", "jq", "cat"] # Read-only tools
64
+ deny_shell = true # No shell execution
65
+ network = false # No network access
66
+ allow_env = false # No environment variables
67
+
68
+ # -----------------------------------------------------------------------------
69
+ # Development Profile
70
+ # -----------------------------------------------------------------------------
71
+ # More permissive for development work
72
+ [profiles.dev]
73
+ fs_read_roots = ["./", "~/projects"]
74
+ fs_write_roots = ["./", "~/projects/output", "./build", "./dist"]
75
+ deny_paths = [
76
+ "~/.ssh", # Still protect SSH keys
77
+ "~/.aws", # Still protect AWS credentials
78
+ "~/.gnupg", # Still protect GPG keys
79
+ ]
80
+ allowed_commands = [
81
+ "bash", "sh", # Shell access
82
+ "curl", "wget", # Network tools
83
+ "git", # Version control
84
+ "python", "node", "go", # Programming languages
85
+ "npm", "pip", "cargo", # Package managers
86
+ "rg", "fd", "jq", # Search/parse tools
87
+ ]
88
+ deny_shell = false # Allow shell commands
89
+ network = true # Allow network access
90
+ allow_env = true # Allow environment variables
91
+
92
+ # -----------------------------------------------------------------------------
93
+ # Testing Profile
94
+ # -----------------------------------------------------------------------------
95
+ # Isolated profile for running tests
96
+ [profiles.test]
97
+ fs_read_roots = ["./tests", "./fixtures", "./test-data"]
98
+ fs_write_roots = ["./test-output", "./coverage", "./.pytest_cache"]
99
+ deny_paths = [
100
+ "~/.ssh",
101
+ "~/.aws",
102
+ "~/", # Deny entire home directory
103
+ ]
104
+ allowed_commands = [
105
+ "pytest", "coverage", # Python testing
106
+ "jest", "vitest", # JavaScript testing
107
+ "cargo", "go", # Other language test runners
108
+ "rg", "fd", # Search tools
109
+ ]
110
+ deny_shell = true
111
+ network = false # Tests should not need network
112
+ allow_env = false
113
+
114
+ # -----------------------------------------------------------------------------
115
+ # CI/CD Profile
116
+ # -----------------------------------------------------------------------------
117
+ # Profile for continuous integration environments
118
+ [profiles.ci]
119
+ fs_read_roots = ["./", "/tmp/ci"]
120
+ fs_write_roots = ["./build", "./dist", "./coverage", "/tmp/ci"]
121
+ deny_paths = [
122
+ "~/.ssh", # Protect credentials
123
+ "~/.aws", # (CI should use injected secrets)
124
+ ]
125
+ allowed_commands = [
126
+ "npm", "yarn", "pnpm",
127
+ "python", "pip",
128
+ "cargo", "go",
129
+ "git",
130
+ "docker", # Container builds
131
+ "kubectl", # Kubernetes
132
+ ]
133
+ deny_shell = false
134
+ network = true # May need to fetch dependencies
135
+ allow_env = true # CI environment variables needed
136
+
137
+ # -----------------------------------------------------------------------------
138
+ # Data Analysis Profile
139
+ # -----------------------------------------------------------------------------
140
+ # Profile for data science and analysis tasks
141
+ [profiles.analysis]
142
+ fs_read_roots = ["./data", "./datasets", "./notebooks"]
143
+ fs_write_roots = ["./output", "./reports", "./plots"]
144
+ deny_paths = [
145
+ "~/.ssh",
146
+ "~/.aws",
147
+ "~/.gnupg",
148
+ ]
149
+ allowed_commands = [
150
+ "python",
151
+ "jupyter",
152
+ "pandas",
153
+ "rg", "fd",
154
+ ]
155
+ deny_shell = false # May need Python subprocess
156
+ network = false # Analysis should be offline
157
+ allow_env = false
158
+
159
+ # -----------------------------------------------------------------------------
160
+ # Production Profile
161
+ # -----------------------------------------------------------------------------
162
+ # Extremely restrictive profile for production use
163
+ [profiles.production]
164
+ fs_read_roots = ["./"]
165
+ fs_write_roots = ["./logs"] # Only write logs
166
+ deny_paths = [
167
+ "~/.ssh",
168
+ "~/.aws",
169
+ "~/.gnupg",
170
+ "~/.config",
171
+ ".env",
172
+ "~/",
173
+ ]
174
+ allowed_commands = ["rg", "cat"] # Minimal read-only
175
+ deny_shell = true
176
+ network = false
177
+ allow_env = false
178
+
179
+ # =============================================================================
180
+ # Usage Examples
181
+ # =============================================================================
182
+ #
183
+ # Use default profile:
184
+ # oasr exec my-skill -p "prompt"
185
+ #
186
+ # Use specific profile:
187
+ # oasr exec my-skill -p "prompt" --profile dev
188
+ #
189
+ # Skip confirmation (use carefully!):
190
+ # echo "data" | oasr exec my-skill --yes
191
+ #
192
+ # Force confirmation:
193
+ # oasr exec my-skill -p "prompt" --confirm
194
+ #
195
+ # Set default profile:
196
+ # oasr config set oasr.default_profile dev
197
+ #
198
+ # =============================================================================
199
+ # Security Notes
200
+ # =============================================================================
201
+ #
202
+ # 1. Always protect sensitive directories in deny_paths:
203
+ # - ~/.ssh (SSH keys)
204
+ # - ~/.aws (AWS credentials)
205
+ # - ~/.gnupg (GPG keys)
206
+ # - .env (environment secrets)
207
+ #
208
+ # 2. Use the most restrictive profile that works for your use case
209
+ #
210
+ # 3. Create custom profiles for different trust levels:
211
+ # - "safe" for untrusted skills
212
+ # - "dev" for development
213
+ # - "ci" for automation
214
+ # - Custom profiles for specific projects
215
+ #
216
+ # 4. Review policy summary before confirming risky operations
217
+ #
218
+ # 5. Use --yes flag sparingly and only when you understand the risks
219
+ #
220
+ # =============================================================================
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "oasr"
7
- version = "0.4.1"
7
+ version = "0.5.0"
8
8
  description = "CLI for managing agent skills across IDE integrations"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -13,7 +13,7 @@ from pathlib import Path
13
13
  from commands import adapter, clean, clone, config, diff, exec, find, registry, sync, update, use, validate
14
14
  from commands import help as help_cmd
15
15
 
16
- __version__ = "0.4.1"
16
+ __version__ = "0.5.0"
17
17
 
18
18
 
19
19
  def main(argv: list[str] | None = None) -> int:
@@ -0,0 +1,30 @@
1
+ """`asr clean` command - DEPRECATED, use `oasr registry prune` instead."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ import sys
7
+
8
+
9
+ def register(subparsers) -> None:
10
+ p = subparsers.add_parser(
11
+ "clean",
12
+ help="(Deprecated) Clean up corrupted/missing skills - use 'oasr registry prune'",
13
+ )
14
+ p.add_argument("-y", "--yes", action="store_true", help="Skip confirmation prompt")
15
+ p.add_argument("--json", action="store_true", help="Output in JSON format")
16
+ p.add_argument("--dry-run", action="store_true", help="Show what would be cleaned without doing it")
17
+ p.set_defaults(func=run)
18
+
19
+
20
+ def run(args: argparse.Namespace) -> int:
21
+ """Delegate to registry prune with deprecation warning."""
22
+ # Show deprecation warning unless --json or --quiet
23
+ if not args.json:
24
+ print("⚠ Warning: 'oasr clean' is deprecated. Use 'oasr registry prune' instead.", file=sys.stderr)
25
+ print(" This command will be removed in v0.6.0.\n", file=sys.stderr)
26
+
27
+ # Delegate to registry prune
28
+ from commands.registry import run_prune
29
+
30
+ return run_prune(args)