Skip to content

Commit bd568db

Browse files
committed
Add plainx.* namespace discovery to plain agent install
Enable community packages in the plainx namespace to ship skills and rules that get installed alongside plain packages.
1 parent 2c8982e commit bd568db

File tree

1 file changed

+31
-4
lines changed

1 file changed

+31
-4
lines changed

plain/plain/cli/agent.py

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@
1010

1111

1212
def _get_agent_dirs() -> list[Path]:
13-
"""Get list of agents/.claude/ directories from installed plain.* packages."""
13+
"""Get list of agents/.claude/ directories from installed plain.* and plainx.* packages."""
1414
agent_dirs: list[Path] = []
1515

16+
# Search plain.* packages
1617
try:
1718
import plain
1819

@@ -42,6 +43,27 @@ def _get_agent_dirs() -> list[Path]:
4243
except Exception:
4344
pass
4445

46+
# Search plainx.* packages
47+
try:
48+
import plainx # type: ignore[import-not-found]
49+
50+
# Check plainx.* subpackages
51+
if hasattr(plainx, "__path__"):
52+
for importer, modname, ispkg in pkgutil.iter_modules(
53+
plainx.__path__, "plainx."
54+
):
55+
if ispkg:
56+
try:
57+
spec = importlib.util.find_spec(modname)
58+
if spec and spec.origin:
59+
agent_dir = Path(spec.origin).parent / "agents" / ".claude"
60+
if agent_dir.exists() and agent_dir.is_dir():
61+
agent_dirs.append(agent_dir)
62+
except Exception:
63+
continue
64+
except Exception:
65+
pass
66+
4567
return agent_dirs
4668

4769

@@ -93,8 +115,13 @@ def _install_agent_dir(source_dir: Path, dest_dir: Path) -> tuple[int, int]:
93115
return installed_count, 0
94116

95117

118+
def _is_plain_item(name: str) -> bool:
119+
"""Check if a name is from plain or plainx namespace."""
120+
return name.startswith("plain") # Matches both 'plain' and 'plainx'
121+
122+
96123
def _cleanup_orphans(dest_dir: Path, agent_dirs: list[Path]) -> int:
97-
"""Remove plain* items from .claude/ that no longer exist in any source package."""
124+
"""Remove plain* and plainx* items from .claude/ that no longer exist in any source package."""
98125
removed_count = 0
99126

100127
# Collect all source skill and rule names
@@ -118,7 +145,7 @@ def _cleanup_orphans(dest_dir: Path, agent_dirs: list[Path]) -> int:
118145
for dest in dest_skills.iterdir():
119146
if (
120147
dest.is_dir()
121-
and dest.name.startswith("plain")
148+
and _is_plain_item(dest.name)
122149
and dest.name not in source_skills
123150
):
124151
shutil.rmtree(dest)
@@ -130,7 +157,7 @@ def _cleanup_orphans(dest_dir: Path, agent_dirs: list[Path]) -> int:
130157
for dest in dest_rules.iterdir():
131158
if (
132159
dest.is_file()
133-
and dest.name.startswith("plain")
160+
and _is_plain_item(dest.name)
134161
and dest.suffix == ".md"
135162
and dest.name not in source_rules
136163
):

0 commit comments

Comments
 (0)