brindle 0.4.6__tar.gz → 0.5.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.
- {brindle-0.4.6 → brindle-0.5.0}/PKG-INFO +64 -73
- {brindle-0.4.6 → brindle-0.5.0}/README.md +63 -72
- {brindle-0.4.6 → brindle-0.5.0}/pyproject.toml +1 -1
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/agents.py +189 -108
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/antigravity.py +12 -15
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/cli.py +31 -7
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/daemon/api-schema.json +2734 -2430
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/daemon/app.py +1 -4
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/daemon/holds.py +6 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/daemon/routes_actions.py +216 -26
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/daemon/routes_read.py +28 -12
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/db.py +6 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/native/permissions.py +2 -1
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/native/runner.py +11 -9
- brindle-0.5.0/src/brindle/permission_grants.py +799 -0
- brindle-0.5.0/src/brindle/permissions.py +3129 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/providers.py +40 -9
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/service/dto.py +179 -115
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/service/inbox.py +4 -131
- brindle-0.5.0/src/brindle/service/permissions.py +135 -0
- brindle-0.4.6/src/brindle/daemon/grants.py +0 -320
- brindle-0.4.6/src/brindle/daemon/routes_permissions.py +0 -37
- brindle-0.4.6/src/brindle/permission_editor.py +0 -350
- brindle-0.4.6/src/brindle/permission_grants.py +0 -646
- brindle-0.4.6/src/brindle/permissions.py +0 -1870
- {brindle-0.4.6 → brindle-0.5.0}/.gitignore +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/LICENSE +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/SCHEDULE-A +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/__init__.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/__main__.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/account.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/airgap.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/assembler.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/assets/braid_dark.png +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/assets/braid_light.png +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/autopilot.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/budget.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/builtin_agents/__init__.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/builtin_agents/backend-auditor.md +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/builtin_agents/coordinator.md +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/builtin_agents/developer-codex.md +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/builtin_agents/developer-fable.md +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/builtin_agents/developer-gemini.md +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/builtin_agents/developer-heavy.md +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/builtin_agents/developer-light.md +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/builtin_agents/developer-local.md +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/builtin_agents/developer-opencode.md +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/builtin_agents/developer-sonnet.md +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/builtin_agents/developer.md +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/builtin_agents/qa.md +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/builtin_agents/reviewer-codex.md +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/builtin_agents/reviewer-gemini.md +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/builtin_agents/reviewer-local.md +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/builtin_agents/reviewer-opencode.md +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/builtin_agents/reviewer.md +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/builtin_agents/subagent.md +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/builtin_agents/supervisor.md +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/builtin_rules/__init__.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/builtin_rules/security/backend.md +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/builtin_rules/style/minimal-diff.md +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/builtin_rules/tests/only.md +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/bus.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/ci_adapters.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/ci_client.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/ci_federation.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/ci_hosts.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/clone.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/cloud_credential.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/cloud_login.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/codemap.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/codemap_docs.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/codex_hook.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/company_identity.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/company_login.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/config.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/conflicts.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/coordinator.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/cost.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/cost_estimate.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/cull.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/daemon/__init__.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/daemon/auth.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/daemon/events.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/daemon/lifecycle.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/daemon/peer.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/daemon/routes_org_permissions.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/daemon/schema.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/daemon/session_review.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/daemon/terminal.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/debuglog.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/demo.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/detect.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/doctor.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/escapes.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/events.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/gates.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/git.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/guardrails.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/history.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/identity_lock.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/inbox.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/kb.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/key_check.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/keys_cmds.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/keystore.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/knowledge.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/launch_health.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/learned_rules.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/learning.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/legacy.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/local_setup.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/login_pause.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/mcp_server.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/model_access.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/model_availability.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/native/__init__.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/native/catalog.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/native/client.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/native/loop.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/native/lsp.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/native/serve.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/native/tools.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/opencode.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/org_permissions.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/pane_auth.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/picker.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/pipeline.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/plugins.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/policy.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/pool.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/preflight.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/pricing.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/pro/__init__.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/pro/_files.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/pro/account.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/pro/audit_chain.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/pro/audit_export.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/pro/auth.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/pro/brief_learning.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/pro/cost_centers.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/pro/credentials.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/pro/features.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/pro/keys.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/pro/learning.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/pro/license.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/pro/loopback.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/pro/managed_models.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/pro/org_profiles.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/pro/orgkey.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/pro/rollout.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/pro/route_health.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/pro/settings_sync.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/pro/status.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/pro/team_events.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/pro/team_policy.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/procs.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/profiles.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/prompt_answer.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/provider_homes.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/providers_install.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/quota.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/repo_cmds.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/repos.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/rewind.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/rule_checks.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/savings.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/scratch.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/secrets.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/self_serve.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/service/__init__.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/service/errors.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/service/routing.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/service/sessions.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/services.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/sessions.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/sidebar_follow.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/sidebar_logo.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/signin_pause.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/status_cache.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/tasks.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/tmux.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/updates.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/upgrade.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/usage.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/view.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/wake.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/watch.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/watch_costs.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/web/__init__.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/web/chat.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/web/dashboard.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/web/diff.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/web/server.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/web/static/app.js +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/web/static/index.html +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/worker_models.py +0 -0
- {brindle-0.4.6 → brindle-0.5.0}/src/brindle/workspaces.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: brindle
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.0
|
|
4
4
|
Summary: Run coding agents in parallel, each on its own git branch, with a supervisor that delegates, reviews, and merges
|
|
5
5
|
Project-URL: Homepage, https://pawdelta.com/brindle/
|
|
6
6
|
Project-URL: Documentation, https://pawdelta.com/brindle/docs/recommended-use
|
|
@@ -404,7 +404,7 @@ your own status line prints, so what you see doesn't change.
|
|
|
404
404
|
| `brindle cost [--days N] [--all]` | dollar spend at list prices over the last 30 days, by model |
|
|
405
405
|
| `brindle cost report [--days N] [--all]` | Pro: spend by day, profile and goal, cost per merged branch, review pass rate per worker profile |
|
|
406
406
|
| `brindle history --share [--session ID]` | a few lines about this session to paste into Slack or a post: goal, milestones verified, workers, merges, reviews (and how many by a different model), parallel speedup, tokens |
|
|
407
|
-
| `brindle permissions list / check / suggestions / accept / allow / deny / forget / reset` | the rules brindle answers workers' permission requests with, and what it suggests from your approvals (see "Permission policy") |
|
|
407
|
+
| `brindle permissions list / check / preset / suggestions / accept / allow / deny / forget / reset` | the rules brindle answers workers' permission requests with, the preset they started from, and what it suggests from your approvals (see "Permission policy"; saved actions are managed in the app for now, [#285](https://github.com/PawDelta/brindle/issues/285)) |
|
|
408
408
|
| `brindle permissions install-codex-hook [--yes]` / `brindle permissions sync-agy` | trust brindle's Codex permission hook now (brindle does it itself when needed); copy your rules into Antigravity's settings (see "Permission policy") |
|
|
409
409
|
| `brindle cost request --usd N --reason "..." [--goal TEXT]` | Enterprise (cost centers): ask an admin to approve spend over your budget. A budget refusal points here. Once approved, this month's limit (or the named goal's) goes up by the approved amount, for the month it was approved in |
|
|
410
410
|
| `brindle cost requests` | Enterprise: your approval requests and their status; checks pending ones with the server (the cull pass also does, every few minutes). With cost centers, spend events also carry the repo (`owner/name`) so the org can total spend per center |
|
|
@@ -691,7 +691,7 @@ Autopilot, merge gates and cleanup:
|
|
|
691
691
|
| `goal_audit` | `true` | once every milestone passes, an adversarial reviewer checks the work against the original goal before the goal counts as reached |
|
|
692
692
|
| `merge_into` | none | branch that worker branches are cut from and merge into, whatever branch the supervisor is on |
|
|
693
693
|
| `auto_merge_default_branch` | `false` | let the pipeline merge into the repo's default branch (origin HEAD, else `main`/`master`) on its own; by default it sends a "needs you" message instead, and you run `merge_workspace` yourself (manual merges are never gated) |
|
|
694
|
-
| `permission_policy` | `"off"` | `"on"`: brindle answers
|
|
694
|
+
| `permission_policy` | `"on"` with a Pro license, else `"off"` | `"on"`: brindle answers workers' permission requests from its rules (see "Permission policy" below); `"off"`: the provider's own prompts and permission mode decide, except Antigravity workers under `agy_approvals: "brindle"`, whose hook still enforces the rules. The only permission switch: a leftover `permission_essentials` key is ignored |
|
|
695
695
|
| `agy_approvals` | unset | `"brindle"`: Antigravity agents run without approval prompts and brindle's hook allows or denies every call, applying the profile's `allowed_tools` (see "Antigravity" under "Permission policy"); `"prompt"`: agy asks as usual. Unset, workers get `"brindle"` and interactive agy sessions `"prompt"` |
|
|
696
696
|
| `rules` | `[]` | standing rules for the supervisor, e.g. `["Fix review findings without asking", "Validate options before offering them"]`; added to every supervisor's brief. Rules in `~/.brindle/config.json`, the repo's config and `config.local.json` are all kept, so a team's rules and your own add up |
|
|
697
697
|
| `plan_first` | `false` | workers propose a plan (`submit_plan`) and wait for `approve_plan` before editing |
|
|
@@ -879,26 +879,43 @@ command, path or URL; brindle never reads the screen) and brindle answers
|
|
|
879
879
|
**allow**, **deny**, or **ask**, which leaves the prompt to you as usual. Any
|
|
880
880
|
error is ask.
|
|
881
881
|
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
- **
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
`
|
|
897
|
-
|
|
898
|
-
|
|
882
|
+
Nothing is built in. Every rule lives in `~/.brindle/permissions.json`, and
|
|
883
|
+
you can edit or remove any of them, including the ones a **preset** seeded.
|
|
884
|
+
Pick a preset in Settings → Permissions or at setup:
|
|
885
|
+
|
|
886
|
+
- **Autonomous** (the default): everything runs, except pushes into the
|
|
887
|
+
repo's default branch (ask) and destructive actions (deny: git force flags,
|
|
888
|
+
deleting a branch by push, a recursive `rm` of `/`, a top-level folder or
|
|
889
|
+
home);
|
|
890
|
+
- **Permissive**: edits in the worktree and everyday commands run, the rest asks;
|
|
891
|
+
- **Standard**: routine reads and everyday commands run, changes ask;
|
|
892
|
+
- **Secure**: short approvals, and a deny for anything no rule covers.
|
|
893
|
+
|
|
894
|
+
Every preset also denies reading `~/.ssh`, `~/.aws`, `~/.gnupg`, `.env*` and
|
|
895
|
+
the daemon's token, and asks before every push into a `release` or
|
|
896
|
+
`release/*` branch, which starts a signed build (an approval there is never
|
|
897
|
+
saved). It allows reading files git tracks, the repo's `checks`, read-only
|
|
898
|
+
git commands and read-only pipelines (grep, rg, ls, cat, head, `sed -n` ...
|
|
899
|
+
joined by pipes or `&&`, quoting read as the shell reads it). A pipeline
|
|
900
|
+
stops being read-only when it writes a file, substitutes a command, sets a
|
|
901
|
+
variable, recurses into a tree with a file a read deny covers, or reads such a
|
|
902
|
+
file. Precedence: a deny wins, then an ask, then an allow, then the preset's
|
|
903
|
+
setting for what no rule covers (ask, allow or deny). A deny or ask also
|
|
904
|
+
catches a part of a compound command however it's spelled (spacing, quotes,
|
|
905
|
+
assignments, redirects, `$(...)`, patterns the shell expands); when brindle
|
|
906
|
+
can't read the syntax and a deny or ask could match it, it asks.
|
|
907
|
+
|
|
908
|
+
Add your own with `brindle permissions allow|deny KIND MATCH` (kinds: `read`,
|
|
909
|
+
`write`, `edit`, `bash`, `fetch`, `mcp`, `other`; the match is exact unless
|
|
910
|
+
`--prefix` or `--glob`) or in the app, which can also make ask rules with
|
|
911
|
+
limits on saved approvals, timed rules and exceptions. A repo's
|
|
899
912
|
`.brindle/permissions.json` (`{"rules": [...]}`, same format) can only add
|
|
900
913
|
denies. `brindle permissions list` shows every rule and where it came from,
|
|
901
|
-
`forget ID` removes one
|
|
914
|
+
`forget ID` removes one, `reset` goes back to the preset's rules. A store
|
|
915
|
+
written by brindle 0.4.7 is migrated on first load: its permission editor's
|
|
916
|
+
preset becomes Permissive, Standard or Secure (Autonomous when it chose
|
|
917
|
+
none), its own rules stay, and its remembered approvals become saved actions;
|
|
918
|
+
its old rows stay in the file.
|
|
902
919
|
Profiles can add narrower, profile-local denies with a JSON array in frontmatter,
|
|
903
920
|
for example `permission_denies: ["read glob ~/.private*", "bash prefix deploy"]`.
|
|
904
921
|
Built-in profiles ship with no profile-specific denies by default. These denies
|
|
@@ -919,63 +936,37 @@ on without the tool running counts for nothing. Every decision is in
|
|
|
919
936
|
`brindle history --kind permission`, and when a worker sits on a prompt, its
|
|
920
937
|
supervisor is told exactly which request is pending (only you can answer it).
|
|
921
938
|
|
|
922
|
-
**
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
**Remembered approvals** are saved in your user permission preferences, across
|
|
943
|
-
sessions and daemon restarts, until you revoke them in Settings → Permission
|
|
944
|
-
grants. A remembered push covers the same repository, remote URL and destination
|
|
945
|
-
branch across future commits; a file approval covers that specific file.
|
|
946
|
-
Every use still checks the current policy, explicit denies and adapter protections.
|
|
947
|
-
Temporary time/use limits apply to temporary grants; persistent approvals require
|
|
948
|
-
their own policy permission. Turning that permission off prevents their use.
|
|
949
|
-
- `git push` qualifies only as `git push <remote> <full commit sha>:refs/heads/<branch>`, run in the agent's own worktree (not another clone or a nested repository), and only when:
|
|
950
|
-
- the remote resolves (insteadOf applied) to exactly one https, ssh or `user@host:path` URL;
|
|
951
|
-
- none of `core.sshCommand`, `core.hooksPath`, the remote's receivepack/vcs/mirror, `push.followTags` or `push.recurseSubmodules` is set;
|
|
952
|
-
- there is no pre-push or reference-transaction hook;
|
|
953
|
-
- neither the repo nor your org sets protected paths (a push skips the merge check that enforces them).
|
|
954
|
-
- `.env*` qualifies for one file inside the worktree.
|
|
955
|
-
|
|
956
|
-
After your answer, brindle checks the policy, every rule and that scope again
|
|
957
|
-
before allowing. Anything that changed meanwhile refuses it. The command then
|
|
958
|
-
runs outside brindle.
|
|
959
|
-
|
|
960
|
-
Never lifted: your own, the repo's, a profile's or your org's denies, git force
|
|
961
|
-
flags, and reads of `~/.ssh`, `~/.aws`, `~/.gnupg` or the daemon's token.
|
|
962
|
-
Antigravity and OpenCode workers get no grants: agy ignores a hook's allow, and
|
|
963
|
-
OpenCode's plugin has no hold.
|
|
964
|
-
|
|
965
|
-
In a Team org, only the org policy's `permission_grants` block decides what may
|
|
966
|
-
be granted. It is read again on every request:
|
|
939
|
+
**Saved actions.** The app's Inbox groups pending asks by kind and general
|
|
940
|
+
form (a push by its destination, a file by its top folder, a command by its
|
|
941
|
+
first two words, an MCP tool or its server). One decision answers the group:
|
|
942
|
+
once, for the session, for a time, until revoked, deny, or always deny. Anything
|
|
943
|
+
kept is a saved action, listed and editable under Settings → Permissions. A
|
|
944
|
+
saved deny stops every ask it covers. A saved allow settles an ask only within
|
|
945
|
+
the limits of the ask rule that asked (its scope and how long approvals may
|
|
946
|
+
last), never past a deny rule, and never once it has expired. Every use reads
|
|
947
|
+
the current rules again.
|
|
948
|
+
|
|
949
|
+
Saved actions and the grouped Inbox are in the app only for now. From the
|
|
950
|
+
CLI, saved actions still apply to every worker, but you can't list, edit or
|
|
951
|
+
delete one (`brindle permissions reset` removes them all, with your own and
|
|
952
|
+
learned rules), and without the app a held request falls back to the worker
|
|
953
|
+
CLI's own prompt in its pane, one exact request at a time. CLI commands for
|
|
954
|
+
both are tracked in
|
|
955
|
+
[#285](https://github.com/PawDelta/brindle/issues/285).
|
|
956
|
+
|
|
957
|
+
In a Team org, the org policy's `permission_grants` block bounds what a saved
|
|
958
|
+
allow may do. It is read again on every request:
|
|
967
959
|
|
|
968
960
|
```json
|
|
969
|
-
"permission_grants": {"allow": true, "kinds": ["bash", "fetch"], "
|
|
970
|
-
"
|
|
971
|
-
"deny": ["bash prefix terraform apply"]}
|
|
961
|
+
"permission_grants": {"allow": true, "kinds": ["bash", "fetch"], "max_minutes": 30,
|
|
962
|
+
"allow_persistent": true, "lifetimes": ["session", "time", "forever"],
|
|
963
|
+
"scopes": ["branch", "remote"], "deny": ["bash prefix terraform apply"]}
|
|
972
964
|
```
|
|
973
965
|
|
|
974
966
|
- `deny` entries are enforced for every provider and can't be lifted.
|
|
975
|
-
-
|
|
976
|
-
- A policy without the block,
|
|
977
|
-
-
|
|
978
|
-
- The org backend that serves this block isn't part of this repository. Until it serves one, Team orgs get no grants. It is enforced from the cached policy, or in air-gap mode from `.brindle/policy.json`.
|
|
967
|
+
- A saved allow applies only for the listed `kinds`, `lifetimes` and `scopes`, with timed ones capped at `max_minutes`; one that lasts until revoked also needs `allow_persistent`.
|
|
968
|
+
- A policy without the block, one that can't be read, or a paused or shut-down member: no saved allow applies.
|
|
969
|
+
- Org admins edit the block in Settings → Organization approvals. It is enforced from the cached policy, or in air-gap mode from `.brindle/policy.json`.
|
|
979
970
|
|
|
980
971
|
**Codex.** Codex runs a hook only once it's trusted, so with
|
|
981
972
|
`permission_policy` on, brindle trusts its own hook the first time a Codex worker
|
|
@@ -372,7 +372,7 @@ your own status line prints, so what you see doesn't change.
|
|
|
372
372
|
| `brindle cost [--days N] [--all]` | dollar spend at list prices over the last 30 days, by model |
|
|
373
373
|
| `brindle cost report [--days N] [--all]` | Pro: spend by day, profile and goal, cost per merged branch, review pass rate per worker profile |
|
|
374
374
|
| `brindle history --share [--session ID]` | a few lines about this session to paste into Slack or a post: goal, milestones verified, workers, merges, reviews (and how many by a different model), parallel speedup, tokens |
|
|
375
|
-
| `brindle permissions list / check / suggestions / accept / allow / deny / forget / reset` | the rules brindle answers workers' permission requests with, and what it suggests from your approvals (see "Permission policy") |
|
|
375
|
+
| `brindle permissions list / check / preset / suggestions / accept / allow / deny / forget / reset` | the rules brindle answers workers' permission requests with, the preset they started from, and what it suggests from your approvals (see "Permission policy"; saved actions are managed in the app for now, [#285](https://github.com/PawDelta/brindle/issues/285)) |
|
|
376
376
|
| `brindle permissions install-codex-hook [--yes]` / `brindle permissions sync-agy` | trust brindle's Codex permission hook now (brindle does it itself when needed); copy your rules into Antigravity's settings (see "Permission policy") |
|
|
377
377
|
| `brindle cost request --usd N --reason "..." [--goal TEXT]` | Enterprise (cost centers): ask an admin to approve spend over your budget. A budget refusal points here. Once approved, this month's limit (or the named goal's) goes up by the approved amount, for the month it was approved in |
|
|
378
378
|
| `brindle cost requests` | Enterprise: your approval requests and their status; checks pending ones with the server (the cull pass also does, every few minutes). With cost centers, spend events also carry the repo (`owner/name`) so the org can total spend per center |
|
|
@@ -659,7 +659,7 @@ Autopilot, merge gates and cleanup:
|
|
|
659
659
|
| `goal_audit` | `true` | once every milestone passes, an adversarial reviewer checks the work against the original goal before the goal counts as reached |
|
|
660
660
|
| `merge_into` | none | branch that worker branches are cut from and merge into, whatever branch the supervisor is on |
|
|
661
661
|
| `auto_merge_default_branch` | `false` | let the pipeline merge into the repo's default branch (origin HEAD, else `main`/`master`) on its own; by default it sends a "needs you" message instead, and you run `merge_workspace` yourself (manual merges are never gated) |
|
|
662
|
-
| `permission_policy` | `"off"` | `"on"`: brindle answers
|
|
662
|
+
| `permission_policy` | `"on"` with a Pro license, else `"off"` | `"on"`: brindle answers workers' permission requests from its rules (see "Permission policy" below); `"off"`: the provider's own prompts and permission mode decide, except Antigravity workers under `agy_approvals: "brindle"`, whose hook still enforces the rules. The only permission switch: a leftover `permission_essentials` key is ignored |
|
|
663
663
|
| `agy_approvals` | unset | `"brindle"`: Antigravity agents run without approval prompts and brindle's hook allows or denies every call, applying the profile's `allowed_tools` (see "Antigravity" under "Permission policy"); `"prompt"`: agy asks as usual. Unset, workers get `"brindle"` and interactive agy sessions `"prompt"` |
|
|
664
664
|
| `rules` | `[]` | standing rules for the supervisor, e.g. `["Fix review findings without asking", "Validate options before offering them"]`; added to every supervisor's brief. Rules in `~/.brindle/config.json`, the repo's config and `config.local.json` are all kept, so a team's rules and your own add up |
|
|
665
665
|
| `plan_first` | `false` | workers propose a plan (`submit_plan`) and wait for `approve_plan` before editing |
|
|
@@ -847,26 +847,43 @@ command, path or URL; brindle never reads the screen) and brindle answers
|
|
|
847
847
|
**allow**, **deny**, or **ask**, which leaves the prompt to you as usual. Any
|
|
848
848
|
error is ask.
|
|
849
849
|
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
- **
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
`
|
|
865
|
-
|
|
866
|
-
|
|
850
|
+
Nothing is built in. Every rule lives in `~/.brindle/permissions.json`, and
|
|
851
|
+
you can edit or remove any of them, including the ones a **preset** seeded.
|
|
852
|
+
Pick a preset in Settings → Permissions or at setup:
|
|
853
|
+
|
|
854
|
+
- **Autonomous** (the default): everything runs, except pushes into the
|
|
855
|
+
repo's default branch (ask) and destructive actions (deny: git force flags,
|
|
856
|
+
deleting a branch by push, a recursive `rm` of `/`, a top-level folder or
|
|
857
|
+
home);
|
|
858
|
+
- **Permissive**: edits in the worktree and everyday commands run, the rest asks;
|
|
859
|
+
- **Standard**: routine reads and everyday commands run, changes ask;
|
|
860
|
+
- **Secure**: short approvals, and a deny for anything no rule covers.
|
|
861
|
+
|
|
862
|
+
Every preset also denies reading `~/.ssh`, `~/.aws`, `~/.gnupg`, `.env*` and
|
|
863
|
+
the daemon's token, and asks before every push into a `release` or
|
|
864
|
+
`release/*` branch, which starts a signed build (an approval there is never
|
|
865
|
+
saved). It allows reading files git tracks, the repo's `checks`, read-only
|
|
866
|
+
git commands and read-only pipelines (grep, rg, ls, cat, head, `sed -n` ...
|
|
867
|
+
joined by pipes or `&&`, quoting read as the shell reads it). A pipeline
|
|
868
|
+
stops being read-only when it writes a file, substitutes a command, sets a
|
|
869
|
+
variable, recurses into a tree with a file a read deny covers, or reads such a
|
|
870
|
+
file. Precedence: a deny wins, then an ask, then an allow, then the preset's
|
|
871
|
+
setting for what no rule covers (ask, allow or deny). A deny or ask also
|
|
872
|
+
catches a part of a compound command however it's spelled (spacing, quotes,
|
|
873
|
+
assignments, redirects, `$(...)`, patterns the shell expands); when brindle
|
|
874
|
+
can't read the syntax and a deny or ask could match it, it asks.
|
|
875
|
+
|
|
876
|
+
Add your own with `brindle permissions allow|deny KIND MATCH` (kinds: `read`,
|
|
877
|
+
`write`, `edit`, `bash`, `fetch`, `mcp`, `other`; the match is exact unless
|
|
878
|
+
`--prefix` or `--glob`) or in the app, which can also make ask rules with
|
|
879
|
+
limits on saved approvals, timed rules and exceptions. A repo's
|
|
867
880
|
`.brindle/permissions.json` (`{"rules": [...]}`, same format) can only add
|
|
868
881
|
denies. `brindle permissions list` shows every rule and where it came from,
|
|
869
|
-
`forget ID` removes one
|
|
882
|
+
`forget ID` removes one, `reset` goes back to the preset's rules. A store
|
|
883
|
+
written by brindle 0.4.7 is migrated on first load: its permission editor's
|
|
884
|
+
preset becomes Permissive, Standard or Secure (Autonomous when it chose
|
|
885
|
+
none), its own rules stay, and its remembered approvals become saved actions;
|
|
886
|
+
its old rows stay in the file.
|
|
870
887
|
Profiles can add narrower, profile-local denies with a JSON array in frontmatter,
|
|
871
888
|
for example `permission_denies: ["read glob ~/.private*", "bash prefix deploy"]`.
|
|
872
889
|
Built-in profiles ship with no profile-specific denies by default. These denies
|
|
@@ -887,63 +904,37 @@ on without the tool running counts for nothing. Every decision is in
|
|
|
887
904
|
`brindle history --kind permission`, and when a worker sits on a prompt, its
|
|
888
905
|
supervisor is told exactly which request is pending (only you can answer it).
|
|
889
906
|
|
|
890
|
-
**
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
**Remembered approvals** are saved in your user permission preferences, across
|
|
911
|
-
sessions and daemon restarts, until you revoke them in Settings → Permission
|
|
912
|
-
grants. A remembered push covers the same repository, remote URL and destination
|
|
913
|
-
branch across future commits; a file approval covers that specific file.
|
|
914
|
-
Every use still checks the current policy, explicit denies and adapter protections.
|
|
915
|
-
Temporary time/use limits apply to temporary grants; persistent approvals require
|
|
916
|
-
their own policy permission. Turning that permission off prevents their use.
|
|
917
|
-
- `git push` qualifies only as `git push <remote> <full commit sha>:refs/heads/<branch>`, run in the agent's own worktree (not another clone or a nested repository), and only when:
|
|
918
|
-
- the remote resolves (insteadOf applied) to exactly one https, ssh or `user@host:path` URL;
|
|
919
|
-
- none of `core.sshCommand`, `core.hooksPath`, the remote's receivepack/vcs/mirror, `push.followTags` or `push.recurseSubmodules` is set;
|
|
920
|
-
- there is no pre-push or reference-transaction hook;
|
|
921
|
-
- neither the repo nor your org sets protected paths (a push skips the merge check that enforces them).
|
|
922
|
-
- `.env*` qualifies for one file inside the worktree.
|
|
923
|
-
|
|
924
|
-
After your answer, brindle checks the policy, every rule and that scope again
|
|
925
|
-
before allowing. Anything that changed meanwhile refuses it. The command then
|
|
926
|
-
runs outside brindle.
|
|
927
|
-
|
|
928
|
-
Never lifted: your own, the repo's, a profile's or your org's denies, git force
|
|
929
|
-
flags, and reads of `~/.ssh`, `~/.aws`, `~/.gnupg` or the daemon's token.
|
|
930
|
-
Antigravity and OpenCode workers get no grants: agy ignores a hook's allow, and
|
|
931
|
-
OpenCode's plugin has no hold.
|
|
932
|
-
|
|
933
|
-
In a Team org, only the org policy's `permission_grants` block decides what may
|
|
934
|
-
be granted. It is read again on every request:
|
|
907
|
+
**Saved actions.** The app's Inbox groups pending asks by kind and general
|
|
908
|
+
form (a push by its destination, a file by its top folder, a command by its
|
|
909
|
+
first two words, an MCP tool or its server). One decision answers the group:
|
|
910
|
+
once, for the session, for a time, until revoked, deny, or always deny. Anything
|
|
911
|
+
kept is a saved action, listed and editable under Settings → Permissions. A
|
|
912
|
+
saved deny stops every ask it covers. A saved allow settles an ask only within
|
|
913
|
+
the limits of the ask rule that asked (its scope and how long approvals may
|
|
914
|
+
last), never past a deny rule, and never once it has expired. Every use reads
|
|
915
|
+
the current rules again.
|
|
916
|
+
|
|
917
|
+
Saved actions and the grouped Inbox are in the app only for now. From the
|
|
918
|
+
CLI, saved actions still apply to every worker, but you can't list, edit or
|
|
919
|
+
delete one (`brindle permissions reset` removes them all, with your own and
|
|
920
|
+
learned rules), and without the app a held request falls back to the worker
|
|
921
|
+
CLI's own prompt in its pane, one exact request at a time. CLI commands for
|
|
922
|
+
both are tracked in
|
|
923
|
+
[#285](https://github.com/PawDelta/brindle/issues/285).
|
|
924
|
+
|
|
925
|
+
In a Team org, the org policy's `permission_grants` block bounds what a saved
|
|
926
|
+
allow may do. It is read again on every request:
|
|
935
927
|
|
|
936
928
|
```json
|
|
937
|
-
"permission_grants": {"allow": true, "kinds": ["bash", "fetch"], "
|
|
938
|
-
"
|
|
939
|
-
"deny": ["bash prefix terraform apply"]}
|
|
929
|
+
"permission_grants": {"allow": true, "kinds": ["bash", "fetch"], "max_minutes": 30,
|
|
930
|
+
"allow_persistent": true, "lifetimes": ["session", "time", "forever"],
|
|
931
|
+
"scopes": ["branch", "remote"], "deny": ["bash prefix terraform apply"]}
|
|
940
932
|
```
|
|
941
933
|
|
|
942
934
|
- `deny` entries are enforced for every provider and can't be lifted.
|
|
943
|
-
-
|
|
944
|
-
- A policy without the block,
|
|
945
|
-
-
|
|
946
|
-
- The org backend that serves this block isn't part of this repository. Until it serves one, Team orgs get no grants. It is enforced from the cached policy, or in air-gap mode from `.brindle/policy.json`.
|
|
935
|
+
- A saved allow applies only for the listed `kinds`, `lifetimes` and `scopes`, with timed ones capped at `max_minutes`; one that lasts until revoked also needs `allow_persistent`.
|
|
936
|
+
- A policy without the block, one that can't be read, or a paused or shut-down member: no saved allow applies.
|
|
937
|
+
- Org admins edit the block in Settings → Organization approvals. It is enforced from the cached policy, or in air-gap mode from `.brindle/policy.json`.
|
|
947
938
|
|
|
948
939
|
**Codex.** Codex runs a hook only once it's trusted, so with
|
|
949
940
|
`permission_policy` on, brindle trusts its own hook the first time a Codex worker
|