agnostic-prompt-aps 1.1.2__py3-none-any.whl → 1.1.4__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.
Files changed (30) hide show
  1. {agnostic_prompt_aps-1.1.2.dist-info → agnostic_prompt_aps-1.1.4.dist-info}/METADATA +36 -5
  2. {agnostic_prompt_aps-1.1.2.dist-info → agnostic_prompt_aps-1.1.4.dist-info}/RECORD +28 -24
  3. {agnostic_prompt_aps-1.1.2.dist-info → agnostic_prompt_aps-1.1.4.dist-info}/WHEEL +1 -1
  4. {agnostic_prompt_aps-1.1.2.dist-info → agnostic_prompt_aps-1.1.4.dist-info}/entry_points.txt +1 -0
  5. aps_cli/__init__.py +1 -1
  6. aps_cli/__main__.py +5 -0
  7. aps_cli/cli.py +43 -53
  8. aps_cli/core.py +32 -25
  9. aps_cli/payload/agnostic-prompt-standard/SKILL.md +1 -2
  10. aps_cli/payload/agnostic-prompt-standard/assets/constants/constants-json-block-v1.0.0.example.md +3 -3
  11. aps_cli/payload/agnostic-prompt-standard/platforms/README.md +7 -1
  12. aps_cli/payload/agnostic-prompt-standard/platforms/_schemas/platform-manifest.schema.json +83 -10
  13. aps_cli/payload/agnostic-prompt-standard/platforms/_template/README.md +0 -2
  14. aps_cli/payload/agnostic-prompt-standard/platforms/_template/manifest.json +1 -2
  15. aps_cli/payload/agnostic-prompt-standard/platforms/claude-code/README.md +247 -0
  16. aps_cli/payload/agnostic-prompt-standard/platforms/claude-code/frontmatter/agent-frontmatter.md +98 -0
  17. aps_cli/payload/agnostic-prompt-standard/platforms/claude-code/frontmatter/rules-frontmatter.md +47 -0
  18. aps_cli/payload/agnostic-prompt-standard/platforms/claude-code/manifest.json +71 -0
  19. aps_cli/payload/agnostic-prompt-standard/platforms/claude-code/tools-registry.json +300 -0
  20. aps_cli/payload/agnostic-prompt-standard/platforms/vscode-copilot/README.md +3 -11
  21. aps_cli/payload/agnostic-prompt-standard/platforms/vscode-copilot/frontmatter/agent-frontmatter.md +1 -1
  22. aps_cli/payload/agnostic-prompt-standard/platforms/vscode-copilot/frontmatter/instructions-frontmatter.md +0 -1
  23. aps_cli/payload/agnostic-prompt-standard/platforms/vscode-copilot/manifest.json +0 -1
  24. aps_cli/payload/agnostic-prompt-standard/references/03-agentic-control.md +55 -14
  25. aps_cli/payload/agnostic-prompt-standard/references/04-schemas-and-types.md +0 -3
  26. aps_cli/payload/agnostic-prompt-standard/references/05-grammar.md +5 -3
  27. aps_cli/payload/agnostic-prompt-standard/assets/agents/vscode-agent-v1.0.0.agent.md +0 -187
  28. aps_cli/payload/agnostic-prompt-standard/platforms/vscode-copilot/templates/AGENTS.md +0 -7
  29. {agnostic_prompt_aps-1.1.2.dist-info → agnostic_prompt_aps-1.1.4.dist-info}/licenses/LICENSE +0 -0
  30. {agnostic_prompt_aps-1.1.2.dist-info → agnostic_prompt_aps-1.1.4.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agnostic-prompt-aps
3
- Version: 1.1.2
3
+ Version: 1.1.4
4
4
  Summary: CLI to install and manage the Agnostic Prompt Standard (APS) skill and platform templates.
5
5
  Author: Agnostic Prompt Standard contributors
6
6
  License: Apache-2.0
@@ -42,16 +42,47 @@ pipx run agnostic-prompt-aps init
42
42
  ## Commands
43
43
 
44
44
  ```bash
45
- aps init [--repo|--personal] [--platform <id>] [--templates] [--yes] [--force]
45
+ aps init [--repo|--personal] [--platform <id>] [--yes] [--force]
46
46
  aps doctor [--json]
47
47
  aps platforms
48
48
  aps version
49
49
  ```
50
50
 
51
- ## Claude platform path
51
+ ## Platform-specific paths
52
52
 
53
- If you need the Claude platform `.claude/skills` location, pass `--claude`:
53
+ Use `--platform <id>` to specify a platform adapter:
54
54
 
55
55
  ```bash
56
- aps init --claude
56
+ # VS Code / Copilot (default paths: .github/skills, ~/.copilot/skills)
57
+ aps init --platform vscode-copilot
58
+
59
+ # Claude Code (paths: .claude/skills, ~/.claude/skills)
60
+ aps init --platform claude-code
57
61
  ```
62
+
63
+ ## Windows troubleshooting
64
+
65
+ On Windows, `pipx run agnostic-prompt-aps` may fail with `FileNotFoundError` due to a known pipx bug with `.exe` launcher paths.
66
+
67
+ **Workarounds:**
68
+
69
+ 1. **Use `pipx install` instead** (recommended):
70
+ ```bash
71
+ pipx install agnostic-prompt-aps
72
+ aps init
73
+ ```
74
+
75
+ 2. **Use Python module syntax**:
76
+ ```bash
77
+ python -m aps_cli init
78
+ ```
79
+
80
+ 3. **Try the full-name entry point**:
81
+ ```bash
82
+ pipx run agnostic-prompt-aps agnostic-prompt-aps init
83
+ ```
84
+
85
+ 4. **Upgrade pipx** to the latest version:
86
+ ```bash
87
+ python -m pip install --upgrade pipx
88
+ ```
@@ -1,10 +1,10 @@
1
- agnostic_prompt_aps-1.1.2.dist-info/licenses/LICENSE,sha256=ZnrdsR9KFRBGUrA3oci51kC6Ky7bOEiN38fzODJIz8w,10744
2
- aps_cli/__init__.py,sha256=spFIzMNaxv0RDC_CJqDwuWy-I926FQlntQheC3s5_fI,49
3
- aps_cli/cli.py,sha256=l92OIvCH30DzSiUsSbaLAEMYEsD5N2KMDJPYNsgFRcU,10699
4
- aps_cli/core.py,sha256=tC39TZ--50jd-3yZtiO49LM4PKMtDhDWUW7frfeWPvU,4685
5
- aps_cli/payload/agnostic-prompt-standard/SKILL.md,sha256=oArglfqVFU-2KXuwwE2J8GgQLkHjb5GONirwyyjDKuY,3299
6
- aps_cli/payload/agnostic-prompt-standard/assets/agents/vscode-agent-v1.0.0.agent.md,sha256=n9xqDqewZYamiV0mLq_VUCODwj_c5ab7rSUDTS_zVIU,6324
7
- aps_cli/payload/agnostic-prompt-standard/assets/constants/constants-json-block-v1.0.0.example.md,sha256=5p7OzBxfZuTHOTengwUlHlId8OuUDC2tIc_onqDarAA,309
1
+ agnostic_prompt_aps-1.1.4.dist-info/licenses/LICENSE,sha256=ZnrdsR9KFRBGUrA3oci51kC6Ky7bOEiN38fzODJIz8w,10744
2
+ aps_cli/__init__.py,sha256=Evw3YjHq5uuL46cWNlFrfy25VPdQPhqi2ZXcBSQicn4,49
3
+ aps_cli/__main__.py,sha256=8nvQUt6R5ewRVwm-4nTGanTubiL0voDVOycLQ3kCziw,126
4
+ aps_cli/cli.py,sha256=NRd2FB0Xl-hHS56r5JoC1TW1cjnewnJsja6nsSY3ZLQ,9724
5
+ aps_cli/core.py,sha256=K2e69_t0DCk2QVljo9SS17QdVHXq1ulRNeGADNz_V8c,4734
6
+ aps_cli/payload/agnostic-prompt-standard/SKILL.md,sha256=F3TmaDBkZ39rpe0zAtjU31A3RLA6_uhykVY4lnWRsjQ,3214
7
+ aps_cli/payload/agnostic-prompt-standard/assets/constants/constants-json-block-v1.0.0.example.md,sha256=xFwyXhYK1s4IcHG7b_951lpOCvi4pmIenWG0QNvYn3Q,314
8
8
  aps_cli/payload/agnostic-prompt-standard/assets/constants/constants-text-block-v1.0.0.example.md,sha256=JHIO0ph7Pa1eBUyoqn8rYmtNivVADJD1K1uOllEY5GM,454
9
9
  aps_cli/payload/agnostic-prompt-standard/assets/formats/format-code-changes-full-v1.0.0.example.md,sha256=CTt0CS0ZLy3pNjc-wxxG8kIZvM8KOEIaXtzNJwHSc1A,754
10
10
  aps_cli/payload/agnostic-prompt-standard/assets/formats/format-code-map-v1.0.0.example.md,sha256=zFHHNhtRS9DW1EBcbnckowwgovlfa4YQX7bVbtagCwM,646
@@ -13,30 +13,34 @@ aps_cli/payload/agnostic-prompt-standard/assets/formats/format-hierarchical-outl
13
13
  aps_cli/payload/agnostic-prompt-standard/assets/formats/format-ideation-list-v1.0.0.example.md,sha256=8PIHFtsnmph7aFyiXDYQqu9zzuREb7tDzNmOXA8iNeA,766
14
14
  aps_cli/payload/agnostic-prompt-standard/assets/formats/format-markdown-table-v1.0.0.example.md,sha256=p8_m8xa_CgJqO_s4yRNi3-kmxV2fdPlwWt7xSmRkhIQ,790
15
15
  aps_cli/payload/agnostic-prompt-standard/assets/formats/format-table-api-coverage-v1.0.0.example.md,sha256=H5ifFMGpeb7lZmwxrD7_12ELwRsPOMBKnxPgspurdQU,805
16
- aps_cli/payload/agnostic-prompt-standard/platforms/README.md,sha256=WB9kHLCKTmiDpTsjjhQTnkSYdClTEGoHnFmNzMPaPgU,1583
17
- aps_cli/payload/agnostic-prompt-standard/platforms/_schemas/platform-manifest.schema.json,sha256=YpjTWZAqfxEiUmN6zYEhfEBrSgwVbXfSRTeLCi8dsMI,1708
16
+ aps_cli/payload/agnostic-prompt-standard/platforms/README.md,sha256=8UG_U4PqbOhtzk6LVa9EaK2VK8By1T6EGzKpcs3NGak,1894
17
+ aps_cli/payload/agnostic-prompt-standard/platforms/_schemas/platform-manifest.schema.json,sha256=p7CQ8TE1miFK8pnz0La-Z-fveOodqARB82HeAZ6qSUE,3900
18
18
  aps_cli/payload/agnostic-prompt-standard/platforms/_schemas/tools-registry.schema.json,sha256=Sab8ydDEj4yyleZuNxJV3JXd5ibz5BY2xS1w4Vo4bI4,3083
19
- aps_cli/payload/agnostic-prompt-standard/platforms/_template/README.md,sha256=tHY851VXpFo8_PgGoXC6AmJAwvmcEnQtEUJrnT_DO6Y,269
20
- aps_cli/payload/agnostic-prompt-standard/platforms/_template/manifest.json,sha256=SBlQ7oBO6Kxbv0lGmyQSoDwUusT7LjtFwRJ-3yt_kJc,542
19
+ aps_cli/payload/agnostic-prompt-standard/platforms/_template/README.md,sha256=9N0UQYBpADfsNQjC83vhXsAstxxMGG52qZFOHVVccsg,203
20
+ aps_cli/payload/agnostic-prompt-standard/platforms/_template/manifest.json,sha256=0BWKB95FcJU-Nn0ZCLoE5td9q0vfbYgOq9rjW8OhQlw,523
21
21
  aps_cli/payload/agnostic-prompt-standard/platforms/_template/tools-registry.json,sha256=myt1MAnLArg_BWMiiMpj1fcWQy_Ve-LLIYPITtYlM5o,231
22
- aps_cli/payload/agnostic-prompt-standard/platforms/vscode-copilot/README.md,sha256=7oFEuyRG6Vkd2LsCb87LuVBzV1_vn_vMdbtXocj2csA,2953
23
- aps_cli/payload/agnostic-prompt-standard/platforms/vscode-copilot/manifest.json,sha256=xkwwuwbldMatUj2BhxQcJCauBDSRMvdi21LDFzCHKmA,1821
22
+ aps_cli/payload/agnostic-prompt-standard/platforms/claude-code/README.md,sha256=OSYK-SkgaD8rYfpolJJJ2aI8KK8iH8YQIZPHdMGNYF0,6963
23
+ aps_cli/payload/agnostic-prompt-standard/platforms/claude-code/manifest.json,sha256=jRXppWLfuxVDEAPJcq0ROhWob5XxxoonBijsm4DxYtQ,2225
24
+ aps_cli/payload/agnostic-prompt-standard/platforms/claude-code/tools-registry.json,sha256=j3bHgu4D7hGFs0WgQEWY7GglLP-ceubI4g_3s2EzN5k,8447
25
+ aps_cli/payload/agnostic-prompt-standard/platforms/claude-code/frontmatter/agent-frontmatter.md,sha256=PbAKJlJoCRBKg6hbkCIV4sb0U62nPWGiMB3IVvfmIBg,2398
26
+ aps_cli/payload/agnostic-prompt-standard/platforms/claude-code/frontmatter/rules-frontmatter.md,sha256=W6_UWAHUco_E8B-QhKDyZ3e7-HETvfouyye9PlPlW5E,857
27
+ aps_cli/payload/agnostic-prompt-standard/platforms/vscode-copilot/README.md,sha256=Az2HrIYb_ixz2NWzc_U5DDMkiyV1Xj-SuPZflYZlKl4,2620
28
+ aps_cli/payload/agnostic-prompt-standard/platforms/vscode-copilot/manifest.json,sha256=6SUGzmvXut5lH5MNXkHGESO_HcPNNY6M56FsLZEOPk8,1766
24
29
  aps_cli/payload/agnostic-prompt-standard/platforms/vscode-copilot/tools-registry.json,sha256=yomjl-_jztd2I0-CGF8plnYtvAWrT-t0StqJF8LoQ04,14966
25
- aps_cli/payload/agnostic-prompt-standard/platforms/vscode-copilot/frontmatter/agent-frontmatter.md,sha256=S3zEEpvjOzeJiufgXL0Gl-j3ynDBlTknrHCci_y5zkY,1005
26
- aps_cli/payload/agnostic-prompt-standard/platforms/vscode-copilot/frontmatter/instructions-frontmatter.md,sha256=Te15nSiypS1vp-bVWiETk-g5juG-ItXDvv6-OnfuOLs,440
30
+ aps_cli/payload/agnostic-prompt-standard/platforms/vscode-copilot/frontmatter/agent-frontmatter.md,sha256=FXXhAofu4PKxmbKSPtIJIEGfHz6BD-XhQOYBHgdGoTU,1071
31
+ aps_cli/payload/agnostic-prompt-standard/platforms/vscode-copilot/frontmatter/instructions-frontmatter.md,sha256=Mso-Yz7EEoAWlDbJy_2ydt267f1wwDzwrNL7J-QFhqk,356
27
32
  aps_cli/payload/agnostic-prompt-standard/platforms/vscode-copilot/frontmatter/prompt-frontmatter.md,sha256=YAG5Rppj4lMkvAmXs2S5ReNwhyAkEXR4ddRGcaiQ4ZE,582
28
33
  aps_cli/payload/agnostic-prompt-standard/platforms/vscode-copilot/frontmatter/skill-frontmatter.md,sha256=0pgGZ4pb-N82oSr0Vu9icHSWjJt6LTBv-3vTSwbFjks,267
29
- aps_cli/payload/agnostic-prompt-standard/platforms/vscode-copilot/templates/AGENTS.md,sha256=lGZuPQb6rvcnADM-lKlXsAeigXcXRzI3QRll2jod9is,342
30
34
  aps_cli/payload/agnostic-prompt-standard/references/00-structure.md,sha256=ROjU_kX7q4KM544Wm3sXF6OiEpNooJIc_G6A924Adcs,3562
31
35
  aps_cli/payload/agnostic-prompt-standard/references/01-vocabulary.md,sha256=K-wEDEq4ZWGniU4IdHenCBBaGsYbx1-gdiZ-zmTzKao,2680
32
36
  aps_cli/payload/agnostic-prompt-standard/references/02-linting-and-formatting.md,sha256=mfOIKWnoGjVgrOPs5hhyjCLhJJSyXO9TdwUNYKRBnIk,3945
33
- aps_cli/payload/agnostic-prompt-standard/references/03-agentic-control.md,sha256=hgBDd2N-1MTDsRcBModnhrBrK6j_7fk_qU2FOpuPtsQ,5013
34
- aps_cli/payload/agnostic-prompt-standard/references/04-schemas-and-types.md,sha256=goklMFUFEXbGzzf_LQQx7cbq2AgCKy5cJ1jHPUFTAqw,6279
35
- aps_cli/payload/agnostic-prompt-standard/references/05-grammar.md,sha256=j-JXRRfvHpJAITVaD2iLhIECfPMlh63KhU8pSIe05FE,4910
37
+ aps_cli/payload/agnostic-prompt-standard/references/03-agentic-control.md,sha256=wWWsm-Sxt64FonfgdJngDNAKwnHBkTfQ1xAfRjC6MAk,6824
38
+ aps_cli/payload/agnostic-prompt-standard/references/04-schemas-and-types.md,sha256=iglJnetnm4VfBm3qHDGoyVhtuHADWxzc67iUElvdk4c,6134
39
+ aps_cli/payload/agnostic-prompt-standard/references/05-grammar.md,sha256=2wdAmgPnMvEZp9NP5yxJ0B7qzdbHQgi_clQWwmx6ipM,5056
36
40
  aps_cli/payload/agnostic-prompt-standard/references/06-logging-and-privacy.md,sha256=38jq2KiJaMxbYQl5b6-6cd-9n9u30Dp9XpdCvJ00cAk,753
37
41
  aps_cli/payload/agnostic-prompt-standard/references/07-error-taxonomy.md,sha256=DiZDOl3rzL2QxuvOOzuIvafbOyfse0l-zJL83HncOYw,5266
38
- agnostic_prompt_aps-1.1.2.dist-info/METADATA,sha256=-9vHkv6jLNeWRGoAjxti_HP1lREvMSx0QPJs3gVFgUQ,1419
39
- agnostic_prompt_aps-1.1.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
40
- agnostic_prompt_aps-1.1.2.dist-info/entry_points.txt,sha256=9XoKSiznWmXDN_0YibQhOg24yu-MvD6Zf5yLG2ZteyM,41
41
- agnostic_prompt_aps-1.1.2.dist-info/top_level.txt,sha256=ZH6TKm_OpENvlmI63-Fqi10WFhuYf_hMAspRwxQmK6Y,8
42
- agnostic_prompt_aps-1.1.2.dist-info/RECORD,,
42
+ agnostic_prompt_aps-1.1.4.dist-info/METADATA,sha256=oZNuQa8-xBtSPkd_HyR7z4NP_qzztNBUtvcZ0xGJZT4,2148
43
+ agnostic_prompt_aps-1.1.4.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
44
+ agnostic_prompt_aps-1.1.4.dist-info/entry_points.txt,sha256=a43GxenITS3XmOM2LOZgHWOyY1_usOojF0FJvAhwWwU,80
45
+ agnostic_prompt_aps-1.1.4.dist-info/top_level.txt,sha256=ZH6TKm_OpENvlmI63-Fqi10WFhuYf_hMAspRwxQmK6Y,8
46
+ agnostic_prompt_aps-1.1.4.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: setuptools (80.10.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,2 +1,3 @@
1
1
  [console_scripts]
2
+ agnostic-prompt-aps = aps_cli.cli:main
2
3
  aps = aps_cli.cli:main
aps_cli/__init__.py CHANGED
@@ -1,3 +1,3 @@
1
1
  __all__ = ["__version__"]
2
2
 
3
- __version__ = "1.1.2"
3
+ __version__ = "1.1.4"
aps_cli/__main__.py ADDED
@@ -0,0 +1,5 @@
1
+ """Allow running the package with `python -m aps_cli`."""
2
+ from aps_cli.cli import main
3
+
4
+ if __name__ == "__main__":
5
+ main()
aps_cli/cli.py CHANGED
@@ -13,7 +13,7 @@ from . import __version__
13
13
  from .core import (
14
14
  SKILL_ID,
15
15
  copy_dir,
16
- copy_templates,
16
+ copy_template_tree,
17
17
  default_personal_skill_path,
18
18
  default_project_skill_path,
19
19
  ensure_dir,
@@ -37,21 +37,22 @@ def _norm_platform(platform: Optional[str]) -> str:
37
37
  return platform
38
38
 
39
39
 
40
+ def _is_claude_platform(platform_id: str) -> bool:
41
+ return platform_id == "claude-code"
42
+
43
+
40
44
  @app.command()
41
45
  def init(
42
46
  root: Optional[str] = typer.Option(
43
47
  None,
44
48
  "--root",
45
- help="Workspace root to install templates / project skill under (defaults to repo root or cwd)",
49
+ help="Workspace root to install project skill under (defaults to repo root or cwd)",
46
50
  ),
47
51
  repo: bool = typer.Option(False, "--repo", help="Force install as project skill (workspace/.github/skills or workspace/.claude/skills)"),
48
52
  personal: bool = typer.Option(False, "--personal", help="Force install as personal skill (~/.copilot/skills or ~/.claude/skills)"),
49
53
  platform: Optional[str] = typer.Option(None, "--platform", help='Platform adapter to apply (default: inferred; use "none" for skill only)'),
50
- templates: bool = typer.Option(False, "--templates", help="Also install platform templates (agents / AGENTS.md / .github/*), if available"),
51
- templates_root: Optional[str] = typer.Option(None, "--templates-root", help="Workspace root for templates when installing personal skill"),
52
- claude: bool = typer.Option(False, "--claude", help="Use Claude platform .claude/skills paths (instead of .github/skills + ~/.copilot/skills)"),
53
54
  yes: bool = typer.Option(False, "--yes", help="Non-interactive: accept inferred/default choices"),
54
- force: bool = typer.Option(False, "--force", help="Overwrite existing skill/templates"),
55
+ force: bool = typer.Option(False, "--force", help="Overwrite existing skill"),
55
56
  dry_run: bool = typer.Option(False, "--dry-run", help="Print the plan only, do not write files"),
56
57
  ):
57
58
  """Install APS into a repo (.github/skills/...) or as a personal skill (~/.copilot/skills/...)."""
@@ -69,10 +70,6 @@ def init(
69
70
 
70
71
  install_scope = "repo" if repo else "personal" if personal else ("repo" if repo_root else "personal")
71
72
 
72
- # Defaults
73
- install_templates = templates or (platform_id not in ("", "none"))
74
- chosen_templates_root: Optional[Path] = None
75
-
76
73
  if not yes and is_tty():
77
74
  # Platform selection (first, so platform choice can inform installation location)
78
75
  if not platform:
@@ -90,6 +87,7 @@ def init(
90
87
 
91
88
  # Scope
92
89
  if not (repo or personal):
90
+ claude = _is_claude_platform(platform_id)
93
91
  install_scope = questionary.select(
94
92
  "Where should APS be installed?",
95
93
  choices=[
@@ -106,59 +104,41 @@ def init(
106
104
  ).ask()
107
105
  assert isinstance(install_scope, str)
108
106
 
109
- # Workspace root (only necessary for repo scope or for applying templates)
107
+ # Workspace root (only necessary for repo scope)
110
108
  if install_scope == "repo" and (not root and not repo_root):
111
109
  root_answer = questionary.text("Workspace root path:", default=str(workspace_root)).ask()
112
110
  workspace_root = Path(str(root_answer)).expanduser().resolve()
113
111
 
114
- # Extras (templates)
115
- install_templates = False
116
- if platform_id != "none":
117
- install_templates = questionary.confirm("Apply platform templates to the workspace?", default=True).ask()
118
-
119
112
  force = questionary.confirm("Overwrite existing files if they exist?", default=force).ask()
120
113
  dry_run = questionary.confirm("Dry run (print plan only)?", default=dry_run).ask()
121
114
 
122
- # Determine where templates should be applied.
123
- if install_templates and platform_id not in ("", "none"):
124
- if install_scope == "repo":
125
- chosen_templates_root = workspace_root
126
- else:
127
- if templates_root:
128
- chosen_templates_root = Path(templates_root).expanduser().resolve()
129
- elif repo_root:
130
- chosen_templates_root = repo_root
131
- else:
132
- chosen_templates_root = Path.cwd().resolve()
133
-
134
115
  # Compute destinations
116
+ claude = _is_claude_platform(platform_id)
135
117
  skill_dest = (
136
118
  default_project_skill_path(workspace_root, claude=claude)
137
119
  if install_scope == "repo"
138
120
  else default_personal_skill_path(claude=claude)
139
121
  )
140
122
 
141
- templates_src = (
142
- payload_skill_dir / "platforms" / platform_id / "templates"
143
- if platform_id not in ("", "none")
144
- else None
145
- )
123
+ # Determine template source if platform is set
124
+ templates_dir = None
125
+ template_root = None
126
+ if platform_id and platform_id != "none":
127
+ templates_dir = payload_skill_dir / "platforms" / platform_id / "templates"
128
+ if templates_dir.is_dir():
129
+ template_root = Path.home() if install_scope == "personal" else workspace_root
130
+ else:
131
+ templates_dir = None
146
132
 
147
133
  plan = {
148
134
  "install_scope": install_scope,
149
135
  "workspace_root": str(workspace_root),
150
- "templates_root": str(chosen_templates_root) if chosen_templates_root else None,
151
136
  "platform_id": platform_id or None,
152
137
  "claude": bool(claude),
153
138
  "skill_source": str(payload_skill_dir),
154
139
  "skill_dest": str(skill_dest),
155
- "install_templates": bool(
156
- install_templates
157
- and chosen_templates_root is not None
158
- and templates_src is not None
159
- and templates_src.is_dir()
160
- ),
161
- "templates_source": str(templates_src) if templates_src else None,
140
+ "templates_source": str(templates_dir) if templates_dir else None,
141
+ "templates_dest": str(template_root) if template_root else None,
162
142
  "force": bool(force),
163
143
  }
164
144
 
@@ -175,16 +155,27 @@ def init(
175
155
  ensure_dir(skill_dest.parent)
176
156
  copy_dir(payload_skill_dir, skill_dest)
177
157
 
178
- templates_summary = None
179
- if plan["install_templates"] and chosen_templates_root and templates_src and templates_src.is_dir():
180
- templates_summary = copy_templates(templates_src, chosen_templates_root, force=force)
181
-
182
158
  console.print("[green]APS installed.[/green]")
183
159
  console.print(f" Skill: {skill_dest}")
184
- if templates_summary:
185
- console.print(f" Templates copied: {len(templates_summary['copied'])}")
186
- if templates_summary["skipped"]:
187
- console.print(f" Templates skipped (existing): {len(templates_summary['skipped'])}")
160
+
161
+ # Copy templates (if platform has templates)
162
+ if templates_dir and template_root:
163
+ def filter_fn(rel_path: str) -> bool:
164
+ # Skip .github/** for personal installs (shouldn't put .github in home dir)
165
+ if install_scope == "personal" and rel_path.startswith(".github"):
166
+ return False
167
+ return True
168
+
169
+ copied = copy_template_tree(
170
+ templates_dir,
171
+ template_root,
172
+ force=force,
173
+ filter_fn=filter_fn,
174
+ )
175
+ if copied:
176
+ console.print(f" Installed {len(copied)} template file(s):")
177
+ for f in copied:
178
+ console.print(f" - {f}")
188
179
 
189
180
 
190
181
  @app.command()
@@ -227,16 +218,15 @@ def doctor(json_out: bool = typer.Option(False, "--json", help="Machine-readable
227
218
  def platforms():
228
219
  """List available platform adapters bundled with this APS release."""
229
220
  payload_skill_dir = resolve_payload_skill_dir()
230
- platforms = load_platforms(payload_skill_dir)
221
+ plats = load_platforms(payload_skill_dir)
231
222
 
232
223
  table = Table(title="APS Platform Adapters")
233
224
  table.add_column("platform_id")
234
225
  table.add_column("display_name")
235
- table.add_column("templates")
236
226
  table.add_column("adapter_version")
237
227
 
238
- for p in platforms:
239
- table.add_row(p.platform_id, p.display_name, "yes" if p.has_templates else "no", p.adapter_version or "")
228
+ for p in plats:
229
+ table.add_row(p.platform_id, p.display_name, p.adapter_version or "")
240
230
 
241
231
  console.print(table)
242
232
 
aps_cli/core.py CHANGED
@@ -15,7 +15,6 @@ class Platform:
15
15
  platform_id: str
16
16
  display_name: str
17
17
  adapter_version: Optional[str]
18
- has_templates: bool
19
18
 
20
19
 
21
20
  def is_tty() -> bool:
@@ -105,13 +104,11 @@ def load_platforms(skill_dir: Path) -> list[Platform]:
105
104
  platform_id = manifest.get("platformId", entry.name)
106
105
  display_name = manifest.get("displayName", entry.name)
107
106
  adapter_version = manifest.get("adapterVersion")
108
- has_templates = (entry / "templates").is_dir()
109
107
  out.append(
110
108
  Platform(
111
109
  platform_id=platform_id,
112
110
  display_name=display_name,
113
111
  adapter_version=adapter_version,
114
- has_templates=has_templates,
115
112
  )
116
113
  )
117
114
  out.sort(key=lambda p: p.display_name.lower())
@@ -130,28 +127,38 @@ def copy_dir(src: Path, dst: Path) -> None:
130
127
  shutil.copytree(src, dst)
131
128
 
132
129
 
133
- def copy_templates(templates_dir: Path, workspace_root: Path, force: bool) -> dict[str, list[str]]:
134
- """Merge-copy templates_dir into workspace_root.
130
+ def copy_template_tree(
131
+ src_dir: Path,
132
+ dst_root: Path,
133
+ *,
134
+ force: bool = False,
135
+ filter_fn: Optional[callable] = None,
136
+ ) -> list[str]:
137
+ """Copy template files individually with optional filtering.
135
138
 
136
- Returns {"copied": [...], "skipped": [...]}
139
+ Args:
140
+ src_dir: Source templates directory
141
+ dst_root: Destination root directory
142
+ force: Overwrite existing files
143
+ filter_fn: Callback (rel_path: str) -> bool; return False to skip
144
+
145
+ Returns:
146
+ List of relative paths that were copied
137
147
  """
138
148
  copied: list[str] = []
139
- skipped: list[str] = []
140
-
141
- for root, dirs, files in os.walk(templates_dir):
142
- root_path = Path(root)
143
- rel_root = root_path.relative_to(templates_dir)
144
- for d in dirs:
145
- ensure_dir(workspace_root / rel_root / d)
146
- for f in files:
147
- src = root_path / f
148
- rel = (rel_root / f)
149
- dst = workspace_root / rel
150
- ensure_dir(dst.parent)
151
- if dst.exists() and not force:
152
- skipped.append(str(rel))
153
- continue
154
- shutil.copy2(src, dst)
155
- copied.append(str(rel))
156
-
157
- return {"copied": copied, "skipped": skipped}
149
+ for src_file in src_dir.rglob("*"):
150
+ if not src_file.is_file():
151
+ continue
152
+ rel_path = src_file.relative_to(src_dir)
153
+ rel_str = str(rel_path).replace("\\", "/")
154
+ if filter_fn and not filter_fn(rel_str):
155
+ continue
156
+ dst_file = dst_root / rel_path
157
+ if dst_file.exists() and not force:
158
+ continue
159
+ dst_file.parent.mkdir(parents=True, exist_ok=True)
160
+ shutil.copy2(src_file, dst_file)
161
+ copied.append(rel_str)
162
+ return copied
163
+
164
+
@@ -5,7 +5,7 @@ license: Apache-2.0
5
5
  metadata:
6
6
  authors: "Christopher Buckley; Juan Burckhardt; Anastasiya Smirnova"
7
7
  spec_version: "1.0"
8
- framework_revision: "1.1.2"
8
+ framework_revision: "1.1.4"
9
9
  last_updated: "2026-01-15"
10
10
  ---
11
11
 
@@ -55,7 +55,6 @@ This `SKILL.md` is the **entrypoint** for the Agnostic Prompt Standard (APS) v1.
55
55
  - `manifest.json` — file discovery rules.
56
56
  - `tools-registry.json` — tool names, sets, and renames.
57
57
  - `frontmatter/` — copy/paste YAML frontmatter templates.
58
- - `templates/` — drop-in workspace artifacts (`AGENTS.md`, `.github/agents/`).
59
58
  - `scripts/` — optional build / compile / lint scripts (empty by default).
60
59
 
61
60
  ---
@@ -6,10 +6,10 @@ DEFAULT_TZ: "Z"
6
6
 
7
7
  API_CONFIG: JSON<<
8
8
  {
9
- "apiBasePath": "/v1",
10
- "defaultTimeZone": DEFAULT_TZ,
9
+ "api_base_path": "/v1",
10
+ "default_time_zone": DEFAULT_TZ,
11
11
  "retries": 3,
12
- "timeoutMs": 2000
12
+ "timeout_ms": 2000
13
13
  }
14
14
  >>
15
15
  </constants>
@@ -20,7 +20,6 @@ platforms/
20
20
  manifest.json # validates against _schemas/platform-manifest.schema.json
21
21
  tools-registry.json # validates against _schemas/tools-registry.schema.json
22
22
  frontmatter/ # copy/paste blocks for this platform
23
- templates/ # ready-to-copy workspace artifacts
24
23
  ```
25
24
 
26
25
  ## Add a new platform adapter
@@ -37,3 +36,10 @@ platforms/
37
36
  - Anything under `platforms/` is **non-normative** (documentation/templates/mappings only).
38
37
  - Adapters should prefer **mapping + configuration** over rewriting APS core rules.
39
38
 
39
+ ## Scope and Philosophy
40
+
41
+ Adapters are intended to **map** the APS standard to a host platform. They are **not** project generators.
42
+ We do not provide generic project scaffolding (like `settings.json` or root `CLAUDE.md` templates).
43
+
44
+ > See [ADR 0001: Adapter Scope](https://github.com/chris-buckley/agnostic-prompt-standard/blob/main/docs/adr/0001-adapter-scope-no-scaffolding.md)
45
+
@@ -6,8 +6,7 @@
6
6
  "required": [
7
7
  "platformId",
8
8
  "displayName",
9
- "adapterVersion",
10
- "fileConventions"
9
+ "adapterVersion"
11
10
  ],
12
11
  "properties": {
13
12
  "platformId": {
@@ -35,9 +34,6 @@
35
34
  "fileConventions": {
36
35
  "type": "object",
37
36
  "required": [
38
- "skills",
39
- "agents",
40
- "prompts",
41
37
  "instructions"
42
38
  ],
43
39
  "properties": {
@@ -45,25 +41,102 @@
45
41
  "type": "array",
46
42
  "items": {
47
43
  "type": "string"
48
- }
44
+ },
45
+ "description": "Skill file locations (platform-specific)"
49
46
  },
50
47
  "agents": {
51
48
  "type": "array",
52
49
  "items": {
53
50
  "type": "string"
54
- }
51
+ },
52
+ "description": "Agent file locations (platform-specific)"
55
53
  },
56
54
  "prompts": {
57
55
  "type": "array",
58
56
  "items": {
59
57
  "type": "string"
60
- }
58
+ },
59
+ "description": "Prompt file locations (platform-specific)"
61
60
  },
62
61
  "instructions": {
63
62
  "type": "array",
64
63
  "items": {
65
64
  "type": "string"
66
- }
65
+ },
66
+ "description": "Instruction/memory file locations"
67
+ },
68
+ "settings": {
69
+ "type": "array",
70
+ "items": {
71
+ "type": "string"
72
+ },
73
+ "description": "Platform-specific settings file locations"
74
+ },
75
+ "mcp": {
76
+ "type": "array",
77
+ "items": {
78
+ "type": "string"
79
+ },
80
+ "description": "MCP server configuration file locations"
81
+ }
82
+ },
83
+ "additionalProperties": true
84
+ },
85
+ "hooks": {
86
+ "type": "object",
87
+ "description": "Platform-specific automation hooks",
88
+ "properties": {
89
+ "available": {
90
+ "type": "array",
91
+ "items": {
92
+ "type": "string"
93
+ },
94
+ "description": "List of available hook types"
95
+ },
96
+ "configLocation": {
97
+ "type": "string",
98
+ "description": "Where hooks are configured"
99
+ },
100
+ "docsUrl": {
101
+ "type": "string",
102
+ "description": "Documentation URL for hooks"
103
+ }
104
+ },
105
+ "additionalProperties": true
106
+ },
107
+ "imports": {
108
+ "type": "object",
109
+ "description": "File import/reference syntax supported by the platform",
110
+ "properties": {
111
+ "syntax": {
112
+ "type": "string",
113
+ "description": "Import syntax pattern (e.g., @path)"
114
+ },
115
+ "examples": {
116
+ "type": "array",
117
+ "items": {
118
+ "type": "string"
119
+ },
120
+ "description": "Example import statements"
121
+ }
122
+ },
123
+ "additionalProperties": true
124
+ },
125
+ "permissions": {
126
+ "type": "object",
127
+ "description": "Permission/approval system documentation",
128
+ "properties": {
129
+ "configLocation": {
130
+ "type": "string",
131
+ "description": "Where permissions are configured"
132
+ },
133
+ "syntax": {
134
+ "type": "string",
135
+ "description": "Permission syntax description"
136
+ },
137
+ "docsUrl": {
138
+ "type": "string",
139
+ "description": "Documentation URL for permissions"
67
140
  }
68
141
  },
69
142
  "additionalProperties": true
@@ -81,4 +154,4 @@
81
154
  }
82
155
  },
83
156
  "additionalProperties": false
84
- }
157
+ }
@@ -4,7 +4,5 @@ Copy this folder to `platforms/<your-platform-id>/` and fill in:
4
4
 
5
5
  - `manifest.json`
6
6
  - `tools-registry.json`
7
- - `frontmatter/` templates
8
- - `templates/` ready-to-copy artifacts
9
7
 
10
8
  Then validate JSON against the schemas in `platforms/_schemas/`.
@@ -17,8 +17,7 @@
17
17
  ".github/prompts/*.prompt.md"
18
18
  ],
19
19
  "instructions": [
20
- ".github/copilot-instructions.md",
21
- "AGENTS.md"
20
+ ".github/copilot-instructions.md"
22
21
  ]
23
22
  },
24
23
  "notes": "Describe platform-specific constraints here."