mushu-cli 0.1.1__tar.gz
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.
- mushu_cli-0.1.1/.gitignore +28 -0
- mushu_cli-0.1.1/CHANGELOG.md +13 -0
- mushu_cli-0.1.1/PKG-INFO +11 -0
- mushu_cli-0.1.1/README.md +202 -0
- mushu_cli-0.1.1/justfile +83 -0
- mushu_cli-0.1.1/mushu/__init__.py +1 -0
- mushu_cli-0.1.1/mushu/cli.py +259 -0
- mushu_cli-0.1.1/mushu/commands/__init__.py +1 -0
- mushu_cli-0.1.1/mushu/commands/api_key.py +287 -0
- mushu_cli-0.1.1/mushu/commands/app.py +301 -0
- mushu_cli-0.1.1/mushu/commands/auth.py +480 -0
- mushu_cli-0.1.1/mushu/commands/device.py +163 -0
- mushu_cli-0.1.1/mushu/commands/email.py +436 -0
- mushu_cli-0.1.1/mushu/commands/media.py +490 -0
- mushu_cli-0.1.1/mushu/commands/org.py +724 -0
- mushu_cli-0.1.1/mushu/commands/pay.py +563 -0
- mushu_cli-0.1.1/mushu/commands/push.py +161 -0
- mushu_cli-0.1.1/mushu/commands/tenant.py +251 -0
- mushu_cli-0.1.1/mushu/config.py +246 -0
- mushu_cli-0.1.1/pyproject.toml +30 -0
- mushu_cli-0.1.1/scripts/generate-docs.py +132 -0
- mushu_cli-0.1.1/uv.lock +246 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Virtual environment
|
|
2
|
+
.venv/
|
|
3
|
+
venv/
|
|
4
|
+
|
|
5
|
+
# Python cache
|
|
6
|
+
__pycache__/
|
|
7
|
+
*.py[cod]
|
|
8
|
+
*$py.class
|
|
9
|
+
*.so
|
|
10
|
+
|
|
11
|
+
# Distribution
|
|
12
|
+
dist/
|
|
13
|
+
build/
|
|
14
|
+
*.egg-info/
|
|
15
|
+
|
|
16
|
+
# Ruff cache
|
|
17
|
+
.ruff_cache/
|
|
18
|
+
|
|
19
|
+
# pytest
|
|
20
|
+
.pytest_cache/
|
|
21
|
+
|
|
22
|
+
# IDE
|
|
23
|
+
.idea/
|
|
24
|
+
.vscode/
|
|
25
|
+
*.swp
|
|
26
|
+
|
|
27
|
+
# macOS
|
|
28
|
+
.DS_Store
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [0.1.1](https://github.com/cjoelrun/mushu/compare/mushu-cli-v0.1.0...mushu-cli-v0.1.1) (2026-01-25)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **cli:** add app and api-key commands ([fa651ff](https://github.com/cjoelrun/mushu/commit/fa651ffa924a5d5d25f9e79453ba327a341368eb))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* **cli:** align version with release-please manifest ([ddd628c](https://github.com/cjoelrun/mushu/commit/ddd628cf00cd803270fd4524a67e54b8dbed35b5))
|
mushu_cli-0.1.1/PKG-INFO
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mushu-cli
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: CLI for Mushu platform (auth + notifications)
|
|
5
|
+
Requires-Python: >=3.11
|
|
6
|
+
Requires-Dist: httpx>=0.26.0
|
|
7
|
+
Requires-Dist: pyjwt>=2.8.0
|
|
8
|
+
Requires-Dist: rich>=13.7.0
|
|
9
|
+
Requires-Dist: typer>=0.9.0
|
|
10
|
+
Provides-Extra: dev
|
|
11
|
+
Requires-Dist: pytest>=7.4.0; extra == 'dev'
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# mushu-cli
|
|
2
|
+
|
|
3
|
+
Command-line interface for the Mushu platform.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Authentication**: Sign in with Apple via web OAuth
|
|
8
|
+
- **Organization Management**: Create and manage organizations
|
|
9
|
+
- **Notification Tenants**: Configure APNs credentials and send push notifications
|
|
10
|
+
- **Payment**: Manage Stripe integration and org wallet
|
|
11
|
+
- **Media**: Upload and manage images/videos
|
|
12
|
+
- **Device Management**: Register and list device tokens
|
|
13
|
+
- **Per-Project Config**: Local `.mushu.json` for project-specific settings
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pip install mushu-cli
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Or install from source:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
cd mushu-cli
|
|
25
|
+
pip install -e .
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Quick Start
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# Sign in
|
|
32
|
+
mushu auth login
|
|
33
|
+
|
|
34
|
+
# Create an organization
|
|
35
|
+
mushu org create "My Company"
|
|
36
|
+
|
|
37
|
+
# Initialize project config (creates .mushu.json)
|
|
38
|
+
mushu init --org org_abc123
|
|
39
|
+
|
|
40
|
+
# Commands now use that org automatically
|
|
41
|
+
mushu tenant create --bundle-id com.myapp.ios
|
|
42
|
+
mushu push send --user <user_id> --title "Hello" --body "World"
|
|
43
|
+
mushu media upload photo.jpg
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Project Configuration
|
|
47
|
+
|
|
48
|
+
### Per-Project Config (.mushu.json)
|
|
49
|
+
|
|
50
|
+
Create a `.mushu.json` file in your project root to set defaults for that project:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# Initialize with your org
|
|
54
|
+
mushu init --org org_abc123
|
|
55
|
+
|
|
56
|
+
# Or with more options
|
|
57
|
+
mushu init --org org_abc123 --tenant tenant_xyz --app app_def456
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
This creates a `.mushu.json` file:
|
|
61
|
+
|
|
62
|
+
```json
|
|
63
|
+
{
|
|
64
|
+
"org_id": "org_abc123",
|
|
65
|
+
"tenant_id": "tenant_xyz",
|
|
66
|
+
"app_id": "app_def456"
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
The CLI automatically finds and uses this config when running commands from that directory (or any subdirectory).
|
|
71
|
+
|
|
72
|
+
### Config Resolution Order
|
|
73
|
+
|
|
74
|
+
Settings are resolved in this order (highest priority first):
|
|
75
|
+
|
|
76
|
+
1. **Command-line flags** (`--org`, `--tenant`, etc.)
|
|
77
|
+
2. **Environment variables** (`MUSHU_ORG_ID`, `MUSHU_TENANT_ID`, etc.)
|
|
78
|
+
3. **Local `.mushu.json`** (walked up from current directory)
|
|
79
|
+
4. **Global `~/.mushu/config.json`** defaults
|
|
80
|
+
|
|
81
|
+
### View Current Config
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
# Show status including which config is active
|
|
85
|
+
mushu status
|
|
86
|
+
|
|
87
|
+
# Show detailed config info
|
|
88
|
+
mushu config --show
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Commands
|
|
92
|
+
|
|
93
|
+
### Project Init
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
mushu init # Use current global defaults
|
|
97
|
+
mushu init --org <id> # Set org for this project
|
|
98
|
+
mushu init --org <id> --tenant <id> # Set org and tenant
|
|
99
|
+
mushu init --force # Overwrite existing .mushu.json
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Authentication
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
mushu auth login # Sign in with Apple
|
|
106
|
+
mushu auth logout # Sign out
|
|
107
|
+
mushu auth whoami # Show current user
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Organizations
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
mushu org create <name> # Create organization
|
|
114
|
+
mushu org list # List your organizations
|
|
115
|
+
mushu org show <id> # Show organization details
|
|
116
|
+
mushu org delete <id> # Delete organization
|
|
117
|
+
mushu org use <id> # Set as global default
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Notification Tenants
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
mushu tenant create --bundle-id <bundle> # Create tenant (uses project org)
|
|
124
|
+
mushu tenant list # List tenants
|
|
125
|
+
mushu tenant show <id> # Show tenant
|
|
126
|
+
mushu tenant delete <id> # Delete tenant
|
|
127
|
+
mushu tenant use <id> # Set as default tenant
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Push Notifications
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
mushu push send --user <id> --title "Title" --body "Body"
|
|
134
|
+
mushu push send --user <id> --silent --data '{"key":"value"}'
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Devices
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
mushu device register <token> --user <id> --platform ios
|
|
141
|
+
mushu device list
|
|
142
|
+
mushu device delete <id>
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Media
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
mushu media upload <file> # Upload (uses project org)
|
|
149
|
+
mushu media list # List media
|
|
150
|
+
mushu media show <id>
|
|
151
|
+
mushu media delete <id>
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Pay
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
mushu pay tenant create --name "My App"
|
|
158
|
+
mushu pay tenant list
|
|
159
|
+
mushu pay product create --name "Starter Pack" --price 999 --amount 10000000
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Global Configuration
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
mushu config --show # Show current config
|
|
166
|
+
mushu config --auth-url <url> # Set auth API URL
|
|
167
|
+
mushu config --notify-url <url> # Set notify API URL
|
|
168
|
+
mushu status # Show connection status
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Configuration Files
|
|
172
|
+
|
|
173
|
+
### Global (~/.mushu/)
|
|
174
|
+
|
|
175
|
+
- `config.json` - API URLs and global defaults
|
|
176
|
+
- `tokens.json` - Authentication tokens (created after login)
|
|
177
|
+
|
|
178
|
+
### Local (.mushu.json)
|
|
179
|
+
|
|
180
|
+
Project-specific settings. Supports:
|
|
181
|
+
|
|
182
|
+
| Field | Description |
|
|
183
|
+
|-------|-------------|
|
|
184
|
+
| `org_id` | Organization ID |
|
|
185
|
+
| `org_name` | Organization name (display only) |
|
|
186
|
+
| `app_id` | App ID |
|
|
187
|
+
| `app_name` | App name (display only) |
|
|
188
|
+
| `tenant_id` | Notification tenant ID |
|
|
189
|
+
| `pay_tenant_id` | Pay tenant ID |
|
|
190
|
+
|
|
191
|
+
## Environment Variables
|
|
192
|
+
|
|
193
|
+
| Variable | Description |
|
|
194
|
+
|----------|-------------|
|
|
195
|
+
| `MUSHU_AUTH_URL` | Override auth API URL |
|
|
196
|
+
| `MUSHU_NOTIFY_URL` | Override notify API URL |
|
|
197
|
+
| `MUSHU_PAY_URL` | Override pay API URL |
|
|
198
|
+
| `MUSHU_MEDIA_URL` | Override media API URL |
|
|
199
|
+
| `MUSHU_ORG_ID` | Override org ID |
|
|
200
|
+
| `MUSHU_APP_ID` | Override app ID |
|
|
201
|
+
| `MUSHU_TENANT_ID` | Override tenant ID |
|
|
202
|
+
| `MUSHU_PAY_TENANT_ID` | Override pay tenant ID |
|
mushu_cli-0.1.1/justfile
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Mushu CLI development justfile
|
|
2
|
+
|
|
3
|
+
# Default recipe - show available commands
|
|
4
|
+
default:
|
|
5
|
+
@just --list
|
|
6
|
+
|
|
7
|
+
# Install dependencies and CLI in development mode
|
|
8
|
+
install:
|
|
9
|
+
uv sync
|
|
10
|
+
|
|
11
|
+
# Run the CLI (pass arguments after --)
|
|
12
|
+
run *args:
|
|
13
|
+
uv run mushu {{args}}
|
|
14
|
+
|
|
15
|
+
# Configure CLI for production
|
|
16
|
+
config-prod:
|
|
17
|
+
uv run mushu config \
|
|
18
|
+
--auth-url https://auth.mushucorp.com \
|
|
19
|
+
--notify-url https://notify.mushucorp.com \
|
|
20
|
+
--pay-url https://pay.mushucorp.com
|
|
21
|
+
|
|
22
|
+
# Configure CLI for local development
|
|
23
|
+
config-local:
|
|
24
|
+
uv run mushu config \
|
|
25
|
+
--auth-url http://localhost:8000 \
|
|
26
|
+
--notify-url http://localhost:8001 \
|
|
27
|
+
--pay-url http://localhost:8002
|
|
28
|
+
|
|
29
|
+
# Show current config
|
|
30
|
+
config:
|
|
31
|
+
uv run mushu config --show
|
|
32
|
+
|
|
33
|
+
# Show current status
|
|
34
|
+
status:
|
|
35
|
+
uv run mushu status
|
|
36
|
+
|
|
37
|
+
# Login
|
|
38
|
+
login:
|
|
39
|
+
uv run mushu auth login
|
|
40
|
+
|
|
41
|
+
# Logout
|
|
42
|
+
logout:
|
|
43
|
+
uv run mushu auth logout
|
|
44
|
+
|
|
45
|
+
# List organizations
|
|
46
|
+
orgs:
|
|
47
|
+
uv run mushu org list
|
|
48
|
+
|
|
49
|
+
# List notification tenants
|
|
50
|
+
tenants:
|
|
51
|
+
uv run mushu tenant list
|
|
52
|
+
|
|
53
|
+
# List pay tenants
|
|
54
|
+
pay-tenants:
|
|
55
|
+
uv run mushu pay list
|
|
56
|
+
|
|
57
|
+
# Create a pay tenant
|
|
58
|
+
pay-create name org_id stripe_key:
|
|
59
|
+
uv run mushu pay create --name "{{name}}" --org "{{org_id}}" --stripe-key "{{stripe_key}}"
|
|
60
|
+
|
|
61
|
+
# List products for default pay tenant
|
|
62
|
+
products:
|
|
63
|
+
uv run mushu pay products
|
|
64
|
+
|
|
65
|
+
# Add a product (credit pack)
|
|
66
|
+
add-product name price credits:
|
|
67
|
+
uv run mushu pay add-product --name "{{name}}" --price {{price}} --credits {{credits}}
|
|
68
|
+
|
|
69
|
+
# Create an API key for default pay tenant
|
|
70
|
+
api-key name="default":
|
|
71
|
+
uv run mushu pay api-key --name "{{name}}"
|
|
72
|
+
|
|
73
|
+
# Run linting
|
|
74
|
+
lint:
|
|
75
|
+
uv run ruff check .
|
|
76
|
+
|
|
77
|
+
# Format code
|
|
78
|
+
fmt:
|
|
79
|
+
uv run ruff format .
|
|
80
|
+
|
|
81
|
+
# Clean up
|
|
82
|
+
clean:
|
|
83
|
+
rm -rf .venv __pycache__ .ruff_cache *.egg-info
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Mushu CLI - Unified CLI for Mushu platform (auth + notifications)."""
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
"""Main CLI entry point for Mushu."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
import typer
|
|
6
|
+
from rich.console import Console
|
|
7
|
+
from rich.table import Table
|
|
8
|
+
|
|
9
|
+
from mushu.commands import (
|
|
10
|
+
api_key,
|
|
11
|
+
app as app_cmd,
|
|
12
|
+
auth,
|
|
13
|
+
device,
|
|
14
|
+
email,
|
|
15
|
+
media,
|
|
16
|
+
org,
|
|
17
|
+
pay,
|
|
18
|
+
push,
|
|
19
|
+
tenant,
|
|
20
|
+
)
|
|
21
|
+
from mushu.config import (
|
|
22
|
+
LocalConfig,
|
|
23
|
+
StoredTokens,
|
|
24
|
+
get_config,
|
|
25
|
+
get_global_config,
|
|
26
|
+
LOCAL_CONFIG_FILE,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
app = typer.Typer(
|
|
30
|
+
name="mushu",
|
|
31
|
+
help="Mushu CLI - Authentication and push notifications",
|
|
32
|
+
no_args_is_help=True,
|
|
33
|
+
)
|
|
34
|
+
console = Console()
|
|
35
|
+
|
|
36
|
+
# Add command groups
|
|
37
|
+
app.add_typer(auth.app, name="auth", help="Authentication")
|
|
38
|
+
app.add_typer(org.app, name="org", help="Organization management")
|
|
39
|
+
app.add_typer(app_cmd.app, name="app", help="App management") # app_cmd to avoid name collision
|
|
40
|
+
app.add_typer(api_key.app, name="api-key", help="API key management")
|
|
41
|
+
app.add_typer(tenant.app, name="tenant", help="Notification tenant management")
|
|
42
|
+
app.add_typer(pay.app, name="pay", help="Payment tenant management")
|
|
43
|
+
app.add_typer(media.app, name="media", help="Media management")
|
|
44
|
+
app.add_typer(device.app, name="device", help="Device management")
|
|
45
|
+
app.add_typer(push.app, name="push", help="Push notifications")
|
|
46
|
+
app.add_typer(email.app, name="email", help="Email notifications")
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@app.command("init")
|
|
50
|
+
def init_cmd(
|
|
51
|
+
org_id: str = typer.Option(None, "--org", "-o", help="Organization ID"),
|
|
52
|
+
org_name: str = typer.Option(None, "--org-name", help="Organization name (for display)"),
|
|
53
|
+
app_id: str = typer.Option(None, "--app", "-a", help="App ID"),
|
|
54
|
+
app_name: str = typer.Option(None, "--app-name", help="App name (for display)"),
|
|
55
|
+
tenant_id: str = typer.Option(None, "--tenant", "-t", help="Notification tenant ID"),
|
|
56
|
+
pay_tenant_id: str = typer.Option(None, "--pay-tenant", help="Pay tenant ID"),
|
|
57
|
+
force: bool = typer.Option(False, "--force", "-f", help="Overwrite existing config"),
|
|
58
|
+
):
|
|
59
|
+
"""Initialize a .mushu.json config file in the current directory.
|
|
60
|
+
|
|
61
|
+
This creates a project-specific configuration that the CLI will automatically
|
|
62
|
+
use when running commands from this directory (or any subdirectory).
|
|
63
|
+
|
|
64
|
+
Examples:
|
|
65
|
+
mushu init --org org_abc123
|
|
66
|
+
mushu init --org org_abc123 --tenant tenant_xyz
|
|
67
|
+
mushu init --org org_abc123 --app app_def456
|
|
68
|
+
"""
|
|
69
|
+
config_path = Path.cwd() / LOCAL_CONFIG_FILE
|
|
70
|
+
|
|
71
|
+
# Check if config already exists
|
|
72
|
+
if config_path.exists() and not force:
|
|
73
|
+
console.print(f"[yellow]Config file already exists: {config_path}[/yellow]")
|
|
74
|
+
console.print("Use --force to overwrite")
|
|
75
|
+
raise typer.Exit(1)
|
|
76
|
+
|
|
77
|
+
# If no options provided, try to use current global defaults
|
|
78
|
+
if not any([org_id, app_id, tenant_id, pay_tenant_id]):
|
|
79
|
+
global_config = get_global_config()
|
|
80
|
+
if global_config.default_org:
|
|
81
|
+
org_id = global_config.default_org
|
|
82
|
+
org_name = global_config.default_org_name
|
|
83
|
+
console.print(f"[dim]Using default org from global config: {org_id}[/dim]")
|
|
84
|
+
if global_config.default_tenant:
|
|
85
|
+
tenant_id = global_config.default_tenant
|
|
86
|
+
console.print(f"[dim]Using default tenant from global config: {tenant_id}[/dim]")
|
|
87
|
+
if global_config.default_pay_tenant:
|
|
88
|
+
pay_tenant_id = global_config.default_pay_tenant
|
|
89
|
+
|
|
90
|
+
if not org_id:
|
|
91
|
+
console.print(
|
|
92
|
+
"[yellow]No org specified. Use --org to set one, or run 'mushu org use <id>' first.[/yellow]"
|
|
93
|
+
)
|
|
94
|
+
raise typer.Exit(1)
|
|
95
|
+
|
|
96
|
+
# Create and save local config
|
|
97
|
+
local_config = LocalConfig(
|
|
98
|
+
org_id=org_id,
|
|
99
|
+
org_name=org_name,
|
|
100
|
+
app_id=app_id,
|
|
101
|
+
app_name=app_name,
|
|
102
|
+
tenant_id=tenant_id,
|
|
103
|
+
pay_tenant_id=pay_tenant_id,
|
|
104
|
+
)
|
|
105
|
+
saved_path = local_config.save(config_path)
|
|
106
|
+
|
|
107
|
+
console.print(f"[green]Created {saved_path}[/green]")
|
|
108
|
+
console.print()
|
|
109
|
+
|
|
110
|
+
# Show what was saved
|
|
111
|
+
table = Table(show_header=False, box=None)
|
|
112
|
+
table.add_column("Key", style="dim")
|
|
113
|
+
table.add_column("Value")
|
|
114
|
+
|
|
115
|
+
if org_id:
|
|
116
|
+
display = f"{org_id}" + (f" ({org_name})" if org_name else "")
|
|
117
|
+
table.add_row("org_id", display)
|
|
118
|
+
if app_id:
|
|
119
|
+
display = f"{app_id}" + (f" ({app_name})" if app_name else "")
|
|
120
|
+
table.add_row("app_id", display)
|
|
121
|
+
if tenant_id:
|
|
122
|
+
table.add_row("tenant_id", tenant_id)
|
|
123
|
+
if pay_tenant_id:
|
|
124
|
+
table.add_row("pay_tenant_id", pay_tenant_id)
|
|
125
|
+
|
|
126
|
+
console.print(table)
|
|
127
|
+
console.print()
|
|
128
|
+
console.print("[dim]Commands in this directory will now use these defaults.[/dim]")
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
@app.command("config")
|
|
132
|
+
def config_cmd(
|
|
133
|
+
auth_url: str = typer.Option(None, "--auth-url", help="Set auth API URL"),
|
|
134
|
+
notify_url: str = typer.Option(None, "--notify-url", help="Set notify API URL"),
|
|
135
|
+
pay_url: str = typer.Option(None, "--pay-url", help="Set pay API URL"),
|
|
136
|
+
media_url: str = typer.Option(None, "--media-url", help="Set media API URL"),
|
|
137
|
+
show: bool = typer.Option(False, "--show", "-s", help="Show current config"),
|
|
138
|
+
):
|
|
139
|
+
"""Configure global CLI settings.
|
|
140
|
+
|
|
141
|
+
For per-project settings, use 'mushu init' to create a .mushu.json file.
|
|
142
|
+
"""
|
|
143
|
+
config = get_global_config()
|
|
144
|
+
|
|
145
|
+
if auth_url:
|
|
146
|
+
config.auth_url = auth_url.rstrip("/")
|
|
147
|
+
console.print(f"[green]Auth URL: {auth_url}[/green]")
|
|
148
|
+
|
|
149
|
+
if notify_url:
|
|
150
|
+
config.notify_url = notify_url.rstrip("/")
|
|
151
|
+
console.print(f"[green]Notify URL: {notify_url}[/green]")
|
|
152
|
+
|
|
153
|
+
if pay_url:
|
|
154
|
+
config.pay_url = pay_url.rstrip("/")
|
|
155
|
+
console.print(f"[green]Pay URL: {pay_url}[/green]")
|
|
156
|
+
|
|
157
|
+
if media_url:
|
|
158
|
+
config.media_url = media_url.rstrip("/")
|
|
159
|
+
console.print(f"[green]Media URL: {media_url}[/green]")
|
|
160
|
+
|
|
161
|
+
if auth_url or notify_url or pay_url or media_url:
|
|
162
|
+
config.save()
|
|
163
|
+
|
|
164
|
+
if show or (not auth_url and not notify_url and not pay_url and not media_url):
|
|
165
|
+
# Show effective config (merged)
|
|
166
|
+
effective = get_config()
|
|
167
|
+
|
|
168
|
+
console.print("[bold]Global Config[/bold] (~/.mushu/config.json)")
|
|
169
|
+
console.print(f" Auth URL: {config.auth_url}")
|
|
170
|
+
console.print(f" Notify URL: {config.notify_url}")
|
|
171
|
+
console.print(f" Pay URL: {config.pay_url}")
|
|
172
|
+
console.print(f" Media URL: {config.media_url}")
|
|
173
|
+
console.print(f" Default org: {config.default_org or '[not set]'}")
|
|
174
|
+
console.print(f" Default tenant: {config.default_tenant or '[not set]'}")
|
|
175
|
+
console.print()
|
|
176
|
+
|
|
177
|
+
if effective.local_config_path:
|
|
178
|
+
console.print(f"[bold]Local Config[/bold] ({effective.local_config_path})")
|
|
179
|
+
local = LocalConfig.load()
|
|
180
|
+
if local:
|
|
181
|
+
if local.org_id:
|
|
182
|
+
console.print(f" org_id: {local.org_id}")
|
|
183
|
+
if local.app_id:
|
|
184
|
+
console.print(f" app_id: {local.app_id}")
|
|
185
|
+
if local.tenant_id:
|
|
186
|
+
console.print(f" tenant_id: {local.tenant_id}")
|
|
187
|
+
if local.pay_tenant_id:
|
|
188
|
+
console.print(f" pay_tenant_id: {local.pay_tenant_id}")
|
|
189
|
+
console.print()
|
|
190
|
+
|
|
191
|
+
console.print("[bold]Effective Config[/bold] (merged)")
|
|
192
|
+
console.print(f" org_id: {effective.org_id or '[not set]'}")
|
|
193
|
+
console.print(f" app_id: {effective.app_id or '[not set]'}")
|
|
194
|
+
console.print(f" tenant_id: {effective.tenant_id or '[not set]'}")
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
@app.command("status")
|
|
198
|
+
def status():
|
|
199
|
+
"""Show current status and effective configuration."""
|
|
200
|
+
config = get_config()
|
|
201
|
+
tokens = StoredTokens.load()
|
|
202
|
+
|
|
203
|
+
console.print("[bold]Mushu Status[/bold]")
|
|
204
|
+
console.print()
|
|
205
|
+
|
|
206
|
+
# Auth status
|
|
207
|
+
if tokens:
|
|
208
|
+
console.print("[green]Authenticated[/green]")
|
|
209
|
+
if tokens.email:
|
|
210
|
+
console.print(f" Email: {tokens.email}")
|
|
211
|
+
if tokens.user_id:
|
|
212
|
+
console.print(f" User: {tokens.user_id}")
|
|
213
|
+
else:
|
|
214
|
+
console.print("[yellow]Not authenticated[/yellow]")
|
|
215
|
+
console.print(" Run: mushu auth login")
|
|
216
|
+
|
|
217
|
+
console.print()
|
|
218
|
+
|
|
219
|
+
# Project context
|
|
220
|
+
console.print("[bold]Project Context[/bold]")
|
|
221
|
+
if config.local_config_path:
|
|
222
|
+
console.print(f" [dim]from {config.local_config_path}[/dim]")
|
|
223
|
+
else:
|
|
224
|
+
console.print(" [dim]no .mushu.json found (using global defaults)[/dim]")
|
|
225
|
+
|
|
226
|
+
if config.org_id:
|
|
227
|
+
display = config.org_id + (f" ({config.org_name})" if config.org_name else "")
|
|
228
|
+
console.print(f" [green]Org: {display}[/green]")
|
|
229
|
+
else:
|
|
230
|
+
console.print(" [yellow]Org: not set[/yellow]")
|
|
231
|
+
|
|
232
|
+
if config.app_id:
|
|
233
|
+
display = config.app_id + (f" ({config.app_name})" if config.app_name else "")
|
|
234
|
+
console.print(f" [green]App: {display}[/green]")
|
|
235
|
+
|
|
236
|
+
if config.tenant_id:
|
|
237
|
+
console.print(f" [green]Tenant: {config.tenant_id}[/green]")
|
|
238
|
+
|
|
239
|
+
console.print()
|
|
240
|
+
console.print(f"[dim]Auth: {config.auth_url}[/dim]")
|
|
241
|
+
console.print(f"[dim]Notify: {config.notify_url}[/dim]")
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
@app.callback()
|
|
245
|
+
def main():
|
|
246
|
+
"""
|
|
247
|
+
Mushu CLI - Authentication, push notifications, and media for your apps.
|
|
248
|
+
|
|
249
|
+
Get started:
|
|
250
|
+
mushu auth login # Sign in
|
|
251
|
+
mushu org create ... # Create an organization
|
|
252
|
+
mushu init --org <id> # Set up project config
|
|
253
|
+
mushu push send ... # Send a notification
|
|
254
|
+
"""
|
|
255
|
+
pass
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
if __name__ == "__main__":
|
|
259
|
+
app()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""CLI commands for Mushu."""
|