conduct-cli 0.7.2__tar.gz → 0.7.4__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.
- {conduct_cli-0.7.2 → conduct_cli-0.7.4}/PKG-INFO +32 -1
- {conduct_cli-0.7.2 → conduct_cli-0.7.4}/README.md +31 -0
- {conduct_cli-0.7.2 → conduct_cli-0.7.4}/pyproject.toml +1 -1
- {conduct_cli-0.7.2 → conduct_cli-0.7.4}/src/conduct_cli/guard.py +21 -6
- {conduct_cli-0.7.2 → conduct_cli-0.7.4}/src/conduct_cli.egg-info/PKG-INFO +32 -1
- {conduct_cli-0.7.2 → conduct_cli-0.7.4}/setup.cfg +0 -0
- {conduct_cli-0.7.2 → conduct_cli-0.7.4}/setup.py +0 -0
- {conduct_cli-0.7.2 → conduct_cli-0.7.4}/src/conduct_cli/__init__.py +0 -0
- {conduct_cli-0.7.2 → conduct_cli-0.7.4}/src/conduct_cli/api.py +0 -0
- {conduct_cli-0.7.2 → conduct_cli-0.7.4}/src/conduct_cli/guardmcp.py +0 -0
- {conduct_cli-0.7.2 → conduct_cli-0.7.4}/src/conduct_cli/hooks/__init__.py +0 -0
- {conduct_cli-0.7.2 → conduct_cli-0.7.4}/src/conduct_cli/hooks/base.py +0 -0
- {conduct_cli-0.7.2 → conduct_cli-0.7.4}/src/conduct_cli/hooks/posttooluse.py +0 -0
- {conduct_cli-0.7.2 → conduct_cli-0.7.4}/src/conduct_cli/hooks/precompact.py +0 -0
- {conduct_cli-0.7.2 → conduct_cli-0.7.4}/src/conduct_cli/hooks/pretooluse.py +0 -0
- {conduct_cli-0.7.2 → conduct_cli-0.7.4}/src/conduct_cli/hooks/session_parser.py +0 -0
- {conduct_cli-0.7.2 → conduct_cli-0.7.4}/src/conduct_cli/hooks/session_start.py +0 -0
- {conduct_cli-0.7.2 → conduct_cli-0.7.4}/src/conduct_cli/hooks/stop.py +0 -0
- {conduct_cli-0.7.2 → conduct_cli-0.7.4}/src/conduct_cli/log_util.py +0 -0
- {conduct_cli-0.7.2 → conduct_cli-0.7.4}/src/conduct_cli/main.py +0 -0
- {conduct_cli-0.7.2 → conduct_cli-0.7.4}/src/conduct_cli/mcp_server.py +0 -0
- {conduct_cli-0.7.2 → conduct_cli-0.7.4}/src/conduct_cli/memory.py +0 -0
- {conduct_cli-0.7.2 → conduct_cli-0.7.4}/src/conduct_cli/paxel.py +0 -0
- {conduct_cli-0.7.2 → conduct_cli-0.7.4}/src/conduct_cli.egg-info/SOURCES.txt +0 -0
- {conduct_cli-0.7.2 → conduct_cli-0.7.4}/src/conduct_cli.egg-info/dependency_links.txt +0 -0
- {conduct_cli-0.7.2 → conduct_cli-0.7.4}/src/conduct_cli.egg-info/entry_points.txt +0 -0
- {conduct_cli-0.7.2 → conduct_cli-0.7.4}/src/conduct_cli.egg-info/requires.txt +0 -0
- {conduct_cli-0.7.2 → conduct_cli-0.7.4}/src/conduct_cli.egg-info/top_level.txt +0 -0
- {conduct_cli-0.7.2 → conduct_cli-0.7.4}/tests/test_advisory_and_hook.py +0 -0
- {conduct_cli-0.7.2 → conduct_cli-0.7.4}/tests/test_bash_operator_signature.py +0 -0
- {conduct_cli-0.7.2 → conduct_cli-0.7.4}/tests/test_command_word_matcher.py +0 -0
- {conduct_cli-0.7.2 → conduct_cli-0.7.4}/tests/test_guard_policy.py +0 -0
- {conduct_cli-0.7.2 → conduct_cli-0.7.4}/tests/test_guard_savings.py +0 -0
- {conduct_cli-0.7.2 → conduct_cli-0.7.4}/tests/test_hook_syntax.py +0 -0
- {conduct_cli-0.7.2 → conduct_cli-0.7.4}/tests/test_journal_drain.py +0 -0
- {conduct_cli-0.7.2 → conduct_cli-0.7.4}/tests/test_log_util.py +0 -0
- {conduct_cli-0.7.2 → conduct_cli-0.7.4}/tests/test_proxy_env.py +0 -0
- {conduct_cli-0.7.2 → conduct_cli-0.7.4}/tests/test_signed_policy.py +0 -0
- {conduct_cli-0.7.2 → conduct_cli-0.7.4}/tests/test_switch.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: conduct-cli
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.4
|
|
4
4
|
Summary: CLI for Conduct AI — secure, govern, install agents, manage projects, run tests
|
|
5
5
|
Author-email: Conduct AI <hello@conductai.ai>
|
|
6
6
|
License: MIT
|
|
@@ -152,6 +152,37 @@ That's it. Policy enforcement is active from the next tool call.
|
|
|
152
152
|
| `conduct guard sync` | Pull latest policy, write hook to `~/.conductguard/hook.py`, register hook + MCP |
|
|
153
153
|
| `conduct guard status` | Show today's spend, session count, and violations |
|
|
154
154
|
| `conduct guard audit [--since 7d]` | Print recent guard events in a table |
|
|
155
|
+
| `conduct verify [--evidence FILE] [--strict] [--format json]` | Map guard events to OWASP Agentic Top 10; exit 1 in CI if blocked events (--strict) |
|
|
156
|
+
| `conduct guard discover` | Scan local environment for AI agents; report Guard coverage % |
|
|
157
|
+
| `conduct guard discover --register` | Register discovered agents under Guard |
|
|
158
|
+
|
|
159
|
+
### Advisory mode
|
|
160
|
+
|
|
161
|
+
When advisory mode is enabled by your security admin, all policy violations are logged as "audited" instead of blocked — the developer sees a note but the tool call proceeds. The hook still posts every event to the audit log.
|
|
162
|
+
|
|
163
|
+
To check if advisory mode is active:
|
|
164
|
+
```bash
|
|
165
|
+
conduct guard sync # shows "· advisory" badge if active
|
|
166
|
+
conduct guard status
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### conduct verify
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
# Map last 24h of guard events to OWASP Agentic Top 10
|
|
173
|
+
conduct verify
|
|
174
|
+
|
|
175
|
+
# Use a saved evidence file
|
|
176
|
+
conduct verify --evidence ./conduct-evidence.json
|
|
177
|
+
|
|
178
|
+
# CI mode — exit 1 if any blocked events
|
|
179
|
+
conduct verify --strict
|
|
180
|
+
|
|
181
|
+
# JSON output for downstream tooling
|
|
182
|
+
conduct verify --format json
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
OWASP mapping: `no-rm-rf` → A04 Excessive Agency, `no-sudo` → A09 Privilege Escalation, `policy_signature_invalid` → A07 Insufficient Monitoring, etc. All 10 categories covered.
|
|
155
186
|
|
|
156
187
|
### How the PreToolUse hook works
|
|
157
188
|
|
|
@@ -124,6 +124,37 @@ That's it. Policy enforcement is active from the next tool call.
|
|
|
124
124
|
| `conduct guard sync` | Pull latest policy, write hook to `~/.conductguard/hook.py`, register hook + MCP |
|
|
125
125
|
| `conduct guard status` | Show today's spend, session count, and violations |
|
|
126
126
|
| `conduct guard audit [--since 7d]` | Print recent guard events in a table |
|
|
127
|
+
| `conduct verify [--evidence FILE] [--strict] [--format json]` | Map guard events to OWASP Agentic Top 10; exit 1 in CI if blocked events (--strict) |
|
|
128
|
+
| `conduct guard discover` | Scan local environment for AI agents; report Guard coverage % |
|
|
129
|
+
| `conduct guard discover --register` | Register discovered agents under Guard |
|
|
130
|
+
|
|
131
|
+
### Advisory mode
|
|
132
|
+
|
|
133
|
+
When advisory mode is enabled by your security admin, all policy violations are logged as "audited" instead of blocked — the developer sees a note but the tool call proceeds. The hook still posts every event to the audit log.
|
|
134
|
+
|
|
135
|
+
To check if advisory mode is active:
|
|
136
|
+
```bash
|
|
137
|
+
conduct guard sync # shows "· advisory" badge if active
|
|
138
|
+
conduct guard status
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### conduct verify
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
# Map last 24h of guard events to OWASP Agentic Top 10
|
|
145
|
+
conduct verify
|
|
146
|
+
|
|
147
|
+
# Use a saved evidence file
|
|
148
|
+
conduct verify --evidence ./conduct-evidence.json
|
|
149
|
+
|
|
150
|
+
# CI mode — exit 1 if any blocked events
|
|
151
|
+
conduct verify --strict
|
|
152
|
+
|
|
153
|
+
# JSON output for downstream tooling
|
|
154
|
+
conduct verify --format json
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
OWASP mapping: `no-rm-rf` → A04 Excessive Agency, `no-sudo` → A09 Privilege Escalation, `policy_signature_invalid` → A07 Insufficient Monitoring, etc. All 10 categories covered.
|
|
127
158
|
|
|
128
159
|
### How the PreToolUse hook works
|
|
129
160
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "conduct-cli"
|
|
7
|
-
version = "0.7.
|
|
7
|
+
version = "0.7.4"
|
|
8
8
|
description = "CLI for Conduct AI — secure, govern, install agents, manage projects, run tests"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "MIT" }
|
|
@@ -1699,7 +1699,8 @@ def cmd_guard_status(args):
|
|
|
1699
1699
|
violations = [e for e in events if e.get("decision") == "blocked"]
|
|
1700
1700
|
|
|
1701
1701
|
# Format spend figures
|
|
1702
|
-
|
|
1702
|
+
proxy_sessions = spend.get("sessions", 0)
|
|
1703
|
+
hook_sessions = spend.get("hook_sessions", 0)
|
|
1703
1704
|
tokens_used = spend.get("tokens_used", 0)
|
|
1704
1705
|
token_saved_pct = spend.get("token_saved_pct", 0)
|
|
1705
1706
|
cost = spend.get("cost_usd", 0.0)
|
|
@@ -1707,14 +1708,16 @@ def cmd_guard_status(args):
|
|
|
1707
1708
|
|
|
1708
1709
|
viol_summary = ""
|
|
1709
1710
|
if violations:
|
|
1710
|
-
rule_names = ", ".join(v.get("rule", "unknown") for v in violations[:3])
|
|
1711
|
+
rule_names = ", ".join(v.get("rule_id") or v.get("rule", "unknown") for v in violations[:3])
|
|
1711
1712
|
viol_summary = f" ({rule_names} — blocked)"
|
|
1712
1713
|
|
|
1714
|
+
session_str = f"{proxy_sessions} proxy · {hook_sessions} direct"
|
|
1715
|
+
|
|
1713
1716
|
print(f"\n{BOLD}Guard status{RESET} — {user_email}")
|
|
1714
1717
|
print(f"{rule_count} polic{'y' if rule_count == 1 else 'ies'} active")
|
|
1715
1718
|
print()
|
|
1716
1719
|
print(f"Today:")
|
|
1717
|
-
print(f" Sessions: {
|
|
1720
|
+
print(f" Sessions: {session_str}")
|
|
1718
1721
|
print(f" Tokens used: {tokens_used:,} (saved {token_saved_pct}% via optimization)")
|
|
1719
1722
|
print(f" Cost: ${cost:.2f} (saved ${cost_saved:.2f})")
|
|
1720
1723
|
print(f" Violations: {len(violations)}{viol_summary}")
|
|
@@ -1927,16 +1930,28 @@ def _discover_config_agents() -> list[tuple]:
|
|
|
1927
1930
|
|
|
1928
1931
|
def _mcp_registered(path: Path) -> bool:
|
|
1929
1932
|
try:
|
|
1933
|
+
if not path.exists():
|
|
1934
|
+
return False
|
|
1935
|
+
text = path.read_text()
|
|
1936
|
+
if path.suffix == ".toml":
|
|
1937
|
+
# conduct-mcp or conductai in mcp_servers section
|
|
1938
|
+
return "conduct" in text and "mcp_servers" in text
|
|
1930
1939
|
import json as _j
|
|
1931
|
-
d = _j.loads(
|
|
1940
|
+
d = _j.loads(text)
|
|
1932
1941
|
return "conduct" in d.get("mcpServers", {})
|
|
1933
1942
|
except Exception:
|
|
1934
1943
|
return False
|
|
1935
1944
|
|
|
1936
1945
|
def _hook_registered(path: Path) -> bool:
|
|
1937
1946
|
try:
|
|
1947
|
+
if not path.exists():
|
|
1948
|
+
# Codex: check hooks.json sibling
|
|
1949
|
+
hooks_path = path.parent / "hooks.json"
|
|
1950
|
+
if hooks_path.exists():
|
|
1951
|
+
return "conductguard" in hooks_path.read_text()
|
|
1952
|
+
return False
|
|
1938
1953
|
import json as _j
|
|
1939
|
-
d = _j.loads(path.read_text())
|
|
1954
|
+
d = _j.loads(path.read_text())
|
|
1940
1955
|
hooks = d.get("hooks", {})
|
|
1941
1956
|
return any("conductguard" in str(h).lower() or "conduct" in str(h).lower()
|
|
1942
1957
|
for h in hooks.get("PreToolUse", []))
|
|
@@ -1946,7 +1961,7 @@ def _discover_config_agents() -> list[tuple]:
|
|
|
1946
1961
|
# Known tool config locations
|
|
1947
1962
|
TOOLS = [
|
|
1948
1963
|
("claude-code", home / ".claude", home / ".claude" / "settings.json", "mcp"),
|
|
1949
|
-
("codex", home / ".codex", home / ".codex" / "
|
|
1964
|
+
("codex", home / ".codex", home / ".codex" / "config.toml", "mcp"),
|
|
1950
1965
|
("cursor", home / ".cursor", home / ".cursor" / "mcp.json", "mcp"),
|
|
1951
1966
|
("windsurf", home / ".codeium" / "windsurf", home / ".codeium" / "windsurf" / "mcp_config.json", "mcp"),
|
|
1952
1967
|
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: conduct-cli
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.4
|
|
4
4
|
Summary: CLI for Conduct AI — secure, govern, install agents, manage projects, run tests
|
|
5
5
|
Author-email: Conduct AI <hello@conductai.ai>
|
|
6
6
|
License: MIT
|
|
@@ -152,6 +152,37 @@ That's it. Policy enforcement is active from the next tool call.
|
|
|
152
152
|
| `conduct guard sync` | Pull latest policy, write hook to `~/.conductguard/hook.py`, register hook + MCP |
|
|
153
153
|
| `conduct guard status` | Show today's spend, session count, and violations |
|
|
154
154
|
| `conduct guard audit [--since 7d]` | Print recent guard events in a table |
|
|
155
|
+
| `conduct verify [--evidence FILE] [--strict] [--format json]` | Map guard events to OWASP Agentic Top 10; exit 1 in CI if blocked events (--strict) |
|
|
156
|
+
| `conduct guard discover` | Scan local environment for AI agents; report Guard coverage % |
|
|
157
|
+
| `conduct guard discover --register` | Register discovered agents under Guard |
|
|
158
|
+
|
|
159
|
+
### Advisory mode
|
|
160
|
+
|
|
161
|
+
When advisory mode is enabled by your security admin, all policy violations are logged as "audited" instead of blocked — the developer sees a note but the tool call proceeds. The hook still posts every event to the audit log.
|
|
162
|
+
|
|
163
|
+
To check if advisory mode is active:
|
|
164
|
+
```bash
|
|
165
|
+
conduct guard sync # shows "· advisory" badge if active
|
|
166
|
+
conduct guard status
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### conduct verify
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
# Map last 24h of guard events to OWASP Agentic Top 10
|
|
173
|
+
conduct verify
|
|
174
|
+
|
|
175
|
+
# Use a saved evidence file
|
|
176
|
+
conduct verify --evidence ./conduct-evidence.json
|
|
177
|
+
|
|
178
|
+
# CI mode — exit 1 if any blocked events
|
|
179
|
+
conduct verify --strict
|
|
180
|
+
|
|
181
|
+
# JSON output for downstream tooling
|
|
182
|
+
conduct verify --format json
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
OWASP mapping: `no-rm-rf` → A04 Excessive Agency, `no-sudo` → A09 Privilege Escalation, `policy_signature_invalid` → A07 Insufficient Monitoring, etc. All 10 categories covered.
|
|
155
186
|
|
|
156
187
|
### How the PreToolUse hook works
|
|
157
188
|
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|