Skip to content

Commit bf1873e

Browse files
committed
Add plain install command
1 parent de1fa72 commit bf1873e

File tree

3 files changed

+72
-1
lines changed

3 files changed

+72
-1
lines changed

plain/plain/cli/core.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from .docs import docs
1313
from .formatting import PlainContext
1414
from .help import help_cmd
15+
from .install import install
1516
from .preflight import preflight_checks
1617
from .registry import cli_registry
1718
from .scaffold import create
@@ -38,6 +39,7 @@ def plain_cli():
3839
plain_cli.add_command(setting)
3940
plain_cli.add_command(shell)
4041
plain_cli.add_command(run)
42+
plain_cli.add_command(install)
4143
plain_cli.add_command(upgrade)
4244
plain_cli.add_command(help_cmd)
4345

plain/plain/cli/install.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import subprocess
2+
import sys
3+
4+
import click
5+
6+
from .agent import prompt_agent
7+
8+
9+
@click.command()
10+
@click.argument("packages", nargs=-1, required=True)
11+
@click.option(
12+
"--agent-command",
13+
envvar="PLAIN_AGENT_COMMAND",
14+
help="Run command with generated prompt",
15+
)
16+
def install(packages: tuple[str, ...], agent_command: str | None = None) -> None:
17+
"""Install Plain packages with the help of an agent."""
18+
# Validate all package names
19+
invalid_packages = [pkg for pkg in packages if not pkg.startswith("plain")]
20+
if invalid_packages:
21+
raise click.UsageError(
22+
f"The following packages do not start with 'plain': {', '.join(invalid_packages)}\n"
23+
"This command is only for Plain framework packages."
24+
)
25+
26+
# Install all packages first
27+
if len(packages) == 1:
28+
click.secho(f"Installing {packages[0]}...", bold=True, err=True)
29+
else:
30+
click.secho(f"Installing {len(packages)} packages...", bold=True, err=True)
31+
for pkg in packages:
32+
click.secho(f" - {pkg}", err=True)
33+
click.echo(err=True)
34+
35+
install_cmd = ["uv", "add"] + list(packages)
36+
result = subprocess.run(install_cmd, check=False, stderr=sys.stderr)
37+
38+
if result.returncode != 0:
39+
raise click.ClickException("Failed to install packages")
40+
41+
click.echo(err=True)
42+
if len(packages) == 1:
43+
click.secho(f"✓ {packages[0]} installed successfully", fg="green", err=True)
44+
else:
45+
click.secho(f"✓ {len(packages)} packages installed successfully", fg="green", err=True)
46+
click.echo(err=True)
47+
48+
# Build the prompt for the agent to complete setup
49+
lines = [
50+
f"Complete the setup for the following Plain packages that were just installed: {', '.join(packages)}",
51+
"",
52+
"## Instructions",
53+
"",
54+
"For each package:",
55+
"1. Run `uv run plain docs <package>` and follow any setup instructions",
56+
"2. If the docs point out that it is a --dev tool, move it to dev dependencies: `uv remove <package> && uv add <package> --dev`",
57+
"",
58+
"DO NOT commit any changes",
59+
"",
60+
"Report back with:",
61+
"- Whether the setup completed successfully",
62+
"- Any manual steps that still need to be completed",
63+
"- Any issues or errors encountered",
64+
]
65+
66+
prompt = "\n".join(lines)
67+
success = prompt_agent(prompt, agent_command)
68+
if not success:
69+
raise click.Abort()

plain/plain/cli/upgrade.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
def upgrade(
2424
packages: tuple[str, ...], diff: bool, agent_command: str | None = None
2525
) -> None:
26-
"""Generate an upgrade prompt for plain packages."""
26+
"""Upgrade Plain packages with the help of an agent."""
2727
if not packages:
2828
click.secho("Getting installed packages...", bold=True, err=True)
2929
packages = tuple(sorted(get_installed_plain_packages()))

0 commit comments

Comments
 (0)