Skip to content

phpbotscout ask

The ask command answers a question using only the documentation phpbotscout has already indexed. When the indexed corpus contains an answer, it returns grounded prose backed by citations. When it does not, it declines — honestly and by design — rather than inventing something plausible.

Usage

$ phpbotscout ask "your question"

It reads the index built by index build, so an empty index declines everything.

Description

phpbotscout ask turns a question into a grounded answer, or into an honest refusal to answer.

The command retrieves the most relevant passages from the indexed documentation, then asks a language model to compose an answer using only those passages. Every substantive claim in the reply must be traceable to a specific, cited passage that was actually retrieved.

Declining is treated as a first-class outcome, not a failure. There are three situations in which the command will decline instead of answering:

  • Nothing matched. Retrieval returned no passages relevant to the question, so there is nothing to ground an answer in.

  • The composer declined. The passages discuss the subject but do not actually answer the question — a common and especially damaging trap, because the resulting answer would look well sourced while being wrong.

  • The answer could not be grounded. A draft answer was produced, but it cited nothing (see ErrUngrounded) or cited a passage outside the retrieved set (see ErrFabricatedCitation). Publishing such an answer is exactly the failure this command exists to prevent, so it is downgraded to a decline.

Why declining matters

A declined question is a knowledge gap with a timestamp on it. This is deliberate: the stream of unanswered questions is intended to become a self-writing, prioritised documentation backlog. A decline is an outcome to act on, not an error to suppress.

Answers are grounded, not guessed

The model is instructed to use only the supplied documentation passages and to ignore anything it may "know" about the projects from elsewhere. Passages are treated as untrusted content and fenced within explicit delimiters, so text inside a passage is never interpreted as an instruction.

An actual error (a non-zero exit) is reserved for something genuinely breaking — for example, the index being unreachable or the model provider failing. An error never means "we do not know"; that is a decline. Keeping the two distinct is what allows a knowledge gap to be told apart from an incident.

Which model answers

ask reads two configuration keys and has no flags for either:

Key Default Notes
ai.provider claude-local Only claude and claude-local work. openai, gemini and openai-compatible are refused at construction
ai.model Empty leaves the provider's default, which for claude is claude-opus-4-8not the Haiku 4.5 the project selected

The API key for ai.provider: claude comes from ANTHROPIC_API_KEY and from nowhere else; the credentials chain that serves gitlab.auth is not wired to the AI provider. Full detail in the configuration reference.

--retrieval-only needs no provider and no key at all.

Flags

Name Description Default
--limit How many passages to retrieve. Values of 0 or below fall back to the default, which is why --help lists no default for it. 8
--retrieval-only Print the ranked passages without composing an answer. No model is called, so this costs nothing. false
-h, --help Help for ask. false

Global flags (--config, --debug, --output, --ci) are inherited from the root command.

Diagnosing a bad answer

--retrieval-only separates the two things that can go wrong. If the right passage is not in the ranked list, the problem is retrieval; if it is there and the answer is still wrong, the problem is composition. Raising --limit tells you whether a missing answer was ranked just out of reach.

Examples

Ask a question directly:

$ phpbotscout ask "How do I stop a gtb tool checking for updates?"

Ask a longer, quoted question:

$ phpbotscout ask "What environment variable overrides the log level?"

An answer is grounded in the documentation and carries its citations, heading path included:

$ phpbotscout ask "How do I stop a gtb tool checking for updates?"
To stop a gtb tool from checking for updates, set the `update.policy` configuration key to
`disabled`. This will log only without checking for updates.

Sources:
  Configuration Keys › Self-update
    https://go-tool-base-ff2fdf.gitlab.io/reference/config/#self-update

When the corpus does not cover the question, it declines rather than guessing — and shows what it did retrieve, so the gap is diagnosable:

$ phpbotscout ask "What is the airspeed velocity of an unladen swallow?"
No answer from the indexed documentation.

  nothing in the indexed documentation matched this question

Inspect retrieval without spending anything on a model:

$ phpbotscout ask --retrieval-only --limit 20 "how is the index refreshed"

What ask cannot do

  • It cannot answer from anything not indexed. An empty index declines everything; build one first with index build.
  • It cannot search semantically. Ranking is BM25 keyword matching, so a question sharing no vocabulary with the page that answers it will not find it.
  • It has no memory. Each question is answered from its own passages; nothing carries over.
  • It has no relevance-threshold setting. --limit is the only retrieval control.

See also