Aegro CLI
Command-line interface for the Aegro agricultural management API.
Install
# pipx (recommended)
pipx install aegro
# uv
uv tool install aegro
# Homebrew (macOS)
brew tap aegro/tap
brew install aegro
# Windows — pipx (recommended)
pipx install aegro
# Windows — uv
uv tool install aegro
# Windows — pip
pip install aegro
Credentials are stored in
%USERPROFILE%\.aegro\(outside AppData on purpose: packaged apps like Claude Desktop and Store Python run under MSIX filesystem virtualization, which would silently redirect AppData writes to a per-app shadow folder). Files from the previous location (%LOCALAPPDATA%\aegro\) are migrated automatically on first run.
WSL: Inside WSL, follow the Linux instructions. WSL and Windows credentials are stored separately — do not mix installations.
OneDrive/Dropbox: Avoid pointing
AEGRO_CONFIG_DIRto cloud-synced folders, as file locking may cause intermittent errors.
For development:
git clone https://github.com/aegro/tool-aegro-cli.git
cd tool-aegro-cli
uv sync
uv run aegro --help
Quick Start
# 1. Authenticate — opens the browser for Aegro login (email/password, OTP or Google)
aegro auth login
# Alternative: static API key (CI, agents, fallback)
aegro auth login --farm-name "Fazenda Sul" --api-key "aegro_abc123..."
# 2. Select a farm
aegro farms list
aegro farms select "Fazenda Sul" # persists to state.json (global per machine)
# Per-command farm — preferred with parallel sessions (one per farm), because
# one session's `farms select` retargets the others
aegro crops list --farm "Fazenda Sul"
aegro crops list --farm farm::abc123 # key: opaque, stable, no quoting needed
# 3. Start working
aegro crops list --start-date 2025-01-01 --end-date 2025-12-31
aegro financial installments --status NOT_PAID
aegro stock items --output table
Commands
| Group | Commands | Domain |
|---|---|---|
auth |
login, status, logout | Authentication |
farms |
list, select, info | Farm management |
files |
upload, attach, list-attachments (anexos: upload S3 + vinculo a realization, fuel-supply, maintenance, bill, purchase-order, purchase-requisition, harvest-log, asset, element, bank-transfer, livestock-lot; upload exige OAuth) | Attachments |
crops |
get, list, prorate, harvest-discounts, prorates, glebes | Harvest management |
activities |
get, list, plan, realizations, get-plan, get-realization, create-plan, create-realization (--file anexa), update-plan, update-realization (--file anexa), delete-activity, delete-realization |
Activity planning |
financial |
bill, installment, installments, create-bill, update-bill, closes, realize, settle, category-usage, migrate-category (plan/apply/verify) | Accounts payable/receivable, incluindo troca de categoria em massa |
stock |
item, location, items, locations, logs, log, transfer, entry, removal | Inventory |
elements |
get, list, create-defensive/fertilizer/item/seed/service, set-categories | Inputs/supplies |
assets |
get, list, create-machine/vehicle/garner/immobilized/pivot/weather-station | Equipment |
fuel-supplies |
get, list, create (--file anexa), update (--file acrescenta) |
Fuel management |
maintenances |
get, list, create (--file anexa), update (--file acrescenta) |
Maintenance records |
harvest-logs |
get, create | Harvest records |
bank-accounts |
get, list, create | Bank accounts |
bank-reconciliation |
import-ofx, entries, candidates, confirm, ignore, undo, history, accounts, clear-pending | Bank reconciliation (OFX × financeiro; requires OAuth) |
companies |
get, list, create | Suppliers/vendors |
fin-categories |
get, list, create, subcategories | Chart of accounts |
catalogs |
list, element-keys, elements | Catalog lookups |
tags |
get, list, create | Tags/labels |
weather |
get, create | Weather data |
purchase-orders |
get, list, create | Purchase orders |
glebes |
get, list | Farm fields |
crop-glebes |
get, list | Crop fields |
Output Formats
All commands support three output formats:
aegro crops list --output json # JSON (default, for LLMs/scripts)
aegro crops list --output table # Rich table for humans
aegro crops list --output csv # CSV export
Safe Mode for Mutations
Agents and automation should enable safe mode before running workflows that may create, update, delete, realize, transfer, enter, or remove data:
export AEGRO_SAFE_MODE=1
aegro purchase-orders create ... --dry-run # Preview request; no API mutation
# Execute after validating the payload. The farm must be explicit in safe mode
# (see below) — `--execute` on its own is refused.
aegro purchase-orders create ... --execute --farm "Fazenda Sul"
--dry-run prints the target farm (plus farmSource, where that farm came
from), method, endpoint, payload, and local warnings without calling the Aegro
API. With AEGRO_SAFE_MODE=1, mutating commands are blocked unless --execute
is passed. List/filter/get commands continue to work.
Safe mode also requires writes to name their farm explicitly. If the active farm
came from state.json (written by farms select, global per machine and shared
by every session), --execute fails with IMPLICIT_FARM_BLOCKED (exit 4):
export AEGRO_SAFE_MODE=1
aegro tags create --name Plantio --relation-type CROP --execute
# → IMPLICIT_FARM_BLOCKED: repeat with --farm "Fazenda Sul"
aegro tags create --name Plantio --relation-type CROP --execute --farm "Fazenda Sul"
This exists because parallel sessions — one per farm — used to overwrite each
other's farms select, silently retargeting writes at the wrong farm. --farm
is per-invocation, so it cannot race.
Usage Examples
Human workflow
# Morning overview
aegro farms select "Fazenda Norte"
aegro crops list --output table
# Date windows come in pairs (--due-date-start needs --due-date-end)
aegro financial installments --status NOT_PAID --due-date-start 2025-03-01 --due-date-end 2025-03-31 --output table
aegro stock items --output table
# Register a fuel supply
aegro fuel-supplies create --asset-key K --date 2025-03-13 --quantity 150 --unit L --cost 900
# Check harvest
aegro harvest-logs get <key>
LLM/Agent workflow
# Agents use JSON output (default) for structured data
aegro crops list --start-date 2025-01-01 --end-date 2025-12-31
aegro activities list --crop-key <key>
aegro stock items
aegro financial installments --status NOT_PAID
AI Skills
The source of truth for public Aegro skills is the Aegro-owned Claude plugin
repository aegro/skills. Internal
harness skills live separately in the private
aegro/skills-internal repository.
This CLI embeds a generated snapshot of aegro/skills in aegro/_skills/
for PyPI installs. Do not edit embedded skills directly; update aegro/skills
and then run:
python scripts/sync-skills.py <version>
/plugin marketplace add aegro/skills
/plugin install aegro-skills@aegro-skills
Users who install the CLI from PyPI get the skills with:
pip install --upgrade aegro
aegro skills install
install reads aegro/skills and falls back to the snapshot embedded in the
wheel only if the repository is unreachable. Pass --offline to require the
snapshot and skip the network entirely.
The snapshot is a safety net — corporate networks that intercept HTTPS, GitHub
being down, machines without access — not the source of truth. It is generated
at build time and deliberately not tracked in git; a checkout produces it
with python scripts/sync-skills.py <version>.
Staying up to date
aegro skills sync is the explicit form: it always reads the repository, and
adds --ref, --prune and --dry-run. Unlike install, a network failure is
an error rather than a silent fallback.
aegro skills sync # install/update from the default branch
aegro skills sync --dry-run # show what would change
aegro skills sync --ref v0.7.0 # pin to a tag or commit
aegro skills sync --prune # also drop skills deleted upstream
Sync overwrites local edits to aegro-* skills and repairs partially broken
ones — it makes the target directory match the repository. It records the
commit it installed in .aegro-skills-sync.json, which aegro skills status
reports as the provenance.
To keep an assistant current without anyone remembering to run it, wire it to a
SessionStart hook in ~/.claude/settings.json (see
docs/ev-cowork/settings.example.json). Use --quiet --offline-ok there so a
session never fails or gets noisy because GitHub was unreachable:
{
"hooks": {
"SessionStart": [
{
"matcher": "startup",
"hooks": [{ "type": "command", "command": "aegro skills sync --quiet --offline-ok" }]
}
]
}
}
Overrides: AEGRO_SKILLS_REPO, AEGRO_SKILLS_REF, AEGRO_SKILLS_PATH.
Behind a TLS-intercepting proxy
Corporate networks that inspect HTTPS re-sign traffic with their own root CA. The
OS trusts it, but Python verifies against the bundled certifi CAs, so requests
fail with self-signed certificate in certificate chain.
Every command retries with the OS trust store automatically — and only after a certificate error, so nothing that works today changes. That is usually enough, because the CA is already installed on the machine. If it still fails, point the CLI at your network's root certificate:
export AEGRO_CA_BUNDLE=/path/to/corporate-root-ca.pem # or SSL_CERT_FILE
When no strategy works, the error is TLS_TRUST_ERROR (not a generic connection
error), and it names the host and the strategies that were tried.
aegro skills install needs no network at all and remains the offline fallback.
Never disable certificate verification to work around this.
Claude Code's own plugin marketplace (autoUpdate) does the same job natively
and is the better default when the assistant is Claude Code; sync covers other
tools and environments where that is not available.
Domain skills (personas)
| Skill | Purpose |
|---|---|
aegro-agronomo |
Agronomic domain — crops, fields, activities, harvests, weather, inputs |
aegro-estoquista |
Stock domain — items, locations, movements, catalogs, elements |
aegro-financeiro |
Financial domain — bills, installments, categories, bank accounts, companies |
aegro-operacional |
Operational domain — farms, auth, tags, cross-domain orchestration |
aegro-patrimonial |
Asset domain — machines, vehicles, fuel supplies, maintenances |
Workflow skills
| Skill | Purpose |
|---|---|
aegro-visao-geral |
Farm overview dashboard |
aegro-fechamento-safra |
Crop season closing checklist |
aegro-lancamento-financeiro |
Financial entry guide |
aegro-conciliacao-bancaria |
Bank reconciliation (OFX × financeiro) |
aegro-reconciliacao-estoque |
Stock reconciliation |
aegro-monitoramento-pragas |
Pest monitoring |
aegro-analise-rentabilidade |
Profitability analysis |
aegro-cadastro-patrimonio |
Asset registration |
Configuration
Authentication
Two authentication modes:
- OAuth login (default) —
aegro auth loginopens the browser for the regular Aegro login (email/password, e-mail code or Google). The CLI stores the user session (access + refresh token) and discovers the user's farms automatically. The session renews itself; no key handling needed. - API key —
aegro auth login --api-key ...stores a static per-farm key. Best for CI/CD, scripts and agents.
API key resolution priority (when both modes have credentials for a farm, the API key wins):
AEGRO_FARMSenv var (JSON) — for CI/CD and scriptsAEGRO_FARMS_FILEenv var (path) — for Docker/K8s secrets- Config directory (
~/.config/aegro/on Linux,~/Library/Application Support/aegro/on macOS,%USERPROFILE%\.aegro\on Windows) — interactive setup viaaegro auth login
# Option 1: Browser login (recommended for humans)
aegro auth login
# Option 2: Environment variable
export AEGRO_FARMS='{"Fazenda Norte": "aegro_key1", "Fazenda Sul": "aegro_key2"}'
# Option 3: Static API key (saves to OS-native config directory)
aegro auth login --farm-name "Fazenda Norte" --api-key "aegro_key1"
# Inspect the session (method, user, expiry, farms)
aegro auth status
# Remove local credentials (revokes the OAuth session server-side)
aegro auth logout # everything
aegro auth logout --env staging # one environment only
Active Farm Resolution
With credentials configured, the active farm is resolved from two sources, in this order:
--farmflag — scoped to a single invocation, accepted by every API commandstate.jsonwritten byaegro farms select— global per machine
Use --farm when several sessions run in parallel, one per farm. Only the
flag survives that: state.json is shared, so one session's farms select
retargets every other session.
--farm accepts either the farm name (case- and accent-insensitive, so
"fazenda sul" finds "Fazenda Sul") or the farm key (farm::...), which
is opaque and stable — handy for avoiding shell quoting of names with spaces. An
ambiguous name is rejected rather than guessed.
# Scope a single command to one farm, regardless of what any session selected
aegro assets list --farm "Fazenda Norte"
aegro assets list --farm farm::abc123
# Confirm which farm is active, where it came from, and each farm's key
aegro farms list # 'source': "flag" | "state" | null, plus 'key'
AEGRO_ACTIVE_FARM was removed
Three ways to name the same thing was itself the source of the confusion it was
meant to solve, so the env var is gone — --farm covers every case it did.
The removal is loud, not silent: while the variable is still set in the
environment, API commands fail with ACTIVE_FARM_ENV_REMOVED (exit 4) instead of
running. Ignoring it quietly would resolve the farm from state.json — a
different farm from the one the variable names — which is exactly the accident
--farm exists to prevent. Remove the variable and pass --farm instead.
Environment Variables
| Variable | Default | Purpose |
|---|---|---|
AEGRO_API_BASE_URL |
https://app.aegro.com.br |
Aegro API base URL |
AEGRO_FARMS |
— | JSON map of farm name → API key |
AEGRO_FARMS_FILE |
— | Path to JSON credentials file |
AEGRO_CONFIG_DIR |
— | Override config directory path |
AEGRO_SAFE_MODE |
— | Blocks mutating commands unless --execute; also requires the farm to come from --farm. Use --dry-run to preview |
AEGRO_OAUTH_CLIENT_ID |
aegro-cli |
OAuth client id (AEGRO_OAUTH_CLIENT_ID_<ENV> for other envs) |
AEGRO_NO_VERSION_CHECK |
— | 1 disables the outdated-version notice (no PyPI lookup) |
AEGRO_CA_BUNDLE |
— | Root CA bundle (PEM) to verify HTTPS against, for TLS-intercepting proxies. Applies to every command. SSL_CERT_FILE also works and AEGRO_CA_BUNDLE wins over it (both are cafile); SSL_CERT_DIR is additive (capath) and advisory |
Outdated-version notice
aegro --version and aegro auth status compare the installed version against
PyPI and print one line to stderr when a newer release exists. Commands that fail
with API_ERROR, UNEXPECTED or NOT_PERSISTED carry the same hint as an
upgrade field next to error in the JSON on stderr — a contract error is very
often a CLI that predates the fix.
The lookup runs at most once a day (cached under the config dir; once an hour
after a failure), times out in 1.5s and fails silently: no network, no notice, no
change in behaviour. A successful command never triggers it. Set
AEGRO_NO_VERSION_CHECK=1 to switch it off entirely.
Updates are verified after they are written
fuel-supplies update, maintenances update and harvest-logs update re-read the
record after a successful PATCH and compare it against what was sent;
purchase-orders create-shipment re-reads the order and looks for the shipment the
POST returned. If the change did not persist, the command fails with
NOT_PERSISTED and exit code 1 instead of reporting success — an API that answers
200 and discards the payload is worse than one that errors, because the operator
marks the task done. What could not be compared with confidence (a unit the server
converted, a nested structure) is reported as unverified on stderr rather than
treated as a failure.
Pass --skip-verify to skip the re-read. On success the command prints the
re-read record; with --skip-verify, or if the re-read itself fails, it prints the
PATCH response instead.
Development
# Install dependencies
uv sync
# Run tests
uv run pytest -v
# Lint
uv run ruff check aegro/ tests/
# Format
uv run ruff format aegro/ tests/
Links
- Aegro — Agricultural management platform
- Typer — CLI framework
- PyPI: aegro — Package page
License
Release files for aegro 0.28.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| aegro-0.28.0.tar.gz | 904.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| aegro-0.28.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 1.6 MB
Release files / aegro-0.28.0.tar.gz
| Download URL | aegro-0.28.0.tar.gz |
|---|---|
| Size | 904.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
14242c39a58fe84322ccc50536fcdd20e6011ccd8382671b753d402476f35980
|
|
BLAKE2b-256 checksum How to use checksums |
6273ffe398f17d6fe7345784661738ecc6e299513894c6d6df537f6a074a1299
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.
Transparency logRelease files / aegro-0.28.0-py3-none-any.whl
| Download URL | aegro-0.28.0-py3-none-any.whl |
|---|---|
| Size | 673.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7b0a410d0b5bd3bd8b0df5518730c0e260c9fc59adeeb8cebfda1550cb9c3c9a
|
|
BLAKE2b-256 checksum How to use checksums |
99a9a110db54920136aca4d23f3503ecca2fb8a360eed9e5691ac8a4ffa8ad62
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.
Transparency log