oasr 0.5.1__py3-none-any.whl → 0.6.0__py3-none-any.whl
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.
- agents/base.py +17 -3
- agents/claude.py +12 -2
- agents/codex.py +12 -2
- agents/copilot.py +12 -2
- agents/opencode.py +12 -2
- cli.py +8 -2
- commands/completion.py +345 -0
- commands/config.py +284 -37
- commands/exec.py +21 -1
- commands/profile.py +84 -0
- commands/update.py +89 -7
- completions/__init__.py +1 -0
- completions/bash.sh +210 -0
- completions/fish.fish +134 -0
- completions/powershell.ps1 +184 -0
- completions/zsh.sh +285 -0
- config/__init__.py +11 -0
- config/defaults.py +4 -21
- config/schema.py +3 -29
- {oasr-0.5.1.dist-info → oasr-0.6.0.dist-info}/METADATA +51 -21
- {oasr-0.5.1.dist-info → oasr-0.6.0.dist-info}/RECORD +34 -20
- policy/defaults.py +3 -19
- policy/profile.py +5 -7
- profiles/__init__.py +23 -0
- profiles/builtins.py +63 -0
- profiles/loader.py +74 -0
- profiles/paths.py +22 -0
- profiles/registry.py +19 -0
- profiles/summary.py +23 -0
- profiles/validation.py +34 -0
- {oasr-0.5.1.dist-info → oasr-0.6.0.dist-info}/WHEEL +0 -0
- {oasr-0.5.1.dist-info → oasr-0.6.0.dist-info}/entry_points.txt +0 -0
- {oasr-0.5.1.dist-info → oasr-0.6.0.dist-info}/licenses/LICENSE +0 -0
- {oasr-0.5.1.dist-info → oasr-0.6.0.dist-info}/licenses/NOTICE +0 -0
completions/zsh.sh
ADDED
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
#compdef oasr
|
|
2
|
+
# oasr completion for zsh
|
|
3
|
+
# This file provides tab completion for the oasr command in zsh.
|
|
4
|
+
#
|
|
5
|
+
# Installation:
|
|
6
|
+
# Run: oasr completion install
|
|
7
|
+
# Or manually: Add this file to your fpath and run compinit
|
|
8
|
+
|
|
9
|
+
_oasr_skills() {
|
|
10
|
+
local skills
|
|
11
|
+
skills=(${(f)"$(oasr registry list --quiet 2>/dev/null | grep '^ -' | sed 's/^ - //' | awk '{print $1}')"})
|
|
12
|
+
_describe 'skill' skills
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
_oasr_agents() {
|
|
16
|
+
local agents
|
|
17
|
+
agents=(
|
|
18
|
+
'codex:OpenAI Codex agent'
|
|
19
|
+
'copilot:GitHub Copilot agent'
|
|
20
|
+
'claude:Anthropic Claude agent'
|
|
21
|
+
'opencode:OpenCode agent'
|
|
22
|
+
)
|
|
23
|
+
_describe 'agent' agents
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
_oasr_profiles() {
|
|
27
|
+
local profiles
|
|
28
|
+
profiles=(${(f)"$(oasr config profiles --names 2>/dev/null)"})
|
|
29
|
+
_describe 'profile' profiles
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
_oasr_config_keys() {
|
|
33
|
+
local keys
|
|
34
|
+
keys=(
|
|
35
|
+
'agent:Default agent'
|
|
36
|
+
'profile:Default policy profile'
|
|
37
|
+
'adapter.default_targets:Default adapter targets'
|
|
38
|
+
'validation.strict:Strict validation'
|
|
39
|
+
'validation.reference_max_lines:Reference max lines'
|
|
40
|
+
'oasr.completions:Enable completions'
|
|
41
|
+
)
|
|
42
|
+
_describe 'config key' keys
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
_oasr_exec() {
|
|
46
|
+
_arguments \
|
|
47
|
+
'--agent[Agent to use]:agent:_oasr_agents' \
|
|
48
|
+
'--profile[Policy profile]:profile:_oasr_profiles' \
|
|
49
|
+
'--agent-flags[Additional agent flags]:flags:' \
|
|
50
|
+
'(-y --yes)'{-y,--yes}'[Skip confirmation]' \
|
|
51
|
+
'--confirm[Force confirmation] \
|
|
52
|
+
--unsafe[Pass unsafe agent flags]' \
|
|
53
|
+
'(-p --prompt)'{-p,--prompt}'[Prompt from file]:file:_files' \
|
|
54
|
+
'1:skill:_oasr_skills'
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
_oasr_clone() {
|
|
58
|
+
_arguments \
|
|
59
|
+
'(-t --target)'{-t,--target}'[Target directory]:directory:_directories' \
|
|
60
|
+
'*:skill:_oasr_skills'
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
_oasr_info() {
|
|
64
|
+
_arguments \
|
|
65
|
+
'--files[Show file list]' \
|
|
66
|
+
'1:skill:_oasr_skills'
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
_oasr_validate() {
|
|
70
|
+
_arguments \
|
|
71
|
+
'*:skill:_oasr_skills'
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
_oasr_config() {
|
|
75
|
+
local -a subcommands
|
|
76
|
+
subcommands=(
|
|
77
|
+
'set:Set a configuration value'
|
|
78
|
+
'get:Get a configuration value'
|
|
79
|
+
'list:List all configuration'
|
|
80
|
+
'agent:Show agent configuration'
|
|
81
|
+
'validation:Show validation settings'
|
|
82
|
+
'adapter:Show adapter settings'
|
|
83
|
+
'oasr:Show core settings'
|
|
84
|
+
'profiles:Show profiles'
|
|
85
|
+
'man:Show config reference'
|
|
86
|
+
'validate:Validate config file'
|
|
87
|
+
'path:Show config file path'
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
_arguments -C \
|
|
91
|
+
'1:subcommand:->subcommand' \
|
|
92
|
+
'*::arg:->args'
|
|
93
|
+
|
|
94
|
+
case $state in
|
|
95
|
+
subcommand)
|
|
96
|
+
_describe 'config subcommand' subcommands
|
|
97
|
+
;;
|
|
98
|
+
args)
|
|
99
|
+
case ${words[1]} in
|
|
100
|
+
set)
|
|
101
|
+
if [ ${#words[@]} -eq 2 ]; then
|
|
102
|
+
_oasr_config_keys
|
|
103
|
+
elif [ ${#words[@]} -eq 3 ]; then
|
|
104
|
+
case ${words[2]} in
|
|
105
|
+
agent)
|
|
106
|
+
_oasr_agents
|
|
107
|
+
;;
|
|
108
|
+
profile|oasr.default_profile)
|
|
109
|
+
_oasr_profiles
|
|
110
|
+
;;
|
|
111
|
+
validation.strict|oasr.completions)
|
|
112
|
+
_values 'boolean' true false
|
|
113
|
+
;;
|
|
114
|
+
validation.reference_max_lines)
|
|
115
|
+
_message 'integer'
|
|
116
|
+
;;
|
|
117
|
+
adapter.default_targets)
|
|
118
|
+
_message 'comma-separated list'
|
|
119
|
+
;;
|
|
120
|
+
esac
|
|
121
|
+
fi
|
|
122
|
+
;;
|
|
123
|
+
get)
|
|
124
|
+
_oasr_config_keys
|
|
125
|
+
;;
|
|
126
|
+
esac
|
|
127
|
+
;;
|
|
128
|
+
esac
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
_oasr_profile() {
|
|
132
|
+
_arguments \
|
|
133
|
+
'1:profile:_oasr_profiles'
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
_oasr_registry() {
|
|
137
|
+
local -a subcommands
|
|
138
|
+
subcommands=(
|
|
139
|
+
'add:Add skill to registry'
|
|
140
|
+
'rm:Remove skill from registry'
|
|
141
|
+
'sync:Sync remote skills'
|
|
142
|
+
'list:List registry skills'
|
|
143
|
+
'validate:Validate registry'
|
|
144
|
+
'prune:Clean up registry'
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
_arguments -C \
|
|
148
|
+
'1:subcommand:->subcommand' \
|
|
149
|
+
'*::arg:->args'
|
|
150
|
+
|
|
151
|
+
case $state in
|
|
152
|
+
subcommand)
|
|
153
|
+
_describe 'registry subcommand' subcommands
|
|
154
|
+
;;
|
|
155
|
+
args)
|
|
156
|
+
case ${words[1]} in
|
|
157
|
+
add)
|
|
158
|
+
_alternative \
|
|
159
|
+
'directories:directory:_directories' \
|
|
160
|
+
'urls:url:(http:// https:// git@)'
|
|
161
|
+
;;
|
|
162
|
+
rm)
|
|
163
|
+
_oasr_skills
|
|
164
|
+
;;
|
|
165
|
+
prune)
|
|
166
|
+
_arguments '--dry-run[Show what would be removed]'
|
|
167
|
+
;;
|
|
168
|
+
esac
|
|
169
|
+
;;
|
|
170
|
+
esac
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
_oasr_completion() {
|
|
174
|
+
local -a shells
|
|
175
|
+
shells=(
|
|
176
|
+
'bash:Bash completion'
|
|
177
|
+
'zsh:Zsh completion'
|
|
178
|
+
'fish:Fish completion'
|
|
179
|
+
'powershell:PowerShell completion'
|
|
180
|
+
'install:Auto-detect and install'
|
|
181
|
+
'uninstall:Remove completions'
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
_arguments \
|
|
185
|
+
'--force[Force reinstall]' \
|
|
186
|
+
'--dry-run[Preview without installing]' \
|
|
187
|
+
'1:shell:->shell'
|
|
188
|
+
|
|
189
|
+
case $state in
|
|
190
|
+
shell)
|
|
191
|
+
_describe 'shell' shells
|
|
192
|
+
;;
|
|
193
|
+
esac
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
_oasr_adapter() {
|
|
197
|
+
local -a subcommands
|
|
198
|
+
subcommands=(
|
|
199
|
+
'list:List adapters'
|
|
200
|
+
'generate:Generate adapter files'
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
_arguments -C \
|
|
204
|
+
'1:subcommand:->subcommand' \
|
|
205
|
+
'*::arg:->args'
|
|
206
|
+
|
|
207
|
+
case $state in
|
|
208
|
+
subcommand)
|
|
209
|
+
_describe 'adapter subcommand' subcommands
|
|
210
|
+
;;
|
|
211
|
+
esac
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
_oasr() {
|
|
215
|
+
local -a commands
|
|
216
|
+
commands=(
|
|
217
|
+
'registry:Manage skill registry'
|
|
218
|
+
'diff:Show tracked skill status'
|
|
219
|
+
'sync:Refresh tracked skills'
|
|
220
|
+
'config:Manage configuration'
|
|
221
|
+
'profile:Select execution profile'
|
|
222
|
+
'clone:Clone skills to directory'
|
|
223
|
+
'exec:Execute a skill'
|
|
224
|
+
'use:DEPRECATED - use clone instead'
|
|
225
|
+
'find:Find skills recursively'
|
|
226
|
+
'validate:Validate skills'
|
|
227
|
+
'clean:Clean up corrupted skills'
|
|
228
|
+
'adapter:Generate IDE-specific files'
|
|
229
|
+
'update:Update OASR tool'
|
|
230
|
+
'info:Show skill information'
|
|
231
|
+
'help:Show help'
|
|
232
|
+
'completion:Manage shell completions'
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
_arguments -C \
|
|
236
|
+
'(--help -h)'{--help,-h}'[Show help]' \
|
|
237
|
+
'--version[Show version]' \
|
|
238
|
+
'--config[Config file path]:file:_files' \
|
|
239
|
+
'--json[JSON output]' \
|
|
240
|
+
'--quiet[Suppress warnings]' \
|
|
241
|
+
'1:command:->command' \
|
|
242
|
+
'*::arg:->args'
|
|
243
|
+
|
|
244
|
+
case $state in
|
|
245
|
+
command)
|
|
246
|
+
_describe 'oasr command' commands
|
|
247
|
+
;;
|
|
248
|
+
args)
|
|
249
|
+
case ${words[1]} in
|
|
250
|
+
exec)
|
|
251
|
+
_oasr_exec
|
|
252
|
+
;;
|
|
253
|
+
profile)
|
|
254
|
+
_oasr_profile
|
|
255
|
+
;;
|
|
256
|
+
clone)
|
|
257
|
+
_oasr_clone
|
|
258
|
+
;;
|
|
259
|
+
info)
|
|
260
|
+
_oasr_info
|
|
261
|
+
;;
|
|
262
|
+
validate)
|
|
263
|
+
_oasr_validate
|
|
264
|
+
;;
|
|
265
|
+
config)
|
|
266
|
+
_oasr_config
|
|
267
|
+
;;
|
|
268
|
+
profile)
|
|
269
|
+
_oasr_profile
|
|
270
|
+
;;
|
|
271
|
+
registry)
|
|
272
|
+
_oasr_registry
|
|
273
|
+
;;
|
|
274
|
+
completion)
|
|
275
|
+
_oasr_completion
|
|
276
|
+
;;
|
|
277
|
+
adapter)
|
|
278
|
+
_oasr_adapter
|
|
279
|
+
;;
|
|
280
|
+
esac
|
|
281
|
+
;;
|
|
282
|
+
esac
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
_oasr "$@"
|
config/__init__.py
CHANGED
|
@@ -14,6 +14,7 @@ import tomli_w
|
|
|
14
14
|
from config.defaults import DEFAULT_CONFIG
|
|
15
15
|
from config.env import load_env_config, merge_configs
|
|
16
16
|
from config.schema import validate_config
|
|
17
|
+
from profiles.loader import load_profiles
|
|
17
18
|
|
|
18
19
|
OASR_DIR = Path.home() / ".oasr"
|
|
19
20
|
CONFIG_FILE = OASR_DIR / "config.toml"
|
|
@@ -75,6 +76,16 @@ def load_config(config_path: Path | None = None, cli_overrides: dict[str, Any] |
|
|
|
75
76
|
with open(path, "rb") as f:
|
|
76
77
|
file_config = tomllib.load(f)
|
|
77
78
|
|
|
79
|
+
if not isinstance(file_config, dict):
|
|
80
|
+
file_config = {}
|
|
81
|
+
|
|
82
|
+
# Merge profile files with inline profiles (inline wins)
|
|
83
|
+
inline_profiles = file_config.get("profiles", {})
|
|
84
|
+
if not isinstance(inline_profiles, dict):
|
|
85
|
+
inline_profiles = {}
|
|
86
|
+
merged_profiles = load_profiles(inline_profiles=inline_profiles)
|
|
87
|
+
file_config["profiles"] = merged_profiles
|
|
88
|
+
|
|
78
89
|
# Load environment variables
|
|
79
90
|
env_config = load_env_config()
|
|
80
91
|
|
config/defaults.py
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
from typing import Any
|
|
4
4
|
|
|
5
|
+
from profiles.builtins import BUILTIN_PROFILES
|
|
6
|
+
|
|
5
7
|
DEFAULT_CONFIG: dict[str, Any] = {
|
|
6
8
|
"validation": {
|
|
7
9
|
"reference_max_lines": 500,
|
|
@@ -15,26 +17,7 @@ DEFAULT_CONFIG: dict[str, Any] = {
|
|
|
15
17
|
},
|
|
16
18
|
"oasr": {
|
|
17
19
|
"default_profile": "safe",
|
|
20
|
+
"completions": True,
|
|
18
21
|
},
|
|
19
|
-
"profiles": {
|
|
20
|
-
# Built-in safe profile (always available as fallback)
|
|
21
|
-
"safe": {
|
|
22
|
-
"fs_read_roots": ["./"],
|
|
23
|
-
"fs_write_roots": ["./out", "./.oasr"],
|
|
24
|
-
"deny_paths": [
|
|
25
|
-
"~/.ssh",
|
|
26
|
-
"~/.aws",
|
|
27
|
-
"~/.gnupg",
|
|
28
|
-
"~/.config",
|
|
29
|
-
".env",
|
|
30
|
-
"~/.bashrc",
|
|
31
|
-
"~/.zshrc",
|
|
32
|
-
"~/.profile",
|
|
33
|
-
],
|
|
34
|
-
"allowed_commands": ["rg", "fd", "jq", "cat"],
|
|
35
|
-
"deny_shell": True,
|
|
36
|
-
"network": False,
|
|
37
|
-
"allow_env": False,
|
|
38
|
-
},
|
|
39
|
-
},
|
|
22
|
+
"profiles": {name: values.copy() for name, values in BUILTIN_PROFILES.items()},
|
|
40
23
|
}
|
config/schema.py
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
from typing import Any
|
|
4
4
|
|
|
5
|
+
from profiles.validation import validate_profiles
|
|
6
|
+
|
|
5
7
|
VALID_AGENTS = {"codex", "copilot", "claude", "opencode"}
|
|
6
8
|
|
|
7
9
|
|
|
@@ -80,32 +82,4 @@ def validate_config(config: dict[str, Any]) -> None:
|
|
|
80
82
|
raise ValueError("oasr.default_profile must be a string")
|
|
81
83
|
|
|
82
84
|
if "profiles" in config:
|
|
83
|
-
|
|
84
|
-
raise ValueError("profiles must be a table (dictionary)")
|
|
85
|
-
|
|
86
|
-
# Validate each profile structure
|
|
87
|
-
for profile_name, profile_data in config["profiles"].items():
|
|
88
|
-
if not isinstance(profile_data, dict):
|
|
89
|
-
raise ValueError(f"Profile '{profile_name}' must be a table (dictionary)")
|
|
90
|
-
|
|
91
|
-
# Validate profile fields if present
|
|
92
|
-
if "fs_read_roots" in profile_data and not isinstance(profile_data["fs_read_roots"], list):
|
|
93
|
-
raise ValueError(f"Profile '{profile_name}': fs_read_roots must be a list")
|
|
94
|
-
|
|
95
|
-
if "fs_write_roots" in profile_data and not isinstance(profile_data["fs_write_roots"], list):
|
|
96
|
-
raise ValueError(f"Profile '{profile_name}': fs_write_roots must be a list")
|
|
97
|
-
|
|
98
|
-
if "deny_paths" in profile_data and not isinstance(profile_data["deny_paths"], list):
|
|
99
|
-
raise ValueError(f"Profile '{profile_name}': deny_paths must be a list")
|
|
100
|
-
|
|
101
|
-
if "allowed_commands" in profile_data and not isinstance(profile_data["allowed_commands"], list):
|
|
102
|
-
raise ValueError(f"Profile '{profile_name}': allowed_commands must be a list")
|
|
103
|
-
|
|
104
|
-
if "deny_shell" in profile_data and not isinstance(profile_data["deny_shell"], bool):
|
|
105
|
-
raise ValueError(f"Profile '{profile_name}': deny_shell must be a boolean")
|
|
106
|
-
|
|
107
|
-
if "network" in profile_data and not isinstance(profile_data["network"], bool):
|
|
108
|
-
raise ValueError(f"Profile '{profile_name}': network must be a boolean")
|
|
109
|
-
|
|
110
|
-
if "allow_env" in profile_data and not isinstance(profile_data["allow_env"], bool):
|
|
111
|
-
raise ValueError(f"Profile '{profile_name}': allow_env must be a boolean")
|
|
85
|
+
validate_profiles(config["profiles"])
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: oasr
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.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
|
|
@@ -210,6 +210,7 @@ Classifier: Topic :: Software Development :: Build Tools
|
|
|
210
210
|
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
211
211
|
Requires-Python: >=3.10
|
|
212
212
|
Requires-Dist: pyyaml>=6.0
|
|
213
|
+
Requires-Dist: questionary>=2.0.1
|
|
213
214
|
Requires-Dist: tomli-w>=1.0.0
|
|
214
215
|
Requires-Dist: tomli>=2.0.0; python_version < '3.11'
|
|
215
216
|
Provides-Extra: dev
|
|
@@ -219,7 +220,7 @@ Description-Content-Type: text/markdown
|
|
|
219
220
|
|
|
220
221
|
# OASR
|
|
221
222
|
|
|
222
|
-
**Open Agent Skill Registry** —
|
|
223
|
+
**Open Agent Skill Registry** — Register, sync, and reuse AI agent skills across IDEs with a single source of truth.
|
|
223
224
|
|
|
224
225
|
---
|
|
225
226
|
|
|
@@ -229,16 +230,22 @@ You've built useful skills for your AI coding assistant. They work great in Curs
|
|
|
229
230
|
|
|
230
231
|
Each tool expects skills in different locations with different formats:
|
|
231
232
|
|
|
232
|
-
- Cursor: `.cursor/
|
|
233
|
-
- Windsurf: `.windsurf/
|
|
233
|
+
- Cursor: `.cursor/commands/`
|
|
234
|
+
- Windsurf: `.windsurf/workflows/`
|
|
234
235
|
- Claude: `.claude/commands/`
|
|
235
|
-
- Copilot: `.github
|
|
236
|
+
- Copilot: `.github/prompts/`
|
|
236
237
|
|
|
237
238
|
So you copy your skills everywhere. Then you improve one. Now the copies are stale. You forget which version is current. Some break silently. This is **skill drift**.
|
|
238
239
|
|
|
239
240
|
## The Solution
|
|
240
241
|
|
|
241
|
-
ASR keeps your skills in
|
|
242
|
+
ASR keeps your skills in a registry, syncs local and remote sources, and generates thin adapters for each IDE.
|
|
243
|
+
It also lets you execute skills safely with policy profiles.
|
|
244
|
+
|
|
245
|
+
Key capabilities:
|
|
246
|
+
- Register skills once (local folders or GitHub/GitLab URLs)
|
|
247
|
+
- Sync and track drift across sources
|
|
248
|
+
- Generate IDE adapters and run skills via `oasr exec`
|
|
242
249
|
|
|
243
250
|
```text
|
|
244
251
|
┌─────────────────────────────────────────────────────────┐
|
|
@@ -267,12 +274,15 @@ No copying. No drift. One source of truth.
|
|
|
267
274
|
|
|
268
275
|
```bash
|
|
269
276
|
# Register local skills
|
|
270
|
-
oasr add ~/skills/git-commit
|
|
271
|
-
oasr add ~/skills/code-review
|
|
277
|
+
oasr registry add ~/skills/git-commit
|
|
278
|
+
oasr registry add ~/skills/code-review
|
|
279
|
+
|
|
280
|
+
# List registered skills
|
|
281
|
+
oasr registry list
|
|
272
282
|
|
|
273
283
|
# Register remote skills from GitHub/GitLab
|
|
274
|
-
oasr add https://github.com/user/skills-repo/tree/main/my-skill
|
|
275
|
-
oasr add https://gitlab.com/org/project/tree/main/cool-skill
|
|
284
|
+
oasr registry add https://github.com/user/skills-repo/tree/main/my-skill
|
|
285
|
+
oasr registry add https://gitlab.com/org/project/tree/main/cool-skill
|
|
276
286
|
|
|
277
287
|
# Generate adapters for a project
|
|
278
288
|
oasr adapter --output-dir ~/projects/my-app
|
|
@@ -294,16 +304,16 @@ ASR supports registering skills directly from GitHub and GitLab repositories:
|
|
|
294
304
|
|
|
295
305
|
```bash
|
|
296
306
|
# Add a skill from GitHub
|
|
297
|
-
oasr add https://github.com/user/repo/tree/main/skills/my-skill
|
|
307
|
+
oasr registry add https://github.com/user/repo/tree/main/skills/my-skill
|
|
298
308
|
|
|
299
309
|
# Add a skill from GitLab
|
|
300
|
-
oasr add https://gitlab.com/org/project/tree/dev/cool-skill
|
|
310
|
+
oasr registry add https://gitlab.com/org/project/tree/dev/cool-skill
|
|
301
311
|
|
|
302
312
|
# Sync remote skills (check for updates)
|
|
303
|
-
oasr sync
|
|
313
|
+
oasr registry sync
|
|
304
314
|
|
|
305
315
|
# Use remote skills
|
|
306
|
-
oasr
|
|
316
|
+
oasr clone my-skill -d ./output
|
|
307
317
|
```
|
|
308
318
|
|
|
309
319
|
**Authentication** (optional, for private repos and higher rate limits):
|
|
@@ -313,7 +323,27 @@ export GITHUB_TOKEN=ghp_your_token_here
|
|
|
313
323
|
export GITLAB_TOKEN=glpat_your_token_here
|
|
314
324
|
```
|
|
315
325
|
|
|
316
|
-
Remote skills are fetched on-demand during `adapter` and `
|
|
326
|
+
Remote skills are fetched on-demand during `adapter` and `clone` operations. The registry stores the URL, and `oasr registry sync` checks if the remote source has changed.
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
## Shell Completions
|
|
331
|
+
|
|
332
|
+
OASR supports intelligent tab completion for Bash, Zsh, Fish, and PowerShell:
|
|
333
|
+
|
|
334
|
+
```bash
|
|
335
|
+
# Install for your current shell
|
|
336
|
+
oasr completion install
|
|
337
|
+
|
|
338
|
+
# Now try it:
|
|
339
|
+
oasr <TAB> # Complete commands
|
|
340
|
+
oasr info <TAB> # Complete skill names
|
|
341
|
+
oasr exec --<TAB> # Complete flags
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
Completions are **dynamic** — skill names, agents, and profiles are fetched live from your registry.
|
|
345
|
+
|
|
346
|
+
See [`oasr completion --help`](docs/commands/COMPLETION.md) for details.
|
|
317
347
|
|
|
318
348
|
---
|
|
319
349
|
|
|
@@ -325,7 +355,7 @@ Remote skills are fetched on-demand during `adapter` and `use` operations. The r
|
|
|
325
355
|
|
|
326
356
|
---
|
|
327
357
|
|
|
328
|
-
## Supported `
|
|
358
|
+
## Supported `oasr adapter` IDEs
|
|
329
359
|
|
|
330
360
|
| IDE | Adapter | Output |
|
|
331
361
|
|----------------|------------|-------------------------------|
|
|
@@ -347,11 +377,11 @@ See [LICENSE](LICENSE).
|
|
|
347
377
|
|
|
348
378
|
| Command | Screenshot |
|
|
349
379
|
|---------|-----------|
|
|
350
|
-
| **oasr list** |  |
|
|
351
|
-
| **oasr add** (local) |  |
|
|
352
|
-
| **oasr add** (remote) |  |
|
|
353
|
-
| **oasr sync** |  |
|
|
354
|
-
| **oasr
|
|
380
|
+
| **oasr registry list** |  |
|
|
381
|
+
| **oasr registry add** (local) |  |
|
|
382
|
+
| **oasr registry add** (remote) |  |
|
|
383
|
+
| **oasr registry sync** |  |
|
|
384
|
+
| **oasr registry -v** |  |
|
|
355
385
|
| **oasr find** |  |
|
|
356
386
|
| **oasr adapter** |  |
|
|
357
387
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
__init__.py,sha256=cYuwXNht5J2GDPEbHz57rmXRyWzaUgAaCXz8okR0rKE,84
|
|
2
2
|
__main__.py,sha256=Due_Us-4KNlLZhf8MkmoP1hWS5qMWmpZvz2ZaCqPHT4,120
|
|
3
3
|
adapter.py,sha256=WEpYkKDTb7We0zU9i6Z-r5ydtUdghNhxTZ5Eq58h4fU,10027
|
|
4
|
-
cli.py,sha256=
|
|
4
|
+
cli.py,sha256=gJLlOplekDkoFKceG3D5tXZ8m0Jm8tnOu0x9n1y2MW0,2883
|
|
5
5
|
discovery.py,sha256=WWF8SN2LH88mOUBJLavM7rvXcxi6uDQGpqRK20GysxA,3298
|
|
6
6
|
manifest.py,sha256=feNCjkFWfhoVubevKjLtKoIEuzT1YGQn6wWgs9XM8_o,12229
|
|
7
7
|
registry.py,sha256=zGutwVP39xaYqc3KDEXMWCV1tORYpqc5JISO8OaWP1Q,4470
|
|
@@ -16,45 +16,59 @@ adapters/copilot.py,sha256=090aS0N7SApSK5kcmm2xErjyUmEsOMrj0n36B0M3fAM,7274
|
|
|
16
16
|
adapters/cursor.py,sha256=BoS3Xo_hZyV4zrZKpNjDAaeGmJPTn_j_GI5QXuW5AOo,2244
|
|
17
17
|
adapters/windsurf.py,sha256=VZidyuFxiHQWl64w0-OgUsfdWeGXV7bf7_XYkiGchyw,2369
|
|
18
18
|
agents/__init__.py,sha256=Dwdwzb01DM2ZJ5pZBsbLPUYRM4Emai7p3oeayiYcj1w,546
|
|
19
|
-
agents/base.py,sha256=
|
|
20
|
-
agents/claude.py,sha256=
|
|
21
|
-
agents/codex.py,sha256=
|
|
22
|
-
agents/copilot.py,sha256=
|
|
23
|
-
agents/opencode.py,sha256=
|
|
19
|
+
agents/base.py,sha256=NBBhpJ4KMBLpi8UjGWaKNx9RNJkSxpobDq2LzIa0EYw,3213
|
|
20
|
+
agents/claude.py,sha256=J3LIha5npufT0dD5ZK2eWvM7BZjb615QYHGu-C-pFXI,857
|
|
21
|
+
agents/codex.py,sha256=tYZQEJCLPTxm8zlpwxADyZEbz9EAWmZPrJM3CPRX6lI,853
|
|
22
|
+
agents/copilot.py,sha256=5gieLBlXcpHu6Ci5JZo2QwJoSKeD-Xprb7nCtU3ODXU,878
|
|
23
|
+
agents/opencode.py,sha256=wTUF2_1jaitQkxjs7oRgvpRmdtyOlLBdvLdJRAMdjAw,881
|
|
24
24
|
agents/registry.py,sha256=i6YUAdNUXq1LNqLDNqSg2RlHxqF5Ig5Z40ryteXoLu4,1434
|
|
25
25
|
commands/__init__.py,sha256=g_ZxSKLVZwCVAPpn-Ga_gj53BS2473SOg72ivGph--U,147
|
|
26
26
|
commands/adapter.py,sha256=_68v3t-dRU0mszzL4udKs1bKennyg7RfBTaK2fDGTsE,3215
|
|
27
27
|
commands/add.py,sha256=NJLQ-8-3zy7o6S9VLfL_wauP-Vz0oNGwN3nvtiwxNYM,15255
|
|
28
28
|
commands/clean.py,sha256=RQBAfe6iCLsjMqUyVR55JdYX9MBqgrUuIrA8rFKs1J0,1102
|
|
29
29
|
commands/clone.py,sha256=4APH34-yHjiXQIQwBnKOSEQ_sxV24_GKypcOJMfncvs,5912
|
|
30
|
-
commands/
|
|
30
|
+
commands/completion.py,sha256=Y2KshaJ64vI1fcTR5z2KTJT7u9PPK_w8qMf5HK_q9ns,8570
|
|
31
|
+
commands/config.py,sha256=zUh65j4N1R5ikRst18eKCvGFQWnhm7fphu314J9lLpo,15211
|
|
31
32
|
commands/diff.py,sha256=37JMjvfAEfvK7-4X5iFbD-IGkS8ae4YSY7ZDIZF5B9E,5766
|
|
32
|
-
commands/exec.py,sha256=
|
|
33
|
+
commands/exec.py,sha256=rO18v7HOcJ9FQ71OHcR4Pplj_YTDD9Z6GxfoWGpK0f0,9518
|
|
33
34
|
commands/find.py,sha256=zgqwUnaG5aLX6gJIU2ZeQzxsFh2s7oDNNtmV-e-62Jg,1663
|
|
34
35
|
commands/help.py,sha256=5yhIpgGs1xPs2f39lg-ELE7D0tV_uUTjxQsgkWusIwo,1449
|
|
35
36
|
commands/info.py,sha256=zywaUQsrvcPXcX8W49P7Jqnr90pX8nBPqnH1XcIs0Uk,4396
|
|
36
37
|
commands/list.py,sha256=P3E_PItNoqAStNTcLCY7dV-Db2_Yb7TRCYXgP4G19rQ,3185
|
|
38
|
+
commands/profile.py,sha256=bjfdXJ6HeM8NRSsEn4t4kbHxSK0o6M3fHc7Cr9RH90U,2732
|
|
37
39
|
commands/registry.py,sha256=nerDoR0Uvd_2WlDMQZshJunMW31HsENklAy19A00x4U,16065
|
|
38
40
|
commands/rm.py,sha256=bOPXgifAbgx7kp4ZuNanJbv4wP1l1sIsI8vD6Rlgi8g,4160
|
|
39
41
|
commands/status.py,sha256=8si3iEVu0AUE2qojSCVoU0BLwpLm4UiFyY-Ln7Uo36k,3944
|
|
40
42
|
commands/sync.py,sha256=ZQoB5hBqrzvM6LUQVlKqHQVJib4dB5qe5M-pVG2vtGM,4946
|
|
41
|
-
commands/update.py,sha256=
|
|
43
|
+
commands/update.py,sha256=gWBBETMxi1ZQ3BV049eAkA_AuCEvvjA9FRzIOBpwdb4,15062
|
|
42
44
|
commands/use.py,sha256=ggB28g2BDg3Lv3nF40wnDAJ7p0mo6C1pc1KgahvQYXM,1452
|
|
43
45
|
commands/validate.py,sha256=Y8TLHxW4Z98onmzu-h-kDIET-48lVaIdQXOvuyBemLw,2361
|
|
44
|
-
|
|
45
|
-
|
|
46
|
+
completions/__init__.py,sha256=cLGMHifEf91ElOIMSVffVWcifjGZ7oStb0Ot4ivLmmE,41
|
|
47
|
+
completions/bash.sh,sha256=2gk60fm17lPfBddpOvO0c8o0anGmqzbVrtic9pabjnQ,6647
|
|
48
|
+
completions/fish.fish,sha256=N2xXseX2djUNRGDs9TaUNU6YltmNT0PSEK0rYJJSuXc,10160
|
|
49
|
+
completions/powershell.ps1,sha256=m-EsgUpyvg1-wO6Afo2QnmHkzdmBfetDUMgaHn4vlO4,7614
|
|
50
|
+
completions/zsh.sh,sha256=XZRLOEi2_grWACeGiDeucsnyFlKwx_SuU7RMBOPe7Ng,7624
|
|
51
|
+
config/__init__.py,sha256=KcrfpKlWkDqVYooupSqMcfYstUDMpVgdSeOJv38nGS0,4063
|
|
52
|
+
config/defaults.py,sha256=1M5rxaOV-51vKAX_CaUZ8-AFL0vnklqYQeo7BpbOsJ8,525
|
|
46
53
|
config/env.py,sha256=WgnQXjhfvV7m1oxZCK9WdIX_rqLy_-BOSuPjbpjdI1c,7163
|
|
47
|
-
config/schema.py,sha256=
|
|
54
|
+
config/schema.py,sha256=kQ1EeepRHjjf4dy9y_qRw7DKEEjeTtyvzd2MZLSIAYY,2816
|
|
48
55
|
policy/__init__.py,sha256=0sPJaruOyc9ioNyIcrTW72RgpaE64FgibS0h5mQELb8,1353
|
|
49
|
-
policy/defaults.py,sha256=
|
|
56
|
+
policy/defaults.py,sha256=7DHRzeW79pEPx7x0_8dTmaFz9cpCosmto_yzb-cpMDs,233
|
|
50
57
|
policy/enforcement.py,sha256=djsosjjfdyr0SjnHF2kz4u3glvMNgd1CJztN6yZE-fM,2749
|
|
51
|
-
policy/profile.py,sha256=
|
|
58
|
+
policy/profile.py,sha256=j9C4Ut5Hwa6DotbbFR1ggmDPVmEC4dNMW7D4oxz2kxM,6839
|
|
59
|
+
profiles/__init__.py,sha256=IqlTPlQdKibdLFMbYIk_tpn_B7dmMSnPhN_OJwPzgAo,760
|
|
60
|
+
profiles/builtins.py,sha256=cu3lvUIUZw-OxEYJgGQeDJvQMPuwTnJqxYTOvnf5oiM,1430
|
|
61
|
+
profiles/loader.py,sha256=n6FJm1r_PhAtuCVlIom2I3yqxnTQUryU8b7ggYyUJjI,2487
|
|
62
|
+
profiles/paths.py,sha256=l0TbuVOOLrJBXOR-BAnxxA__2wZ9rHDTNHANTK1xafo,536
|
|
63
|
+
profiles/registry.py,sha256=hkLUXaN-57iAxQtTwnDkHzLrzl3HTJPF44JcBfg_rjg,659
|
|
64
|
+
profiles/summary.py,sha256=jLbmROC4TqyUJgswsn73rJqPkYq0YmAoKKoWxx5XBRg,853
|
|
65
|
+
profiles/validation.py,sha256=J9pZBs9l-PpNmYoRdn43UhA07FSDM8EdGpZMpsTikvY,1920
|
|
52
66
|
skillcopy/__init__.py,sha256=YUglUkDzKfnCt4ar_DU33ksI9fGyn2UYbV7qn2c_BcU,2322
|
|
53
67
|
skillcopy/local.py,sha256=QH6484dCenjg8pfNOyTRbQQBklEWhkkTnfQok5ssf_4,1049
|
|
54
68
|
skillcopy/remote.py,sha256=83jRA2VfjtSDGO-YM1x3WGJjKvWzK1RmSTL7SdUOz8s,3155
|
|
55
|
-
oasr-0.
|
|
56
|
-
oasr-0.
|
|
57
|
-
oasr-0.
|
|
58
|
-
oasr-0.
|
|
59
|
-
oasr-0.
|
|
60
|
-
oasr-0.
|
|
69
|
+
oasr-0.6.0.dist-info/METADATA,sha256=ueWMiIfDSfj_PC73af_g5NRMgGcVaxiEYU_YM9k-3Fo,18919
|
|
70
|
+
oasr-0.6.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
71
|
+
oasr-0.6.0.dist-info/entry_points.txt,sha256=VnMuOi6XYMbzAD2bP0X5uV1sQXjOqoDWJ33Lsxwq8u8,52
|
|
72
|
+
oasr-0.6.0.dist-info/licenses/LICENSE,sha256=nQ1j9Ldb8FlJ-z7y2WuXPIlyfnYC7YPasjGdOBgcfP4,10561
|
|
73
|
+
oasr-0.6.0.dist-info/licenses/NOTICE,sha256=EsfkCN0ZRDS0oj3ADvMKeKrAXaPlC8YfpSjvjGVv9jE,207
|
|
74
|
+
oasr-0.6.0.dist-info/RECORD,,
|
policy/defaults.py
CHANGED
|
@@ -6,22 +6,6 @@ Conservative defaults that fail closed. Used when:
|
|
|
6
6
|
- Config parsing errors occur
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
"fs_write_roots": ["./out", "./.oasr"],
|
|
13
|
-
"deny_paths": [
|
|
14
|
-
"~/.ssh",
|
|
15
|
-
"~/.aws",
|
|
16
|
-
"~/.gnupg",
|
|
17
|
-
"~/.config",
|
|
18
|
-
".env",
|
|
19
|
-
"~/.bashrc",
|
|
20
|
-
"~/.zshrc",
|
|
21
|
-
"~/.profile",
|
|
22
|
-
],
|
|
23
|
-
"allowed_commands": ["rg", "fd", "jq", "cat"],
|
|
24
|
-
"deny_shell": True,
|
|
25
|
-
"network": False,
|
|
26
|
-
"allow_env": False,
|
|
27
|
-
}
|
|
9
|
+
from profiles.builtins import SAFE
|
|
10
|
+
|
|
11
|
+
__all__ = ["SAFE"]
|