{% extends "curb_base.html" %} {# Projects › Apps: places where each project's own code calls an LLM, and the export. #} {% block scope %}{{ k.picker(project) }}{% endblock %} {% block part %}
{% call k.head("Places where your own code calls an AI model.", "Found by pattern in each project's Python files. Each one is a place to look, not a proven problem." ~ ("" if one or not projects else " Pick one project to export.")) %} {{ k.again() }} {% if one and view.rows %} {{ ico.icon('download', 14) }} Export for code scanning {% endif %} {% endcall %} {% for line in view.problems %}
Curb could not read a file. {{ line }}
{% endfor %} {% if not projects %} {% call empty.state("project", "No projects yet") %}

Curb checks the projects on your Projects page. Add one there first.

New project {% endcall %} {% elif view.rows %}
Model calls {{ k.tally() }} {% call k.tools("Search model calls", {"project": project}) %} {% endcall %}
Where{% if not one %}Project{% endif %}LibraryKindWorth a look
{% for row in table.rows %}
{{ row.where }} {% if not one %}{{ row.project }}{% endif %} {{ row.library }} {{ row.shape }} {% if row.flag %}{{ row.flag }}{% endif %}
{% endfor %} {{ k.foot("No model call matches that search.") }}
{% else %} {% call empty.state("clear", "No model calls found") %}

No Python file in {{ one.name if one else "your projects" }} calls an AI library Curb knows.

{% endcall %} {% endif %} {% call k.explain("What this is for", "A map of where to look, for a deeper tool to check.") %}

Curb finds these by matching the names of AI libraries. It cannot follow your code, so it cannot prove a problem. The export hands the list to Semgrep or CodeQL, which can.

One call
The code asks the model once, and uses the answer.
Uses tools
The model can call functions the code gives it.
Loop
The model runs in a loop, deciding its own next step.
{{ k.cmd("flanner curb app") }} {% endcall %}
{% endblock %}