@infona-ai/cli
v0.1.55
Published
Infona SDK and CLI — context graph platform for structured data
Maintainers
Readme
@infona-ai/cli
Node.js SDK and CLI for Infona — turn raw data into a queryable context graph (a knowledge graph you query in natural language).
Package: @infona-ai/cli. Primary binary: infona. Compatibility alias: onta (same entrypoint). Env vars: INFONA_* only (no ONTA_* fallback).
Quickstart
npx -y -p @infona-ai/cli infona
# or: npm install -g @infona-ai/cli && infonaFirst run with no config opens an interactive connect wizard (not a silent cloud login and not a silent force-local):
Connect Infona
1) Local open-access (http://localhost:8000, tenant default)
2) Browser sign-in (hosted Infona cloud)
3) API key (paste key + optional URL)- Local probes the API, writes
~/.infona/config.json, and never opens a browser for open-access. - Browser is for hosted cloud only.
- API key is for CI/headless or self-hosted with auth.
Re-run any time: infona init (confirms before overwriting saved credentials).
Non-interactive local: infona init --local (probes localhost:8000, writes
open-access config, no readline — safe for scripts). Re-writing the same
local open-access config is idempotent; overwriting a different saved
connection (e.g. cloud API key) requires a TTY confirm, or --force when
non-interactive: infona init --local --force.
Then the interactive shell:
/ingest <file> Ingest a CSV/JSON/text file
/ask <question> Ask in natural language
/kg list|switch|create|delete <name>
/types [query] Types in the active KG, with entity counts
/type <name> Drill into one type — attributes & relationships
/enrich <Type> <attrs...> Plan + run an enrichment job (interactive)
/enrich watch <job_id> Live progress for a running job
/enrich jobs List recent enrichment jobs
/enrich review <job_id> Walk through conflicts and accept/reject
/status Graph stats
/login Re-authenticate
/quitBare lines (no leading /) auto-route to /ask. Full walkthrough at infona.ai/docs/quickstart.
Self-hosted / OSS repo mode
From the infona-oss checkout, after Neo4j + the API are up:
./scripts/oss_setup.sh # health probe → write local config → best-effort CLI link
infona # bare; uses ~/.infona/config.json (no --local needed)One-off flags (do not rewrite config):
infona --local # http://localhost:8000, tenant default
infona --no-login # assume open-access at INFONA_API_URL
INFONA_API_URL=http://my-host:8000 infonaPrecedence: flags (one-off) > env (INFONA_API_URL / INFONA_API_KEY) >
~/.infona/config.json > connect wizard when empty.
When self-hosted, the prompt shows the host suffix: infona@localhost:8000 (kg) ▸.
Auto-enrichment
Fill and verify attributes on entities of a given type by looking them up in external sources, with a human review step before any write:
> /enrich LineItem brand manufacturer
Plan: enrich LineItem.brand, .manufacturer · tier: lite · policy: stage
Job queued: enr_xxxxxxxx · 12,450 entities
[████████████████████] filled 6,200 · verified 1,400 · conflicts 320
Status: review · 320 conflicts pending. Run /enrich review enr_xxxxxxxxUse /enrich watch <job_id> for live progress, /enrich jobs to list recent jobs, and /enrich review <job_id> to walk through conflicts and accept/reject each one. The lite tier uses Wikidata only (free, no API key).
Install
npm install @infona-ai/cli # or: npm install -g @infona-ai/cliRequires Node 20+. The global install exposes the infona command (and the onta compatibility alias).
Browsing what got ingested
After ingest, look around before asking questions:
infona (mentors) [37,715] ▸ /types
Type Entities
Mentor 988
Skill 412
Industry 38
infona (mentors) [37,715] ▸ /type Mentor
Mentor 1,000 entities
Attributes (6)
.name string 988 ( 99%)
.level string 714 ( 71%)
...
Relationships (6)
.title → JobTitle 988 ( 99%) (+775 string)
.skills → Skill 987 ( 99%)
.../types <query> filters by substring; /type <name> accepts case-insensitive prefix. Auto-attached system metadata (rdfs:label, ingested_at, source) is hidden by default — pass --system to see it. The (+775 string) annotation appears when the resolver produced both a literal value and a typed-entity link for the same column.
SDK
import { Client, InfonaError } from "@infona-ai/cli";
const client = new Client({ apiKey: process.env.INFONA_API_KEY });
await client.ingest("sales.csv", { kg: "sales" });
const result = await client.ask("What's the average deal size by region?", { kg: "sales" });
console.log(result.answer);Constructor
new Client({
apiKey?: string, // env: INFONA_API_KEY
baseUrl?: string, // env: INFONA_API_URL (default: https://api.infona.ai)
tenant?: string, // env: INFONA_TENANT (default: demo-tenant)
})Methods
ingest(pathOrText, { kg?, contentType? })— auto-detects CSV by extension and uses the two-step schema/rows flow; otherwise sends raw content.ask(question, { kg? })— returns{ answer, sparql?, ... }.listKgs(),createKg(name, description?),deleteKg(name)— context-graph CRUD.ontologyTypes()— list every type in the tenant ontology with attributes and parents.ontologyResolve(ask, { knowledge_graph? })— resolve a fuzzy natural-language ontology-evolution ask (no exact type/attribute/relationship names needed) against the current schema. Returns{ applied, proposals, summary }; high-confidence changes land automatically, ambiguous/new-type ones come back asproposals.ontologyApply(proposal)— confirm and commit a singleResolvedChangefromontologyResolve'sproposals. Pass the object through unchanged; returns{ applied, operations, summary }.typeCounts(kg)—[{ name, entity_count }]for the given KG, sorted desc. Powers/types.typeUsage(kg, name, { includeSystem? })— full breakdown for one type: attributes (with usage counts), relationships, and 3 sample entities. Powers/type. System predicates filtered by default.exploreRecords(kg, type, { limit?, cursor? })— one keyset-paginated page of entity instances ({ columns, rows, total, next_cursor }).exploreTypeEdges(kg)— undirected type→type edges for an overview graph ([{ source, target, weight }]).normalizeSuggest(kg, type),normalizeRules({ kg?, status? }),normalizeConfirmRule(id),normalizeRejectRule(id),normalizeApplyRule(id)— inferred-normalization rule lifecycle.ontologyRecommend(body?)— recommend ontology relationships/changes for a KG.
All errors throw InfonaError (alias: InfonaError).
Raw / passthrough API (client.raw.*)
Every method above throws on a non-2xx status and some reshape the payload
(e.g. listKgs() unwraps { kgs: [] }). When you instead want the backend
Response verbatim — to forward it 1:1 (e.g. from a web proxy route) or to
branch on status without a try/catch — use the raw namespace. Each raw
method maps to one canonical operation with the path encoded inside the SDK, so
callers pass no path string:
const client = new Client({ apiKey, tenant });
// Forward the backend response unchanged from a proxy:
const res = await client.raw.enrichJobs(); // GET …/enrich/jobs
return new Response(res.body, { status: res.status, headers: res.headers });
// A non-2xx is a Response, not a throw — and the body is never reshaped:
const r = await client.raw.enrichJob("missing");
if (r.status === 404) { /* … */ }client.raw covers agent, ask, ingest (+ csv schema/rows), enrich jobs
(create/list/get/conflicts/apply/cancel), ontology (types/resolve/recommend/apply),
kgs (list/create/delete), explore (summary/records/type-edges/type-counts/search),
search + grep (semantic instance search / index-free literal scan of one KG),
normalize (suggest/rules GET+POST/confirm/reject/apply) and tenants
(list/create/delete). Each returns Promise<Response> and only ever rejects on a
network error or timeout (i.e. when there is no HTTP response to return).
One-shot CLI
For scripts and CI — every command is a single HTTP round-trip (use the infona bin, or npx -y -p @infona-ai/cli infona …):
# List / create / delete context graphs
infona kg list
infona kg create my-data --description "demo"
infona kg delete my-data
# Ingest data
infona ingest data.csv --kg my-data
infona ingest --text "Alice works at Acme" --kg my-data
# Ask questions
infona ask "How many companies?" --kg my-data
infona ask "Top 5 deals" --kg my-data --debug # Cypher + latency breakdown
# Ontology + clear
infona ontology types
infona clear --kg my-data --yesEnvironment
Prefer INFONA_* for new configs:
INFONA_API_KEY— required for headless / CI use;infona init(API key path) orinfona loginwrites one to~/.infona/config.json.INFONA_API_URL— defaulthttps://api.infona.ai. OSS setup / local wizard setshttp://localhost:8000.INFONA_TENANT— defaultdemo-tenanton cloud,defaulton localhost open-access.
Config file
~/.infona/config.json (mode 600). Example after ./scripts/oss_setup.sh or infona init --local:
{
"apiUrl": "http://localhost:8000",
"tenant": "default"
}PDF ingest is not supported on any surface (CLI, API, MCP). Extract text or tables first; CSV is the best-supported path.
License
Apache-2.0. See LICENSE.
