cli/skills/weknora-shared/SKILL.md
weknora is the agent-first CLI for a WeKnora RAG server. Every command prints
a JSON envelope and uses a typed exit code, so you branch on machine-readable
output, not prose. Read this skill before any task-specific weknora-* skill.
Agents usually skip profiles entirely: set WEKNORA_API_KEY (or
WEKNORA_TOKEN) + WEKNORA_HOST and every command authenticates statelessly and
zero-disk — no profile add / auth login needed. auth token echoes that env
credential; auth status / doctor confirm it. The steps below set up a
persistent named profile instead (interactive / multi-environment use).
Authentication is a two-step sequence. weknora auth login operates on the
active profile, so the profile must exist first:
# 1. register a connection target and make it active
weknora profile add prod --host https://kb.example.com --use
# 2a. API key (agent default — pipe the key on stdin, non-interactive):
echo "$WEKNORA_API_KEY" | weknora auth login --with-token
# 2b. OR email+password (interactive prompt only — no flags; not for agents)
weknora auth login
weknora auth status # verify: who am I, which tenant
--profile NAME
(e.g. weknora --profile staging auth refresh). There is no per-command
--name/--host on auth commands.WEKNORA_TOKEN=$(weknora auth token)
(raw token by default; works with an env credential too; --format json gives
the {token, mode, profile} envelope).weknora auth logout clears a profile's stored credentials but keeps the
profile registered (re-auth later with auth login); use profile remove
to delete the profile entirely.weknora doctor runs 4 health checks (reachability, credential, version, storage).--kb)--kb accepts a name or a UUID (resolved server-side). Resolution order:
--kb flag → WEKNORA_KB_ID env → directory link (weknora link --kb X binds
the cwd) → error. Read/create commands that operate "inside a project" inherit
the link; search * and destructive --all operations always require an
explicit --kb (so an agent never silently hits the wrong corpus).
A KB must have an embedding model bound to be searchable. A freshly created
KB is retrieval_ready:false — uploaded docs stay unindexed and search/chat
return nothing until you bind models. Create it ready in one step
(kb create --embedding-model <m> --chat-model <m>, discover ids with
weknora model list) or bind after the fact
(kb config set <kb> --embedding-model <m> --chat-model <m>). kb status /
kb check report retrieval_ready, and kb create hints the fix when it is
false — so an unconfigured KB is never silently "healthy".
Default output is --format json: a single envelope.
| Field | Meaning |
|---|---|
ok | true/false — branch on this first (see batch/wait caveat below) |
data | success payload (object or array; absent on mutation-only success) |
meta | count / has_more / dry_run / plan … |
error | on failure: {type, message, hint?, retry_argv?, retryable?, risk?} |
profile | active profile name |
error.type is a stable typed code (e.g. local.kb_not_found,
input.invalid_argument, input.confirmation_required, server.error).
Branch on it; error.hint usually tells you the next action.--format text = a live human-readable projection. chat and session ask
buffer a bounded answer-event projection into one JSON envelope by default;
pass --reference for indexed citations, --verbose for execution detail,
or --format ndjson for raw event lines. session resume remains
an NDJSON streaming command.--jq '<expr>' filters the envelope (e.g. weknora kb list --jq '.data[].id').weknora auth token emits the raw token by default (it's a
scripting helper); pass --format json for the {token, mode, profile} envelope.ok:
doc/chunk/session delete with several ids → a batch envelope:
status is success/partial/error, ok is true only when every
item succeeded (ok:false on any failure), data is a per-item array
[{id, ok, result|error}], and meta.successes/failures count the split.
Exit 1 if any item failed.doc wait → a normal ok:true envelope whose data partitions the ids
into {completed, failed, timeout}; ok stays true even with failures
(to avoid a contradictory envelope). Exit 1 if any doc failed, 124 on timeout.
Either way, read the exit code first, then data for which items failed.| Code | Meaning (typed code class) | Agent action |
|---|---|---|
| 0 | success (incl. --dry-run) | proceed |
| 1 | local.* / unclassified (incl. local.kb_not_found) | read error, decide retry/abort |
| 2 | flag / argument validation (bad/unknown/missing-required flag) | re-check weknora <cmd> --help |
| 3 | auth.* (missing / expired / forbidden) | re-auth, then retry |
| 4 | resource.not_found (a server resource id) | verify the id |
| 5 | input.* (other than confirmation_required) | adjust args, retry |
| 6 | server.rate_limited | back off, retry |
| 7 | server.* / network.* | transient — retry with backoff |
| 10 | input.confirmation_required (destructive) | see §5 — never auto-bypass |
| 124 | operation.timeout | raise --timeout or check the job |
| 130 | operation.cancelled (SIGINT/SIGTERM) | stop, don't retry |
Note: a server resource id that doesn't exist → exit 4 (resource.not_found);
a --kb name that doesn't resolve client-side → exit 1 (local.kb_not_found).
input.invalid_argument spans two exit codes — a malformed invocation
(unknown/missing flag, wrong arg count) exits 2 (fix the command, re-check
--help), while a value rejected after parsing (e.g. a bad --jq expression)
exits 5 (adjust the value, retry). Branch on the exit code to tell them apart.
Destructive commands (kb/doc/chunk/session/agent delete, kb/agent update,
auth logout, doc delete --all, …) without -y exit 10 with
error.type = input.confirmation_required and error.risk = {level, action}:
{"ok":false,"error":{"type":"input.confirmation_required",
"message":"delete knowledge base X requires explicit confirmation: re-run with -y",
"retry_argv":["weknora","kb","delete","X","-y"],"risk":{"level":"destructive","action":"kb.delete"}}}
Surface this to the user and get explicit approval. Re-run with -y ONLY
after they approve. Never add -y on your own initiative.
--dry-runAny mutation accepts --dry-run: it resolves the request, prints
meta.plan = {action, args}, makes zero server/side-effect changes, exits 0.
Use it to confirm a command is well-formed (and what it would do) before running
it for real — especially before destructive or bulk operations.
Mutations return the new resource id in data.id. Chain with it:
KB=$(weknora kb create "Docs" --jq '.data.id' --format json | tr -d '"')
weknora doc upload ./manual.pdf --kb "$KB"
Use weknora message list --session <sess-id> to review the message history of a session (e.g., after a stream drops) before deciding whether to re-ask or continue. Use weknora message search "<query>" to locate a prior Q&A exchange across all sessions — prefer this over re-running an expensive query when the answer may already exist.
An agent run pauses mid-stream on a tool-approval event when the server requires human sign-off before executing a tool call. The pattern:
pending_id.weknora session tool-approval resolve <pending-id> -y to approve, or add --reject --reason "..." to reject.weknora session resume <sess-id> --message <msg-id>.--modified-args '{"key":"val"}' replaces the tool arguments on approve (non-empty JSON object required). This is an exit-10 interaction — see §5.
kb knowledge bases list/view/create/update/delete/pin/unpin/status/check
doc documents in a KB list/view/create/upload/fetch/download/reparse/update/delete/wait
chunk retrieval units list/view/delete (RAG debug; not search)
session conversations list/view/delete/ask/stop/resume/tool-approval resolve
message session messages list/search/delete
agent custom agents list/view/create/update/delete/status/check
model configured models list/view/create/update/delete (update rotates key / base-url in place, id preserved)
search retrieval chunks / docs / kb / sessions
chat one-shot KB RAG Q&A (streaming)
api raw HTTP passthrough to any server endpoint (escape hatch)
link/unlink bind cwd to a KB mcp serve expose weknora as MCP tools
chat vs session ask vs search — the most common confusion: see the
weknora-rag-search skill for the decision table. Briefly: chat = one-shot
KB Q&A with an LLM; session ask --agent <id> = invoke a custom agent;
search chunks = raw hybrid retrieval (no LLM).
For your own scripted control, use the CLI (richer: dry-run, exit-10, all verbs).
For an IDE/host agent that speaks MCP, weknora mcp serve exposes a curated
read+chat tool set: kb_list, kb_view, doc_list, doc_view, doc_download,
search_chunks, chunk_list, agent_list, chat, session_ask. MCP tools
take raw ids (no name resolution); resolve names via kb_list first.
Run weknora <command> --help. With WEKNORA_AGENT_HELP=1 set, --help emits a
JSON blob (used_for / required_flags / examples) instead of prose — parse
that to learn a command without scraping the human help table.
| Mistake | Fix |
|---|---|
weknora auth login before any profile exists | profile add <n> --host <url> --use first (§1) |
Passing --host or --name to auth login | auth login takes neither — host comes from the profile; use profile add <n> --host <url> --use, then auth login |
Auto-adding -y to clear an exit-10 | Never; get user approval first (§5) |
Need the raw chat event stream | pass --format ndjson; use --format text for a live projected transcript |
search chunks "q" → exit 1 local.kb_id_required | Pass --kb <name-or-id>, set WEKNORA_KB_ID, or weknora link the dir |