Quickstart
1
Install
- Homebrew
- Arch Linux
- Manual
2
Authenticate
3
Ask
Common workflows
- Interactive
- One-shot
- Pipe data
- Investigate
- Query the graph
- Use with agents
Start a terminal chat with session history and markdown output:
Stay up to date
Stable Annie CLI releases tell you when a newer version is available in an interactive terminal. The TUI keeps the available version in its status bar, and successful human-readable commands may show one reminder every 24 hours. Check synchronously whenever you need the current release status:Investigate cloud changes
Use deterministic graph commands when you need retained AWS, Azure, GCP, or Cloudflare change evidence in a terminal, script, or CI job. List recent events by provider and scope. For GCP, you can also narrow events to one provider operation and inspect the affected inventory:2 with
RESOURCE_AMBIGUOUS and lists at most ten stable-ID candidates. JSON keeps the same candidates at
.error.details.candidates. Select one id or anyshiftID and retry; Annie never traverses from an
arbitrary first match.
--operation groups activity by the GCP-native operation identifier. --correlation selects the
broader Anyshift event story. They are separate identifiers. Text output keeps the main evidence
fields; use JSON when automation needs warnings, availability, before and after values, pagination,
or provenance references:
annie graph cloud-events browsing uses bounded page mode. Text output reports the number
shown, whether more results exist, and the next cursor without calculating or claiming an exact
full-window total. Use --exact-stats only when you need the exact total and event-type breakdown;
that opt-in can be slower on large accounts. In page-mode JSON, total is null, byType is empty,
and statistics reports { "mode": "none", "exact": false }.
An unknown status is not success. Unknown provenance does not mean unmanaged, and unknown freshness
does not mean stale. If a response contains nextCursor, pass it back with --cursor to continue
that result page.
Repository context
Add an.annie.yaml file to a repository when you want every question from that workspace to use the same Anyshift project, metadata, and runbooks:
.annie.yaml
.annie.yaml by walking up from your current directory. Repository settings apply only to that invocation and do not change your global default project.
Use project-scoped personal context when a value should follow you across repositories:
.annie.yaml.
Invocation flags take precedence over TUI session context, repository context, and personal project context:
annie context preview to check file status without printing file contents.
Structured output
Pass a local JSON Schema when a script or CI job needs a predictable object instead of prose:service-risk.schema.json
--schema requires --output json and supports JSON Schema Draft 7 and Draft 2020-12 with an object at the root. Remote schema references are rejected.
Conversation history
Resume a previous investigation with its transcript instead of starting over:annie conversation delete <id> requires confirmation and may be restricted to administrators.
Reference
Query options
Query options
ask timeout covers startup input, login renewal, project selection,
submission, and waiting for the answer. With --follow, each question gets a
fresh timeout after you enter it; time spent typing is excluded. Login requests
also have a 30-second limit, and a failed renewal preserves your saved credentials.Graph commands
Graph commands
All non-interactive graph commands support
--project <name|uuid> and --output text|json. Run annie graph <command> --help for command-specific flags.graph brief and resource-scoped graph check resolve the resource before querying posture.
When a name exists in two clusters, qualify the brief or use a stable ID:RESOURCE_SCOPE_UNSUPPORTED in
workflow.warnings and partial completeness. Unavailable headline.activeAlerts and
headline.downstreamServices are null, not zero; text displays unknown. These warnings
mean evidence was not queried, not that the resource is missing or healthy.Inspect public exposure for a Cloudflare hostname or a Kubernetes service:originReachability for internet-facing ALB or NLB security-group evidence versus pinned Cloudflare IP ranges. That field is not DNS proxied / RESOLVES_DIRECTLY_TO, and text output prints it separately from traffic gaps. See Origin reachability.graph triage is deterministic evidence, not AI. It optionally queries incident_context for the
resource (target + since + LIMIT). Returned hops are incident, alerts, service,
onCall, responders, and history. Empty hops are omitted from findings. History cites reviewed
resolution evidence only (confirmed_fix, explicit_reference, or unknown), never
temporal-only association. Raw queries use
incident_context; PagerDuty
setup is on the PagerDuty integration page.graph show accepts a hashedID or anyshiftID returned by graph discovery. It uses the
project-scoped Graph API and never guesses from a display name. Resolve a name first, then inspect
the selected identity:graph show --at reads are not
supported until the Graph API has snapshot semantics; use annie graph history for retained change
evidence instead.Discover the query language without authentication:Automation and exit codes
Automation and exit codes
JSON output uses the
annie.cli/v1 envelope. Natural-language answers are returned under .answer.content, while Graph results are returned under .data.From v0.8.60, Graph query validation errors keep the server’s explanation at
.error.details.reason, such as an unknown table, the allowed filters, or required time bounds.
These errors still return GRAPH_QUERY_INVALID and exit 2. Use the reason to correct the query
before retrying. Ambiguous resource errors remain RESOURCE_AMBIGUOUS, with retry choices in
.error.details.candidates.Require a schema-validated answer with:Sessions and TUI
Sessions and TUI
Use
Tab for command completion, Page Up/Down to scroll, and Ctrl+C to cancel.To recover from a network error, API failure, or failed analysis, enter /retry.
To change the question first, enter /edit, modify the restored text, and press
Enter. Editing alone does not send a request.Both commands also work after a successful answer. Retrying creates a new request
in the same conversation once one has been established; it does not replace the
earlier turn. /retry keeps the context and files from the original submission,
while an edited question uses the current context and files when you send it.
RCA and report questions keep their command prefix. Quick prompts such as
/alerts expand into editable question text.The last question is available for the current session and project. Clearing the
screen keeps it, and switching projects resets it. Wait for the current request
to finish before retrying or editing.Past investigations and reports
Past investigations and reports
Projects
Projects
--project <name|uuid>.Authentication and CI
Authentication and CI
For local use:For CI, create an access token in Settings → Access tokens, store it as a secret, and set:
ANNIE_PROJECT_ID is only required when the token can access multiple projects. Use personal tokens locally and shared tokens for team automation. Token authentication cannot perform administrative operations.Feedback
Feedback
/rate up, /rate down, or /rate hypothesis <n> up|down.Configuration and privacy
Configuration and privacy
~/.annie/config.yaml. Disable anonymous telemetry with:NO_COLOR.Create account
Start using Anyshift
Request a demo
See the CLI in action
Delivery provenance and code owners
Useannie graph delivery to see stored delivery activity, release/commit provenance, and observed code ownership for one resource:
--type, --namespace, and --cluster, or select an exact --id. --project selects the project for the whole workflow.
--cursor continues only the delivery-event page; retain the same resource, time window, and limit. Provenance and ownership are refreshed bounded snapshots. JSON preserves the section payloads under data.sections, including stored identities, provenance paths, evidence warnings, and the delivery continuation cursor.
Code ownership means observed OWNS_CODE team/person relationships. graph owners continues to report GitOps application/repository ownership. Missing commit, actor, release, or owner links remain unknown. A commit, PR, or tag alone does not prove that a customer deployment occurred.
Observed graph coverage
Before interpreting an empty investigation, inspect which source evidence is represented:kubernetes, cloud, github, datadog, tempo, dynatrace, victoria, and grafana; k8s and scm are aliases for Kubernetes and GitHub. PagerDuty and Sentry are not included in this source inventory.
These counts do not establish which integrations are configured, whether ingestion is healthy or fully synced, or whether monitoring policies cover every resource. An empty result means the query found no represented evidence within its scope; it does not prove that the underlying resources or events do not exist.
Exact Sentry alert contributors
Discover a retained Sentry firing, then inspect its stored contributor links:--from/--to, and --cursor pagination. Continue with the same project and
filters; the cursor preserves the original window. Results distinguish metric
evaluations, source errors and unclassified records. No retained firings does not
prove Sentry had no firings. declarationAvailable: false is different from a
known empty declaration.
The firing ID is the exact, case-sensitive firingId returned by discovery
(the graph event’s dedupeId). It is not a Sentry issue number or rule name. The command
returns stored contributor identities, available timestamps, event types, and
release context. JSON exposes the result under data, including counts,
missingProviderEventIds, and page.nextCursor. Use the same firing and project
when continuing a page.
Declared IDs and observed linked events are counted separately. Missing
contributors may be late, expired, or unobserved; the missing-ID list can be a
bounded sample. Evaluation coverage remains unknown even when every declared ID
is linked. Contributor membership describes alert evaluation, not a proven
infrastructure root cause. No temporal match is substituted for a stored link.
Cloudflare resource inventory
Use the same inventory workflow for canonical Cloudflare resources:cf:// account and zone identity. Cloudflare resources
have no fabricated cloud region. Inventory keeps canonical API-scanned resources
separate from Terraform or evaluation copies while retaining observed IaC links.
Absent observation timestamps and missing provenance remain unknown.
Freshness compares each stored resource observation with --max-age, defaulting
to 24 hours. Text output shows the threshold, observation timestamp and age; JSON
retains filter.freshnessHours and each observedAt. This is not the time of the
last completed scan job. Increasing --max-age does not refresh inventory. If
observations stop advancing, investigate the connection and extraction pipeline;
a partial scan does not by itself prove that OAuth authorization was revoked.
Finding Datadog monitor evidence
firing. Zero firing alerts can coexist with stored
recovered, suppressed or unknown monitors. Empty firing results offer a command
that preserves the selected project and filters while switching to --status all.
Page counts use the returned canonical items; coverage is independent of that
count. not_configured describes missing graph coverage, not a verified credential
check.
Monitor snapshots are collected hourly. Datadog alert coverage becomes stale
after 75 minutes, allowing one collection interval plus 15 minutes for processing.
The observation timestamp remains visible. Available coverage means a recent
snapshot under this policy, not real-time confirmation of monitor status.
Datadog cloud scope in alert investigations
Datadog monitoring evidence can identify cloud targets directly, including RDS and EC2, without an intermediate APM service. Alert and monitor results preserve target IDs and actual graph types. Cloud targets do not acquire Kubernetes namespace or cluster values. Compare returned scope targets withscopeTargetCount to detect a bounded sample.
Multiple legitimate targets remain explicit; monitoring scope does not establish
that a target caused the alert. JSON retains scope identities and evidence warnings
for automation.
Cross-layer storage, access, and potential impact
Follow stored Kubernetes-to-cloud relationships using exact resource IDs:storage shows the PVC/PV footprint and cloud resources linked through stored
USES_DISK relationships, including graph/native identities and account scope.
access shows Kubernetes role evidence and observed ServiceAccount-to-IAM-role
associations. An IRSA association does not prove effective permissions or a
successful role assumption. Missing identity and relationship evidence stays
unknown.
Both commands resolve one subject before querying. Qualify ambiguous names with
the common resource selectors or use --id; they reject responses for a different
resolved identity. Cloud-backing and IRSA sections are bounded snapshots with
limit, hasMore, and an explicit evidence boundary. A missing section from an
older server means the evidence is unavailable.
impact evaluates reviewed propagation directions with a depth of 1–3. Its output
keeps exact target IDs, scope, relationship direction and warnings. Continue target
pages with --offset <nextOffset>. It excludes identity bridges and IAM role
associations; those relationships do not establish impact propagation. Potential
impact is not proof of damage or causation, and empty results never establish an
exhaustive absence of impact. The existing blast command remains available.
Path output includes graph/native IDs and scope. Both path scopes can follow cloud
compute, storage, role-association and hosting bridges within five hops;
--scope operational also includes observed APM identity and dependency edges.
These paths describe connectivity, not causal propagation or effective access.
Exact resource IDs
Ambiguous names list candidates with stable IDs. Copy the chosen ID unchanged, including an initial- or _; quoting preserves it as one shell argument:
annie graph delivery anyshift-backend --type GITHUB_REPO
selects that resource type when it uniquely identifies the intended resource.