Metadata-Version: 2.4
Name: muscles-cli
Version: 1.0.1
Summary: Muscles CLI runtime for shared command routing and strategy execution
License: MIT
Author: Denis B.
Author-email: denis@butko.info
Requires-Python: >=3.10,<4.0
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Requires-Dist: dnspython (==2.6.1)
Requires-Dist: greenlet (==3.0.2)
Requires-Dist: jsonschema (==4.16.0)
Requires-Dist: muscles (>=1.0.0rc1,<2.0.0)
Requires-Dist: pyyaml (>=6.0.0,<6.1.0)
Requires-Dist: watchdog (>=4.0.0,<5.0.0)
Requires-Dist: werkzeug (==2.1.1)
Project-URL: Documentation, https://github.com/butkoden/muscles-cli#readme
Project-URL: Homepage, https://github.com/butkoden/muscles-cli
Project-URL: PyPI, https://pypi.org/project/muscles-cli/
Project-URL: Repository, https://github.com/butkoden/muscles-cli
Project-URL: Releases, https://github.com/butkoden/muscles-cli/releases
Project-URL: muscles, https://pypi.org/project/muscles/
Project-URL: muscles-asgi, https://pypi.org/project/muscles-asgi/
Project-URL: muscles-wsgi, https://pypi.org/project/muscles-wsgi/
Project-URL: muscles-mcp, https://pypi.org/project/muscles-mcp/
Project-URL: muscles-benchmarks, https://pypi.org/project/muscles-benchmarks/
Description-Content-Type: text/markdown

# Muscles CLI

`muscles-cli` is the console runtime for Muscles. It uses the same application
shape as the HTTP runtimes: an `ApplicationMeta` class owns a `Context`, and the
context delegates execution to `CliStrategy`.

## Installation

```bash
pip install muscles-cli
```

Canonical ecosystem install matrix is documented in core:
[Muscles installation matrix](https://github.com/butkoden/muscles/blob/master/docs/installation.md).

## Related Repositories

- [`muscles`](https://github.com/butkoden/muscles) - core contracts, actions, inspect output and canonical documentation.
- [`muscles-asgi`](https://github.com/butkoden/muscles-asgi) - ASGI runtime generated projects can target.
- [`muscles-wsgi`](https://github.com/butkoden/muscles-wsgi) - WSGI runtime generated projects can target.
- [`muscles-mcp`](https://github.com/butkoden/muscles-mcp) - MCP projection over the same action contracts.
- [`muscles-benchmarks`](https://github.com/butkoden/muscles-benchmarks) - CLI regression and architecture checks.

## Project Scaffolding

Use canonical command `muscles new`:

```bash
muscles new demo --runtime asgi
muscles new demo --runtime wsgi
muscles new demo --runtime cli
```

Notes:

- `muscular new` is not a canonical command.
- Existing non-empty directory is rejected unless `--force` is used.

## AI Workflow Commands

```bash
muscles capabilities --json
muscles inspect --json --app app.application:App
muscles action list --app app.application:App --json
muscles action inspect bookings.echo --app app.application:App --json
muscles action run bookings.echo --app app.application:App --payload-json '{"title":"Call"}' --json
muscles routes --app app.application:App
muscles schemas --app app.application:App
muscles rules --app app.application:App
muscles cli --app app.application:App
muscles generate page Home --with-tests
muscles doctor --json
muscles test --doctor
```

## Quick Start

```python
from muscles import ApplicationMeta, Context, cli
from muscles.cli import CliStrategy


class App(metaclass=ApplicationMeta):
    context = Context(CliStrategy)

    def run(self, *args):
        return self.context.execute(*args, shutup=True)


@cli.group()
def bookings(*args):
    """Booking commands."""
    return True


@bookings.command(command_name="remove")
def remove_booking(*args):
    booking_id = args[0]
    return f"removed {booking_id}"


app = App()
assert app.run("bookings", "remove", "1") == "removed 1"
```

## Routing Model

Groups and commands form a tree. That makes CLI routing close to HTTP routing:

- `bookings remove 1` is a nested route with an argument;
- `bookings/list` can be normalized by an application before calling the CLI;
- groups can have handlers, but returning `True` lets execution continue to a
  child command.

More detail: [docs/routing.md](docs/routing.md).

## Core Stream Output

English: CLI progress output uses core `StreamEvent` items from
`StreamResult`. `render_stream_result()` can print human-readable progress/log
and result lines, or machine-readable JSON lines. The CLI layer only owns
presentation and exit code mapping; stream semantics stay in `muscles.core`.

Русский: CLI progress output использует core `StreamEvent` из `StreamResult`.
`render_stream_result()` может печатать human-readable progress/log/result
строки или machine-readable JSON lines. CLI слой отвечает только за presentation
и exit code mapping; stream semantics остаётся в `muscles.core`.

## Arguments

Use `@cli.argument()` for named arguments and `@cli.flag()` for boolean flags.
Required prompted arguments use `input()` or `getpass.getpass()` when hidden.

For nested commands, define options on the parent group object:

```python
@cli.group(command_name="bookings")
def bookings(*args):
    return True

@bookings.command(command_name="list")
@bookings.argument("--limit", nargs=1, default="25")
def bookings_list(*args, limit):
    return limit
```

Canonical invocations for benchmark/automation scripts:

```bash
bookings list --limit 10
bookings list --limit=10
```

## Development

Run tests with the core package on `PYTHONPATH`:

```bash
PYTHONPATH=../muscles/src:src python -m pytest -q
```

