- Remove standalone chat subcommand; chat becomes default behavior - Default --cwd resolves to workspace/ instead of repo root - Split CLAUDE.md: repo/ for CLI dev, workspace/ for daily workflow - Add workspace/CLAUDE.md, workspace/.gitignore for tmp files - Ignore MCP temp artifacts (.mcp.json, .playwright-mcp/) - Clean up removed mail subcommand files
112 lines
2.8 KiB
Python
112 lines
2.8 KiB
Python
"""Myclaude CLI entrypoint."""
|
|
|
|
import os
|
|
import shutil
|
|
import subprocess
|
|
from importlib.metadata import PackageNotFoundError, version
|
|
from pathlib import Path
|
|
|
|
import click
|
|
from rich.console import Console
|
|
|
|
from myclaude.commands import update_cmd, upgrade_cmd
|
|
from myclaude.project_root import get_myclaude_project_root
|
|
|
|
stderr_console = Console(stderr=True)
|
|
|
|
|
|
def _package_version() -> str:
|
|
try:
|
|
return version("myclaude")
|
|
except PackageNotFoundError:
|
|
return "0.0.0"
|
|
|
|
|
|
def _resolve_chat_cwd() -> Path:
|
|
root = get_myclaude_project_root()
|
|
fallback = Path.home() / ".myclaude"
|
|
if root == fallback:
|
|
stderr_console.print(
|
|
"[red]Cannot resolve myclaude project root.[/red] Run from the repo or set "
|
|
"[cyan]MYCLAUDE_PROJECT_ROOT[/cyan].",
|
|
)
|
|
raise SystemExit(1)
|
|
workspace = root / "workspace"
|
|
if workspace.is_dir():
|
|
return workspace
|
|
return root
|
|
|
|
|
|
@click.group(
|
|
invoke_without_command=True,
|
|
context_settings={
|
|
"ignore_unknown_options": True,
|
|
"allow_extra_args": True,
|
|
},
|
|
)
|
|
@click.version_option(version=_package_version())
|
|
@click.option(
|
|
"--cwd",
|
|
"-C",
|
|
is_flag=False,
|
|
flag_value=".",
|
|
default=None,
|
|
type=click.Path(dir_okay=True, file_okay=False),
|
|
help="Use specified path as working directory (default: workspace/).",
|
|
)
|
|
@click.option(
|
|
"--dangerously-allow-browser-control",
|
|
is_flag=True,
|
|
default=False,
|
|
help="Forward to claude: allow browser automation without confirmation.",
|
|
)
|
|
@click.pass_context
|
|
def cli(
|
|
ctx: click.Context,
|
|
cwd: str | None,
|
|
dangerously_allow_browser_control: bool,
|
|
) -> None:
|
|
"""Myclaude: CLI toolkit.
|
|
|
|
Run without subcommands to start Claude Code in workspace/.
|
|
Extra arguments pass through to claude.
|
|
"""
|
|
if ctx.invoked_subcommand is not None:
|
|
return
|
|
|
|
binary = os.environ.get("CLAUDE_BIN") or shutil.which("claude")
|
|
if not binary:
|
|
stderr_console.print(
|
|
"[red]claude CLI not found in PATH.[/red] Install Claude Code or set "
|
|
"[cyan]CLAUDE_BIN[/cyan].",
|
|
)
|
|
raise SystemExit(127)
|
|
|
|
if cwd is None:
|
|
chat_cwd = _resolve_chat_cwd()
|
|
else:
|
|
chat_cwd = Path(cwd).resolve()
|
|
if not chat_cwd.is_dir():
|
|
stderr_console.print(f"[red]Not a directory:[/red] {cwd}")
|
|
raise SystemExit(1)
|
|
|
|
cmd: list[str] = [binary]
|
|
if dangerously_allow_browser_control:
|
|
cmd.append("--dangerously-allow-browser-control")
|
|
cmd.extend(ctx.args)
|
|
|
|
proc = subprocess.run(cmd, cwd=str(chat_cwd), check=False)
|
|
raise SystemExit(proc.returncode)
|
|
|
|
|
|
cli.add_command(update_cmd)
|
|
cli.add_command(upgrade_cmd, name="upgrade")
|
|
|
|
|
|
def main() -> None:
|
|
cli()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|