hire-ai 0.1.0__tar.gz → 0.1.2__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.
- {hire_ai-0.1.0 → hire_ai-0.1.2}/PKG-INFO +38 -12
- {hire_ai-0.1.0 → hire_ai-0.1.2}/README.md +32 -7
- {hire_ai-0.1.0 → hire_ai-0.1.2}/hire/cli.py +20 -2
- hire_ai-0.1.2/hire/clipboard.py +40 -0
- {hire_ai-0.1.0 → hire_ai-0.1.2}/hire/commands/__init__.py +2 -1
- {hire_ai-0.1.0 → hire_ai-0.1.2}/hire/commands/ask.py +49 -6
- hire_ai-0.1.2/hire/commands/doctor.py +60 -0
- {hire_ai-0.1.0 → hire_ai-0.1.2}/pyproject.toml +8 -7
- {hire_ai-0.1.0 → hire_ai-0.1.2}/.gitignore +0 -0
- {hire_ai-0.1.0 → hire_ai-0.1.2}/LICENSE +0 -0
- {hire_ai-0.1.0 → hire_ai-0.1.2}/hire/__init__.py +0 -0
- {hire_ai-0.1.0 → hire_ai-0.1.2}/hire/adapters/__init__.py +0 -0
- {hire_ai-0.1.0 → hire_ai-0.1.2}/hire/adapters/base.py +0 -0
- {hire_ai-0.1.0 → hire_ai-0.1.2}/hire/adapters/claude.py +0 -0
- {hire_ai-0.1.0 → hire_ai-0.1.2}/hire/adapters/codex.py +0 -0
- {hire_ai-0.1.0 → hire_ai-0.1.2}/hire/adapters/gemini.py +0 -0
- {hire_ai-0.1.0 → hire_ai-0.1.2}/hire/commands/delete.py +0 -0
- {hire_ai-0.1.0 → hire_ai-0.1.2}/hire/commands/sessions.py +0 -0
- {hire_ai-0.1.0 → hire_ai-0.1.2}/hire/commands/show.py +0 -0
- {hire_ai-0.1.0 → hire_ai-0.1.2}/hire/config.py +0 -0
- {hire_ai-0.1.0 → hire_ai-0.1.2}/hire/paths.py +0 -0
- {hire_ai-0.1.0 → hire_ai-0.1.2}/hire/session.py +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hire-ai
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Summary: CLI to orchestrate AI agents (Claude, Codex, Gemini)
|
|
5
|
-
Project-URL: Homepage, https://github.com/nichiki/hire
|
|
6
|
-
Project-URL: Repository, https://github.com/nichiki/hire
|
|
7
|
-
Project-URL: Issues, https://github.com/nichiki/hire/issues
|
|
5
|
+
Project-URL: Homepage, https://github.com/nichiki/hire-ai
|
|
6
|
+
Project-URL: Repository, https://github.com/nichiki/hire-ai
|
|
7
|
+
Project-URL: Issues, https://github.com/nichiki/hire-ai/issues
|
|
8
8
|
Author: nichiki
|
|
9
9
|
License-Expression: MIT
|
|
10
10
|
License-File: LICENSE
|
|
@@ -15,12 +15,13 @@ Classifier: Intended Audience :: Developers
|
|
|
15
15
|
Classifier: License :: OSI Approved :: MIT License
|
|
16
16
|
Classifier: Operating System :: OS Independent
|
|
17
17
|
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
19
|
Classifier: Programming Language :: Python :: 3.11
|
|
19
20
|
Classifier: Programming Language :: Python :: 3.12
|
|
20
21
|
Classifier: Programming Language :: Python :: 3.13
|
|
21
22
|
Classifier: Topic :: Software Development
|
|
22
23
|
Classifier: Topic :: Utilities
|
|
23
|
-
Requires-Python: >=3.
|
|
24
|
+
Requires-Python: >=3.10
|
|
24
25
|
Provides-Extra: dev
|
|
25
26
|
Requires-Dist: build>=1.0; extra == 'dev'
|
|
26
27
|
Requires-Dist: mypy>=1.10; extra == 'dev'
|
|
@@ -29,29 +30,37 @@ Requires-Dist: ruff>=0.4; extra == 'dev'
|
|
|
29
30
|
Requires-Dist: twine>=5.0; extra == 'dev'
|
|
30
31
|
Description-Content-Type: text/markdown
|
|
31
32
|
|
|
32
|
-
# hire
|
|
33
|
+
# hire-ai
|
|
33
34
|
|
|
34
35
|
CLI to orchestrate AI agents (Claude, Codex, Gemini).
|
|
35
36
|
|
|
37
|
+
> **⚠️ Warning**: By default, all agents run in **auto-approve mode**:
|
|
38
|
+
> - Claude Code: `--dangerously-skip-permissions`
|
|
39
|
+
> - Codex: `--full-auto`
|
|
40
|
+
> - Gemini CLI: `-y`
|
|
41
|
+
>
|
|
42
|
+
> This means agents can execute commands and modify files without confirmation.
|
|
43
|
+
> You can customize this in `~/.config/hire/config.json`.
|
|
44
|
+
|
|
36
45
|
## Installation
|
|
37
46
|
|
|
38
47
|
```bash
|
|
39
48
|
# Using pipx (recommended)
|
|
40
|
-
pipx install hire
|
|
49
|
+
pipx install hire-ai
|
|
41
50
|
|
|
42
51
|
# Using pip
|
|
43
|
-
pip install hire
|
|
52
|
+
pip install hire-ai
|
|
44
53
|
|
|
45
|
-
# Using Homebrew
|
|
46
|
-
brew install nichiki/tap/hire
|
|
54
|
+
# Using Homebrew (macOS)
|
|
55
|
+
brew install nichiki/tap/hire-ai
|
|
47
56
|
```
|
|
48
57
|
|
|
49
58
|
## Prerequisites
|
|
50
59
|
|
|
51
60
|
You need at least one of the following CLI tools installed:
|
|
52
61
|
|
|
53
|
-
- [Claude
|
|
54
|
-
- [Codex
|
|
62
|
+
- [Claude Code](https://claude.ai/claude-code)
|
|
63
|
+
- [Codex](https://github.com/openai/codex)
|
|
55
64
|
- [Gemini CLI](https://github.com/google-gemini/gemini-cli)
|
|
56
65
|
|
|
57
66
|
## Usage
|
|
@@ -70,9 +79,24 @@ hire -s SESSION_ID "Follow up question"
|
|
|
70
79
|
hire -n my-project codex "Start designing the architecture"
|
|
71
80
|
hire -s my-project "What about the database schema?"
|
|
72
81
|
|
|
82
|
+
# Pipe input
|
|
83
|
+
cat main.py | hire codex "Review this code"
|
|
84
|
+
git diff | hire claude "Explain these changes"
|
|
85
|
+
echo "What is 2+2?" | hire gemini
|
|
86
|
+
|
|
87
|
+
# Attach files (using @filepath - agent feature)
|
|
88
|
+
hire claude "Review @src/main.py for security issues"
|
|
89
|
+
hire codex "Explain @package.json and @tsconfig.json"
|
|
90
|
+
|
|
73
91
|
# Output as JSON
|
|
74
92
|
hire gemini "Summarize this" --json
|
|
75
93
|
|
|
94
|
+
# Copy to clipboard
|
|
95
|
+
hire codex "Write a function" --clip
|
|
96
|
+
|
|
97
|
+
# Write to file
|
|
98
|
+
hire claude "Generate a README" -o README.md
|
|
99
|
+
|
|
76
100
|
# Session management
|
|
77
101
|
hire sessions # List all sessions
|
|
78
102
|
hire sessions codex # List Codex sessions only
|
|
@@ -89,6 +113,8 @@ hire delete SESSION_ID # Delete a session
|
|
|
89
113
|
| `-n, --name NAME` | Name the session |
|
|
90
114
|
| `-m, --model MODEL` | Specify model to use |
|
|
91
115
|
| `--json` | Output in JSON format |
|
|
116
|
+
| `--clip` | Copy output to clipboard |
|
|
117
|
+
| `-o, --out FILE` | Write output to file |
|
|
92
118
|
|
|
93
119
|
## Configuration
|
|
94
120
|
|
|
@@ -1,26 +1,34 @@
|
|
|
1
|
-
# hire
|
|
1
|
+
# hire-ai
|
|
2
2
|
|
|
3
3
|
CLI to orchestrate AI agents (Claude, Codex, Gemini).
|
|
4
4
|
|
|
5
|
+
> **⚠️ Warning**: By default, all agents run in **auto-approve mode**:
|
|
6
|
+
> - Claude Code: `--dangerously-skip-permissions`
|
|
7
|
+
> - Codex: `--full-auto`
|
|
8
|
+
> - Gemini CLI: `-y`
|
|
9
|
+
>
|
|
10
|
+
> This means agents can execute commands and modify files without confirmation.
|
|
11
|
+
> You can customize this in `~/.config/hire/config.json`.
|
|
12
|
+
|
|
5
13
|
## Installation
|
|
6
14
|
|
|
7
15
|
```bash
|
|
8
16
|
# Using pipx (recommended)
|
|
9
|
-
pipx install hire
|
|
17
|
+
pipx install hire-ai
|
|
10
18
|
|
|
11
19
|
# Using pip
|
|
12
|
-
pip install hire
|
|
20
|
+
pip install hire-ai
|
|
13
21
|
|
|
14
|
-
# Using Homebrew
|
|
15
|
-
brew install nichiki/tap/hire
|
|
22
|
+
# Using Homebrew (macOS)
|
|
23
|
+
brew install nichiki/tap/hire-ai
|
|
16
24
|
```
|
|
17
25
|
|
|
18
26
|
## Prerequisites
|
|
19
27
|
|
|
20
28
|
You need at least one of the following CLI tools installed:
|
|
21
29
|
|
|
22
|
-
- [Claude
|
|
23
|
-
- [Codex
|
|
30
|
+
- [Claude Code](https://claude.ai/claude-code)
|
|
31
|
+
- [Codex](https://github.com/openai/codex)
|
|
24
32
|
- [Gemini CLI](https://github.com/google-gemini/gemini-cli)
|
|
25
33
|
|
|
26
34
|
## Usage
|
|
@@ -39,9 +47,24 @@ hire -s SESSION_ID "Follow up question"
|
|
|
39
47
|
hire -n my-project codex "Start designing the architecture"
|
|
40
48
|
hire -s my-project "What about the database schema?"
|
|
41
49
|
|
|
50
|
+
# Pipe input
|
|
51
|
+
cat main.py | hire codex "Review this code"
|
|
52
|
+
git diff | hire claude "Explain these changes"
|
|
53
|
+
echo "What is 2+2?" | hire gemini
|
|
54
|
+
|
|
55
|
+
# Attach files (using @filepath - agent feature)
|
|
56
|
+
hire claude "Review @src/main.py for security issues"
|
|
57
|
+
hire codex "Explain @package.json and @tsconfig.json"
|
|
58
|
+
|
|
42
59
|
# Output as JSON
|
|
43
60
|
hire gemini "Summarize this" --json
|
|
44
61
|
|
|
62
|
+
# Copy to clipboard
|
|
63
|
+
hire codex "Write a function" --clip
|
|
64
|
+
|
|
65
|
+
# Write to file
|
|
66
|
+
hire claude "Generate a README" -o README.md
|
|
67
|
+
|
|
45
68
|
# Session management
|
|
46
69
|
hire sessions # List all sessions
|
|
47
70
|
hire sessions codex # List Codex sessions only
|
|
@@ -58,6 +81,8 @@ hire delete SESSION_ID # Delete a session
|
|
|
58
81
|
| `-n, --name NAME` | Name the session |
|
|
59
82
|
| `-m, --model MODEL` | Specify model to use |
|
|
60
83
|
| `--json` | Output in JSON format |
|
|
84
|
+
| `--clip` | Copy output to clipboard |
|
|
85
|
+
| `-o, --out FILE` | Write output to file |
|
|
61
86
|
|
|
62
87
|
## Configuration
|
|
63
88
|
|
|
@@ -4,10 +4,10 @@ import argparse
|
|
|
4
4
|
import sys
|
|
5
5
|
|
|
6
6
|
from . import __version__
|
|
7
|
-
from .commands import run_ask, run_delete, run_sessions, run_show
|
|
7
|
+
from .commands import run_ask, run_delete, run_doctor, run_sessions, run_show
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
SUBCOMMANDS = {"sessions", "show", "delete", "help", "--help", "-h", "--version"}
|
|
10
|
+
SUBCOMMANDS = {"sessions", "show", "delete", "doctor", "help", "--help", "-h", "--version"}
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
def main() -> int:
|
|
@@ -68,6 +68,9 @@ def main() -> int:
|
|
|
68
68
|
help="Delete without confirmation",
|
|
69
69
|
)
|
|
70
70
|
|
|
71
|
+
# doctor command
|
|
72
|
+
subparsers.add_parser("doctor", help="Check environment and agent availability")
|
|
73
|
+
|
|
71
74
|
args = parser.parse_args()
|
|
72
75
|
|
|
73
76
|
if args.command is None:
|
|
@@ -81,6 +84,8 @@ def main() -> int:
|
|
|
81
84
|
return run_show(args)
|
|
82
85
|
elif args.command == "delete":
|
|
83
86
|
return run_delete(args)
|
|
87
|
+
elif args.command == "doctor":
|
|
88
|
+
return run_doctor(args)
|
|
84
89
|
else:
|
|
85
90
|
print_usage()
|
|
86
91
|
return 1
|
|
@@ -126,6 +131,16 @@ def run_default() -> int:
|
|
|
126
131
|
action="store_true",
|
|
127
132
|
help="Output in JSON format",
|
|
128
133
|
)
|
|
134
|
+
parser.add_argument(
|
|
135
|
+
"--clip",
|
|
136
|
+
action="store_true",
|
|
137
|
+
help="Copy output to clipboard",
|
|
138
|
+
)
|
|
139
|
+
parser.add_argument(
|
|
140
|
+
"-o", "--out",
|
|
141
|
+
metavar="FILE",
|
|
142
|
+
help="Write output to file",
|
|
143
|
+
)
|
|
129
144
|
|
|
130
145
|
args = parser.parse_args()
|
|
131
146
|
return run_ask(args)
|
|
@@ -141,6 +156,7 @@ Usage:
|
|
|
141
156
|
hire sessions [target] List sessions
|
|
142
157
|
hire show <name-or-id> Show session details
|
|
143
158
|
hire delete <name-or-id> Delete a session
|
|
159
|
+
hire doctor Check environment
|
|
144
160
|
|
|
145
161
|
Targets:
|
|
146
162
|
claude, codex, gemini
|
|
@@ -151,6 +167,8 @@ Options:
|
|
|
151
167
|
-n, --name NAME Name the session
|
|
152
168
|
-m, --model MODEL Specify model
|
|
153
169
|
--json Output in JSON format
|
|
170
|
+
--clip Copy output to clipboard
|
|
171
|
+
-o, --out FILE Write output to file
|
|
154
172
|
|
|
155
173
|
Examples:
|
|
156
174
|
hire codex "Design a REST API"
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""Clipboard utilities."""
|
|
2
|
+
|
|
3
|
+
import platform
|
|
4
|
+
import subprocess
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def copy_to_clipboard(text: str) -> bool:
|
|
8
|
+
"""Copy text to system clipboard. Returns True on success."""
|
|
9
|
+
system = platform.system()
|
|
10
|
+
try:
|
|
11
|
+
if system == "Darwin": # macOS
|
|
12
|
+
# Don't override env - let system locale handle it
|
|
13
|
+
subprocess.run(
|
|
14
|
+
["pbcopy"],
|
|
15
|
+
input=text,
|
|
16
|
+
text=True,
|
|
17
|
+
encoding="utf-8",
|
|
18
|
+
check=True,
|
|
19
|
+
)
|
|
20
|
+
elif system == "Linux":
|
|
21
|
+
# Try xclip first, fall back to xsel
|
|
22
|
+
try:
|
|
23
|
+
subprocess.run(
|
|
24
|
+
["xclip", "-selection", "clipboard"],
|
|
25
|
+
input=text.encode("utf-8"),
|
|
26
|
+
check=True,
|
|
27
|
+
)
|
|
28
|
+
except FileNotFoundError:
|
|
29
|
+
subprocess.run(
|
|
30
|
+
["xsel", "--clipboard", "--input"],
|
|
31
|
+
input=text.encode("utf-8"),
|
|
32
|
+
check=True,
|
|
33
|
+
)
|
|
34
|
+
elif system == "Windows":
|
|
35
|
+
subprocess.run(["clip"], input=text.encode("utf-8"), check=True)
|
|
36
|
+
else:
|
|
37
|
+
return False
|
|
38
|
+
return True
|
|
39
|
+
except (subprocess.CalledProcessError, FileNotFoundError):
|
|
40
|
+
return False
|
|
@@ -4,5 +4,6 @@ from .ask import run_ask
|
|
|
4
4
|
from .sessions import run_sessions
|
|
5
5
|
from .show import run_show
|
|
6
6
|
from .delete import run_delete
|
|
7
|
+
from .doctor import run_doctor
|
|
7
8
|
|
|
8
|
-
__all__ = ["run_ask", "run_sessions", "run_show", "run_delete"]
|
|
9
|
+
__all__ = ["run_ask", "run_sessions", "run_show", "run_delete", "run_doctor"]
|
|
@@ -5,6 +5,7 @@ import sys
|
|
|
5
5
|
from argparse import Namespace
|
|
6
6
|
|
|
7
7
|
from ..adapters import get_adapter
|
|
8
|
+
from ..clipboard import copy_to_clipboard
|
|
8
9
|
from ..session import (
|
|
9
10
|
create_session,
|
|
10
11
|
find_session,
|
|
@@ -14,25 +15,49 @@ from ..session import (
|
|
|
14
15
|
)
|
|
15
16
|
|
|
16
17
|
|
|
18
|
+
def read_stdin() -> str | None:
|
|
19
|
+
"""Read from stdin if available (pipe/redirect)."""
|
|
20
|
+
if sys.stdin.isatty():
|
|
21
|
+
return None
|
|
22
|
+
content = sys.stdin.read()
|
|
23
|
+
return content.strip() if content else None
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def build_message(message: str | None, stdin: str | None) -> str | None:
|
|
27
|
+
"""Build the final message from args and stdin."""
|
|
28
|
+
if message and stdin:
|
|
29
|
+
return f"{message}\n\n--- stdin ---\n{stdin}"
|
|
30
|
+
elif stdin:
|
|
31
|
+
return stdin
|
|
32
|
+
else:
|
|
33
|
+
return message
|
|
34
|
+
|
|
35
|
+
|
|
17
36
|
VALID_TARGETS = {"claude", "codex", "gemini"}
|
|
18
37
|
|
|
19
38
|
|
|
20
39
|
def run_ask(args: Namespace) -> int:
|
|
21
40
|
"""Run the ask command."""
|
|
22
41
|
target = args.target
|
|
23
|
-
|
|
42
|
+
arg_message = args.message
|
|
43
|
+
stdin_content = read_stdin()
|
|
24
44
|
continue_session = getattr(args, "continue_session", False)
|
|
25
45
|
session_id = args.session
|
|
26
46
|
name = args.name
|
|
27
47
|
model = args.model
|
|
28
48
|
output_json = args.json
|
|
49
|
+
copy_clip = getattr(args, "clip", False)
|
|
50
|
+
out_file = getattr(args, "out", None)
|
|
29
51
|
|
|
30
52
|
# Handle case where target is actually the message (when target is omitted)
|
|
31
|
-
# e.g., "
|
|
32
|
-
if target and target not in VALID_TARGETS and
|
|
33
|
-
|
|
53
|
+
# e.g., "hire 'message'" -> target='message', message=None
|
|
54
|
+
if target and target not in VALID_TARGETS and arg_message is None:
|
|
55
|
+
arg_message = target
|
|
34
56
|
target = None
|
|
35
57
|
|
|
58
|
+
# Build final message from args and stdin
|
|
59
|
+
message = build_message(arg_message, stdin_content)
|
|
60
|
+
|
|
36
61
|
# Load config for defaults
|
|
37
62
|
from ..config import load_config
|
|
38
63
|
config = load_config()
|
|
@@ -136,8 +161,26 @@ def run_ask(args: Namespace) -> int:
|
|
|
136
161
|
"agent": target,
|
|
137
162
|
"name": session.get("name"),
|
|
138
163
|
}
|
|
139
|
-
|
|
164
|
+
output_text = json.dumps(output, indent=2, ensure_ascii=False)
|
|
140
165
|
else:
|
|
141
|
-
|
|
166
|
+
output_text = result.get("response", "")
|
|
167
|
+
|
|
168
|
+
print(output_text)
|
|
169
|
+
|
|
170
|
+
# Copy to clipboard if requested
|
|
171
|
+
if copy_clip:
|
|
172
|
+
if copy_to_clipboard(output_text):
|
|
173
|
+
print("\n(Copied to clipboard)", file=sys.stderr)
|
|
174
|
+
else:
|
|
175
|
+
print("\n(Failed to copy to clipboard)", file=sys.stderr)
|
|
176
|
+
|
|
177
|
+
# Write to file if requested
|
|
178
|
+
if out_file:
|
|
179
|
+
try:
|
|
180
|
+
with open(out_file, "w", encoding="utf-8") as f:
|
|
181
|
+
f.write(output_text)
|
|
182
|
+
print(f"\n(Written to {out_file})", file=sys.stderr)
|
|
183
|
+
except OSError as e:
|
|
184
|
+
print(f"\n(Failed to write to {out_file}: {e})", file=sys.stderr)
|
|
142
185
|
|
|
143
186
|
return 0
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""Doctor command implementation."""
|
|
2
|
+
|
|
3
|
+
import shutil
|
|
4
|
+
import sys
|
|
5
|
+
from argparse import Namespace
|
|
6
|
+
|
|
7
|
+
from .. import __version__
|
|
8
|
+
from ..paths import get_config_path, get_sessions_dir
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
AGENTS = {
|
|
12
|
+
"claude": "claude",
|
|
13
|
+
"codex": "codex",
|
|
14
|
+
"gemini": "gemini",
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def run_doctor(args: Namespace) -> int:
|
|
19
|
+
"""Run the doctor command to check environment."""
|
|
20
|
+
print(f"hire-ai v{__version__}")
|
|
21
|
+
print(f"Python {sys.version.split()[0]}")
|
|
22
|
+
print()
|
|
23
|
+
|
|
24
|
+
# Check agents
|
|
25
|
+
print("Checking agents...")
|
|
26
|
+
found = 0
|
|
27
|
+
missing = 0
|
|
28
|
+
for name, cmd in AGENTS.items():
|
|
29
|
+
path = shutil.which(cmd)
|
|
30
|
+
if path:
|
|
31
|
+
print(f" \u2713 {name} - {path}")
|
|
32
|
+
found += 1
|
|
33
|
+
else:
|
|
34
|
+
print(f" \u2717 {name} - not found")
|
|
35
|
+
missing += 1
|
|
36
|
+
print()
|
|
37
|
+
|
|
38
|
+
# Check config
|
|
39
|
+
print("Checking config...")
|
|
40
|
+
config_path = get_config_path()
|
|
41
|
+
if config_path.exists():
|
|
42
|
+
print(f" \u2713 Config: {config_path}")
|
|
43
|
+
else:
|
|
44
|
+
print(f" - Config: {config_path} (not created yet, using defaults)")
|
|
45
|
+
|
|
46
|
+
sessions_dir = get_sessions_dir()
|
|
47
|
+
session_count = sum(1 for _ in sessions_dir.rglob("*.json"))
|
|
48
|
+
print(f" \u2713 Sessions: {sessions_dir} ({session_count} sessions)")
|
|
49
|
+
print()
|
|
50
|
+
|
|
51
|
+
# Summary
|
|
52
|
+
if missing == 0:
|
|
53
|
+
print("All good!")
|
|
54
|
+
elif found == 0:
|
|
55
|
+
print("No agents found. Install at least one of: claude, codex, gemini")
|
|
56
|
+
return 1
|
|
57
|
+
else:
|
|
58
|
+
print(f"Ready! ({missing} agent(s) not installed)")
|
|
59
|
+
|
|
60
|
+
return 0
|
|
@@ -4,11 +4,11 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "hire-ai"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.2"
|
|
8
8
|
description = "CLI to orchestrate AI agents (Claude, Codex, Gemini)"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
11
|
-
requires-python = ">=3.
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
12
|
authors = [
|
|
13
13
|
{ name = "nichiki" }
|
|
14
14
|
]
|
|
@@ -20,6 +20,7 @@ classifiers = [
|
|
|
20
20
|
"License :: OSI Approved :: MIT License",
|
|
21
21
|
"Operating System :: OS Independent",
|
|
22
22
|
"Programming Language :: Python :: 3",
|
|
23
|
+
"Programming Language :: Python :: 3.10",
|
|
23
24
|
"Programming Language :: Python :: 3.11",
|
|
24
25
|
"Programming Language :: Python :: 3.12",
|
|
25
26
|
"Programming Language :: Python :: 3.13",
|
|
@@ -38,9 +39,9 @@ dev = [
|
|
|
38
39
|
]
|
|
39
40
|
|
|
40
41
|
[project.urls]
|
|
41
|
-
Homepage = "https://github.com/nichiki/hire"
|
|
42
|
-
Repository = "https://github.com/nichiki/hire"
|
|
43
|
-
Issues = "https://github.com/nichiki/hire/issues"
|
|
42
|
+
Homepage = "https://github.com/nichiki/hire-ai"
|
|
43
|
+
Repository = "https://github.com/nichiki/hire-ai"
|
|
44
|
+
Issues = "https://github.com/nichiki/hire-ai/issues"
|
|
44
45
|
|
|
45
46
|
[project.scripts]
|
|
46
47
|
hire = "hire.cli:main"
|
|
@@ -49,14 +50,14 @@ hire = "hire.cli:main"
|
|
|
49
50
|
packages = ["hire"]
|
|
50
51
|
|
|
51
52
|
[tool.ruff]
|
|
52
|
-
target-version = "
|
|
53
|
+
target-version = "py310"
|
|
53
54
|
line-length = 100
|
|
54
55
|
|
|
55
56
|
[tool.ruff.lint]
|
|
56
57
|
select = ["E", "F", "I", "N", "W", "UP", "B", "C4", "SIM"]
|
|
57
58
|
|
|
58
59
|
[tool.mypy]
|
|
59
|
-
python_version = "3.
|
|
60
|
+
python_version = "3.10"
|
|
60
61
|
strict = false
|
|
61
62
|
warn_return_any = true
|
|
62
63
|
warn_unused_configs = true
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|