{% extends "curb_base.html" %} {# Projects › Reach: risk per project and agent; for one project, each way and credential. #} {% block scope %}{{ k.picker(project) }}{% endblock %} {% block part %}
{% call k.head("What each agent can read, and where it can send, when you start it in a project.", "Read from the project's own agent settings, on top of this machine's.", held if one else machine_held) %} {{ k.again() }} {% endcall %} {% if not projects %} {% call empty.state("project", "No projects yet") %}

Curb checks the projects on your Projects page. Add one there, or run this inside a repository:

{{ k.cmd("flanner init") }} New project {% endcall %} {% elif one %} {% if held.value is none %} {% if held.error %}{{ k.failed(held.error) }}{% else %}{{ k.checking("Checking what your agents can reach in " ~ one.name ~ "…") }}{% endif %} {% else %}
{% for card in cards %}
{{ card.label }} in {{ one.name }} {{ k.risk(card.level, card.tone, true) }} {% if card.guess %}Best guess{% endif %}
{{ k.picture(card) }}

{{ card.lede }}

{{ k.ways(card) }}
{% endfor %}
{% if not cards %} {% call empty.state("search", "No agent found") %}

Curb checks Claude Code and Codex. Neither is set up on this machine yet.

{% endcall %} {% endif %} {% if table.of %}
Credentials in reach {{ k.tally() }} {% call k.tools("Search credentials", {"project": project}) %}{% endcall %}
{% if not shown %}

Names and locations are a target list for an agent, so they stay hidden. {{ k.ask_names() }}

{% endif %}
KindNameWhereWho can read it
{% for row in table.rows %}
{{ row.kind }}{{ row.category }} {{ k.slot(row.name) }} {{ k.slot(row.where) }} {% if row.readers %}{{ k.st("open", row.readers | join(", ")) }}{% else %}{{ k.st("closed", "Blocked") }}{% endif %}
{% endfor %} {{ k.foot("No credential matches that search.") }}
{% endif %} {% endif %} {% else %}
By project {{ k.tally() }} {% call k.tools("Search projects") %}{% endcall %}
ProjectRiskWhat differs here
{% for row in table.rows %}
{{ row.name }} {% if row.checking %} Checking… {% elif row.error %}Could not check {% else %}{% for label, level, tone in row.levels %}{{ label }} {{ k.risk(level, tone) }}{% endfor %}{% endif %} {{ row.error or row.differs }} Open
{% endfor %} {% if base and not table.q %}
No projectStarted outside any project {% for label, level, tone in base %}{{ label }} {{ k.risk(level, tone) }}{% endfor %} The starting point for every project. Open
{% endif %} {{ k.foot("No project matches that search.") }}
{% endif %}
{{ k.terminal("Check a different way of starting an agent", "With extra flags, for example, or as a scheduled job starts it. A launch command can hold anything, so Curb reads it only where you type it.", "flanner curb map -- claude --dangerously-skip-permissions") }}
{% call k.explain("How risk is rated", "Two questions: can it read credentials, and can it send data out?") %}
High
It can read a credential and send data out.
Medium
It can read a credential, but every way out is closed. Or it can only read minor ones.
Low
It cannot read any credential.
Open
Nothing stops the agent.
Closed
A setting stops it. Curb read the setting, and has not tested it.
Closed, proved
A test showed the agent being stopped.
Sandbox
A fence around the commands an agent runs. It limits the files and sites they can reach.

Curb takes three things for granted: no extra flags or settings files, no settings from device management it cannot see, and no MCP servers that plugins add.

{{ k.cmd("flanner curb map") }} {% endcall %}
{% endblock %}