iriai-cli 0.2.0__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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Iriai Platform Team
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,134 @@
1
+ Metadata-Version: 2.4
2
+ Name: iriai-cli
3
+ Version: 0.2.0
4
+ Summary: CLI tool for integrating Iriai platform modules into local projects
5
+ Author: Iriai Platform Team
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/thedanielzhang/iriai-cli
8
+ Project-URL: Repository, https://github.com/thedanielzhang/iriai-cli.git
9
+ Project-URL: Issues, https://github.com/thedanielzhang/iriai-cli/issues
10
+ Keywords: iriai,cli,integration,modules
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Requires-Python: >=3.11
17
+ Description-Content-Type: text/markdown
18
+ License-File: LICENSE
19
+ Requires-Dist: click>=8.1.0
20
+ Requires-Dist: httpx>=0.27.0
21
+ Requires-Dist: pyyaml>=6.0
22
+ Requires-Dist: rich>=13.7.0
23
+ Provides-Extra: dev
24
+ Requires-Dist: pytest>=8.0.0; extra == "dev"
25
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"
26
+ Requires-Dist: black>=24.0.0; extra == "dev"
27
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
28
+ Dynamic: license-file
29
+
30
+ # iriai-cli
31
+
32
+ Command-line tool for integrating Iriai platform modules into your local projects.
33
+
34
+ ## Installation
35
+
36
+ ```bash
37
+ pip install iriai-cli
38
+ # or
39
+ pipx install iriai-cli
40
+ ```
41
+
42
+ ## Usage
43
+
44
+ ```bash
45
+ # List available modules
46
+ iriai modules list
47
+
48
+ # Analyze your project
49
+ iriai analyze
50
+
51
+ # Install a module
52
+ iriai integrate auth-react --action install
53
+
54
+ # Repair a misconfigured module
55
+ iriai integrate auth-react --action repair
56
+
57
+ # Install multiple modules
58
+ iriai integrate auth-react auth-python pwa --action install
59
+ ```
60
+
61
+ ## Features
62
+
63
+ - Local file integration (no Git commits required)
64
+ - Pre-flight analysis and misconfiguration detection
65
+ - LLM-powered code generation via engine API or locally via Claude Code (`--local`)
66
+ - Interactive file write prompts (Apply/Skip/Overwrite-all)
67
+ - Syntax-highlighted diffs
68
+ - Secret file filtering (`.env`, `*.pem`, `*.key`, `credentials.*`, etc.)
69
+ - Dry-run mode for previewing changes
70
+
71
+ ## Configuration
72
+
73
+ ### Environment Variables
74
+
75
+ | Variable | Default | Description |
76
+ |----------|---------|-------------|
77
+ | `IRIAI_ENGINE_URL` | `https://integration.iriai.app` | Integration engine base URL |
78
+ | `IRIAI_API_TOKEN` | *(none)* | Bearer token for authenticated modules (get from deploy console) |
79
+ | `IRIAI_MODULES_DIR` | *(fetched from API)* | Override: load module definitions from local YAML files instead of API |
80
+
81
+ ```bash
82
+ # Point to local engine during development
83
+ export IRIAI_ENGINE_URL=http://localhost:8005
84
+
85
+ # Set API token for authenticated modules
86
+ export IRIAI_API_TOKEN=your_token_here
87
+ ```
88
+
89
+ ## Commands
90
+
91
+ ### `iriai modules list`
92
+
93
+ List all available modules with their versions and descriptions.
94
+
95
+ ### `iriai analyze`
96
+
97
+ Analyze the current directory for module compatibility and misconfigurations. Creates a tarball of the project directory (excluding secrets and ignored files) and uploads it to the engine's `POST /api/analyze-local` endpoint.
98
+
99
+ ### `iriai integrate <modules...>`
100
+
101
+ Integrate one or more modules into your project.
102
+
103
+ Options:
104
+ - `--action`: `install`, `repair`, or `overwrite` (default: `install`)
105
+ - `--depth`: `core` or `full` (default: `full`)
106
+ - `--yes`: Skip interactive prompts, apply all changes
107
+ - `--dry-run`: Show what would be changed without writing files
108
+ - `--local`: Run entirely locally via Claude Code (`claude -p`) instead of the engine API
109
+
110
+ ### Local Mode (`--local`)
111
+
112
+ The `--local` flag runs LLM integration on your machine via Claude Code instead of the engine API:
113
+
114
+ ```bash
115
+ iriai integrate auth-react --local
116
+ ```
117
+
118
+ This mode:
119
+ 1. Fetches module definitions from the integration engine API
120
+ 2. Analyzes the project locally (same logic as the engine)
121
+ 3. Builds a prompt identical to `LLMIntegrator._build_prompt()`
122
+ 4. Invokes `claude -p` subprocess with a 5-minute timeout
123
+ 5. Parses the structured JSON response
124
+ 6. Applies file operations through interactive prompts
125
+
126
+ **Requirements:** Claude Code CLI (`claude`) must be installed and on your PATH.
127
+
128
+ **Note:** Profile matching is skipped in local mode (requires database). Most integrations work without profile-specific config.
129
+
130
+ For development, set `IRIAI_MODULES_DIR` to load module definitions from local YAML files instead of the API.
131
+
132
+ ## License
133
+
134
+ MIT
@@ -0,0 +1,105 @@
1
+ # iriai-cli
2
+
3
+ Command-line tool for integrating Iriai platform modules into your local projects.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install iriai-cli
9
+ # or
10
+ pipx install iriai-cli
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ```bash
16
+ # List available modules
17
+ iriai modules list
18
+
19
+ # Analyze your project
20
+ iriai analyze
21
+
22
+ # Install a module
23
+ iriai integrate auth-react --action install
24
+
25
+ # Repair a misconfigured module
26
+ iriai integrate auth-react --action repair
27
+
28
+ # Install multiple modules
29
+ iriai integrate auth-react auth-python pwa --action install
30
+ ```
31
+
32
+ ## Features
33
+
34
+ - Local file integration (no Git commits required)
35
+ - Pre-flight analysis and misconfiguration detection
36
+ - LLM-powered code generation via engine API or locally via Claude Code (`--local`)
37
+ - Interactive file write prompts (Apply/Skip/Overwrite-all)
38
+ - Syntax-highlighted diffs
39
+ - Secret file filtering (`.env`, `*.pem`, `*.key`, `credentials.*`, etc.)
40
+ - Dry-run mode for previewing changes
41
+
42
+ ## Configuration
43
+
44
+ ### Environment Variables
45
+
46
+ | Variable | Default | Description |
47
+ |----------|---------|-------------|
48
+ | `IRIAI_ENGINE_URL` | `https://integration.iriai.app` | Integration engine base URL |
49
+ | `IRIAI_API_TOKEN` | *(none)* | Bearer token for authenticated modules (get from deploy console) |
50
+ | `IRIAI_MODULES_DIR` | *(fetched from API)* | Override: load module definitions from local YAML files instead of API |
51
+
52
+ ```bash
53
+ # Point to local engine during development
54
+ export IRIAI_ENGINE_URL=http://localhost:8005
55
+
56
+ # Set API token for authenticated modules
57
+ export IRIAI_API_TOKEN=your_token_here
58
+ ```
59
+
60
+ ## Commands
61
+
62
+ ### `iriai modules list`
63
+
64
+ List all available modules with their versions and descriptions.
65
+
66
+ ### `iriai analyze`
67
+
68
+ Analyze the current directory for module compatibility and misconfigurations. Creates a tarball of the project directory (excluding secrets and ignored files) and uploads it to the engine's `POST /api/analyze-local` endpoint.
69
+
70
+ ### `iriai integrate <modules...>`
71
+
72
+ Integrate one or more modules into your project.
73
+
74
+ Options:
75
+ - `--action`: `install`, `repair`, or `overwrite` (default: `install`)
76
+ - `--depth`: `core` or `full` (default: `full`)
77
+ - `--yes`: Skip interactive prompts, apply all changes
78
+ - `--dry-run`: Show what would be changed without writing files
79
+ - `--local`: Run entirely locally via Claude Code (`claude -p`) instead of the engine API
80
+
81
+ ### Local Mode (`--local`)
82
+
83
+ The `--local` flag runs LLM integration on your machine via Claude Code instead of the engine API:
84
+
85
+ ```bash
86
+ iriai integrate auth-react --local
87
+ ```
88
+
89
+ This mode:
90
+ 1. Fetches module definitions from the integration engine API
91
+ 2. Analyzes the project locally (same logic as the engine)
92
+ 3. Builds a prompt identical to `LLMIntegrator._build_prompt()`
93
+ 4. Invokes `claude -p` subprocess with a 5-minute timeout
94
+ 5. Parses the structured JSON response
95
+ 6. Applies file operations through interactive prompts
96
+
97
+ **Requirements:** Claude Code CLI (`claude`) must be installed and on your PATH.
98
+
99
+ **Note:** Profile matching is skipped in local mode (requires database). Most integrations work without profile-specific config.
100
+
101
+ For development, set `IRIAI_MODULES_DIR` to load module definitions from local YAML files instead of the API.
102
+
103
+ ## License
104
+
105
+ MIT
@@ -0,0 +1,56 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "iriai-cli"
7
+ version = "0.2.0"
8
+ description = "CLI tool for integrating Iriai platform modules into local projects"
9
+ readme = "README.md"
10
+ requires-python = ">=3.11"
11
+ license = "MIT"
12
+ authors = [
13
+ {name = "Iriai Platform Team"}
14
+ ]
15
+ keywords = ["iriai", "cli", "integration", "modules"]
16
+ classifiers = [
17
+ "Development Status :: 3 - Alpha",
18
+ "Intended Audience :: Developers",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3.11",
21
+ "Programming Language :: Python :: 3.12",
22
+ ]
23
+
24
+ dependencies = [
25
+ "click>=8.1.0",
26
+ "httpx>=0.27.0",
27
+ "pyyaml>=6.0",
28
+ "rich>=13.7.0",
29
+ ]
30
+
31
+ [project.urls]
32
+ Homepage = "https://github.com/thedanielzhang/iriai-cli"
33
+ Repository = "https://github.com/thedanielzhang/iriai-cli.git"
34
+ Issues = "https://github.com/thedanielzhang/iriai-cli/issues"
35
+
36
+ [project.optional-dependencies]
37
+ dev = [
38
+ "pytest>=8.0.0",
39
+ "pytest-asyncio>=0.23.0",
40
+ "black>=24.0.0",
41
+ "ruff>=0.1.0",
42
+ ]
43
+
44
+ [project.scripts]
45
+ iriai = "iriai_cli.cli:main"
46
+
47
+ [tool.setuptools.packages.find]
48
+ where = ["src"]
49
+
50
+ [tool.black]
51
+ line-length = 100
52
+ target-version = ["py311"]
53
+
54
+ [tool.ruff]
55
+ line-length = 100
56
+ target-version = "py311"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,3 @@
1
+ """Iriai CLI — Local module integration tool."""
2
+
3
+ __version__ = "0.1.0"
@@ -0,0 +1,6 @@
1
+ """CLI entry point."""
2
+
3
+ from .cli import main
4
+
5
+ if __name__ == "__main__":
6
+ main()
@@ -0,0 +1,169 @@
1
+ """HTTP client for integration engine API."""
2
+
3
+ import logging
4
+ from typing import Any
5
+
6
+ import httpx
7
+ from rich.console import Console
8
+
9
+ from .config import config
10
+
11
+ logger = logging.getLogger(__name__)
12
+ console = Console()
13
+
14
+
15
+ class APIError(Exception):
16
+ """Base error for API communication."""
17
+
18
+ def __init__(self, message: str, status_code: int | None = None):
19
+ self.status_code = status_code
20
+ super().__init__(message)
21
+
22
+
23
+ class APIClient:
24
+ """Async HTTP client for the integration engine."""
25
+
26
+ def __init__(self, base_url: str | None = None, timeout: int = 30):
27
+ self.base_url = base_url or config.engine_url
28
+ self.timeout = timeout
29
+
30
+ async def get_modules(self) -> list[dict[str, Any]]:
31
+ """Fetch available modules.
32
+
33
+ Returns:
34
+ List of module metadata dicts.
35
+ """
36
+ async with httpx.AsyncClient(timeout=self.timeout) as client:
37
+ try:
38
+ response = await client.get(
39
+ f"{self.base_url}/api/modules",
40
+ headers=config.headers,
41
+ )
42
+ response.raise_for_status()
43
+ data = response.json()
44
+ return data.get("modules", [])
45
+ except httpx.HTTPStatusError as e:
46
+ raise APIError(
47
+ f"Failed to fetch modules: {e.response.status_code}",
48
+ status_code=e.response.status_code,
49
+ )
50
+ except httpx.RequestError as e:
51
+ raise APIError(f"Network error: {e}")
52
+
53
+ async def get_module_definition(self, name: str) -> dict[str, Any]:
54
+ """Fetch a full module definition by name.
55
+
56
+ Args:
57
+ name: Module name (e.g., "auth-react").
58
+
59
+ Returns:
60
+ Full module definition dict including prompt_template, analyze config, etc.
61
+ """
62
+ async with httpx.AsyncClient(timeout=self.timeout) as client:
63
+ try:
64
+ response = await client.get(
65
+ f"{self.base_url}/api/modules/{name}",
66
+ headers=config.headers,
67
+ )
68
+ response.raise_for_status()
69
+ return response.json()
70
+ except httpx.HTTPStatusError as e:
71
+ if e.response.status_code == 404:
72
+ raise APIError(f"Module '{name}' not found", status_code=404)
73
+ raise APIError(
74
+ f"Failed to fetch module '{name}': {e.response.status_code}",
75
+ status_code=e.response.status_code,
76
+ )
77
+ except httpx.RequestError as e:
78
+ raise APIError(f"Network error: {e}")
79
+
80
+ async def analyze(self, tarball_path: str, modules: list[str] | None = None) -> dict[str, Any]:
81
+ """Analyze a project tarball via POST /api/analyze-local.
82
+
83
+ Args:
84
+ tarball_path: Path to .tar.gz file.
85
+ modules: Optional list of module names to check.
86
+
87
+ Returns:
88
+ Analysis result dict.
89
+ """
90
+ import json as _json
91
+
92
+ async with httpx.AsyncClient(timeout=60) as client:
93
+ try:
94
+ with open(tarball_path, "rb") as f:
95
+ files = {"tarball": ("project.tar.gz", f, "application/gzip")}
96
+ data = {}
97
+ if modules:
98
+ data["modules"] = _json.dumps(modules)
99
+ headers = {}
100
+ if config.api_token:
101
+ headers["Authorization"] = f"Bearer {config.api_token}"
102
+ response = await client.post(
103
+ f"{self.base_url}/api/analyze-local",
104
+ headers=headers,
105
+ files=files,
106
+ data=data,
107
+ )
108
+ response.raise_for_status()
109
+ return response.json()
110
+ except httpx.HTTPStatusError as e:
111
+ raise APIError(
112
+ f"Analysis failed: {e.response.status_code}",
113
+ status_code=e.response.status_code,
114
+ )
115
+ except httpx.RequestError as e:
116
+ raise APIError(f"Network error: {e}")
117
+
118
+ async def integrate_local(
119
+ self,
120
+ tarball_path: str,
121
+ modules: dict[str, str],
122
+ integration_depth: str = "full",
123
+ competing_solution_choices: dict[str, str] | None = None,
124
+ ) -> dict[str, Any]:
125
+ """Trigger local integration.
126
+
127
+ Args:
128
+ tarball_path: Path to project tarball.
129
+ modules: Module name -> action mapping.
130
+ integration_depth: "core" or "full".
131
+ competing_solution_choices: Optional competing solution choices.
132
+
133
+ Returns:
134
+ Integration result dict with file operations.
135
+ """
136
+ import json
137
+
138
+ async with httpx.AsyncClient(timeout=120) as client:
139
+ try:
140
+ with open(tarball_path, "rb") as f:
141
+ files = {"tarball": ("project.tar.gz", f, "application/gzip")}
142
+ data = {
143
+ "modules": json.dumps(modules),
144
+ "integration_depth": integration_depth,
145
+ }
146
+ if competing_solution_choices:
147
+ data["competing_solution_choices"] = json.dumps(
148
+ competing_solution_choices
149
+ )
150
+
151
+ headers = {}
152
+ if config.api_token:
153
+ headers["Authorization"] = f"Bearer {config.api_token}"
154
+
155
+ response = await client.post(
156
+ f"{self.base_url}/api/integrate-local",
157
+ headers=headers,
158
+ files=files,
159
+ data=data,
160
+ )
161
+ response.raise_for_status()
162
+ return response.json()
163
+ except httpx.HTTPStatusError as e:
164
+ raise APIError(
165
+ f"Integration failed: {e.response.status_code}",
166
+ status_code=e.response.status_code,
167
+ )
168
+ except httpx.RequestError as e:
169
+ raise APIError(f"Network error: {e}")