Scoutline
A command-line field kit for investigating web, repository, and visual sources.
Independently maintained by Vikas Agarwal. See CREDITS.md for project attribution.
Features
- Vision - Analyze images, screenshots, diagrams, charts, videos using GLM-4.6V
- Search - Real-time web search with domain and recency filtering
- Reader - Fetch and parse web pages to markdown
- Repo - Search and read GitHub repository code via ZRead
- Tools - MCP tool discovery, schemas, and raw calls
- Code Mode - TypeScript tool chaining for agent automation
- Provider selection - Run shared capabilities through Z.AI or MiniMax Token Plan
Quick Start
export Z_AI_API_KEY="your-api-key"
npx scoutline --help
npx scoutline vision analyze ./screenshot.png "What errors do you see?"
npx scoutline search "React 19 new features" --count 5
Get your Z.AI API key at: https://z.ai/manage-apikey/apikey-list
To use MiniMax instead:
export MINIMAX_API_KEY="your-minimax-key"
npx scoutline --provider minimax search "latest LLM benchmarks"
Installation
As an Agent Skill
OpenSkills (universal - works with any AI coding agent):
npx openskills install vikasagarwal101/scoutline
Claude Code (native skill marketplace):
claude skill install vikasagarwal101/scoutline --skill scoutline
As a CLI Tool
npm i -g scoutline
scoutline --help
Or use directly with npx:
npx scoutline --help
Provider Selection
Shared commands (search, vision, quota, doctor, repo) accept a global
--provider <zai|minimax> flag. Resolution precedence:
- Explicit
--provider <zai|minimax>on the command line SCOUTLINE_PROVIDERenvironment variable- Compatibility default
zai
Examples:
# 1. Flag wins over everything
scoutline --provider minimax search "React 19 features"
# 2. Environment variable when no flag is supplied
export SCOUTLINE_PROVIDER=minimax
scoutline quota
# 3. Default Z.AI when nothing is supplied
scoutline search "TypeScript best practices"
Provider selection is never inferred from which credentials are present;
empty credentials leave the Provider unconfigured and shared capabilities will
fail with AUTH_ERROR or CONFIGURATION_ERROR. Unknown Provider IDs fail
fast with VALIDATION_ERROR.
scoutline search, scoutline vision, scoutline quota, scoutline doctor,
scoutline repo, and scoutline read participate in Provider
selection. scoutline tools, scoutline tool, scoutline call, and
scoutline code accept the flag but ignore it; they remain Z.AI-only.
MiniMax does not currently advertise the repository-exploration or reader
Capabilities — selecting MiniMax (explicitly or via SCOUTLINE_PROVIDER) for
any repo subcommand or for read returns UNSUPPORTED_CAPABILITY before
descriptor configuration, Adapter creation, cache identity, or transport
construction, with no Z.AI fallback.
Capability Matrix
| Capability | Z.AI | MiniMax | Notes |
|---|---|---|---|
search |
Yes | Yes | MiniMax rejects domain/recency/content-size/location controls |
vision.interpret-image (analyze) |
Yes | Yes | Provider-specific media limits; uncached |
vision.ui-artifact (ui-to-code) |
Yes | Available | Live-attested; conformance-gated |
vision.extract-text |
Yes | Pending | Implemented, pending live conformance |
vision.diagnose-error |
Yes | Available | Live-attested; conformance-gated |
vision.diagram |
Yes | Pending | Implemented, pending live conformance |
vision.chart |
Yes | Pending | Implemented, pending live conformance |
vision.diff (image diff) |
Yes | No | Z.AI-only (never MiniMax-claimable) |
vision.video |
Yes | No | Z.AI-only (never MiniMax-claimable) |
quota |
Yes | Yes | Normalized QuotaDashboard (ADR-0001) |
diagnostics (doctor) |
Yes | Yes | Lists both Providers; probes configured |
read (Reader) |
Yes | No (UNSUPPORTED_CAPABILITY) | Participates in selection; only Z.AI supplies reader |
repo search / repo read / repo tree |
Yes | No (UNSUPPORTED_CAPABILITY) | Participates in selection; only Z.AI supplies repository-exploration |
tools, tool, call (Raw tools) |
Yes | No | Z.AI-only; accepts but ignores --provider |
code (Code Mode) |
Yes | No | Z.AI-only; accepts but ignores --provider |
Media limits for general single-image interpretation:
| Provider | Formats | Maximum |
|---|---|---|
| Z.AI | JPG, JPEG, PNG | 5 MiB |
| MiniMax | JPG, JPEG, PNG, WebP | 50 MiB |
Vision results are never written to the local response cache.
Usage
The CLI is self-documenting. Use --help at any level:
scoutline --help # All commands
scoutline vision --help # Vision commands
scoutline search --help # Search options
scoutline repo --help # GitHub repo commands
scoutline doctor --help # Provider diagnostics
scoutline quota --help # Plan usage
scoutline cache --help # Local cache inspection and clearing
Examples
# Provider selection
scoutline --provider minimax search "AI policy news"
scoutline --provider zai search "internal docs"
# Vision - analyze images
scoutline vision analyze ./image.png "Describe this"
scoutline vision ui-to-code ./design.png --output code
scoutline vision extract-text ./screenshot.png --language python
scoutline vision diagnose-error ./error.png
# Search - web search
scoutline search "TypeScript best practices" --count 10
scoutline search "security news" --recency oneDay
# Reader - fetch web content
scoutline read https://docs.example.com/api
scoutline read https://blog.example.com --format text
# Repo - GitHub exploration
scoutline repo tree facebook/react
scoutline repo search vercel/next.js "app router"
scoutline repo read anthropics/anthropic-sdk-python README.md
scoutline repo search openai/codex "config" --language en
scoutline repo tree openai/codex --path codex-rs --depth 2
# Quota - effective or all providers
scoutline quota # effective Provider
scoutline quota --all-providers # every configured Provider
# Doctor - check setup
scoutline doctor # full diagnostics
scoutline doctor --no-tools # metadata only, no transport
scoutline doctor --provider minimax # MiniMax connectivity
# Cache - inspect or clear the local cache
scoutline cache stats # show inventory of both subdirectories
scoutline cache clear # delete every file under cache/ and tools/
Output Format
Default output is data-only for token efficiency. Use --output-format json for structured responses:
{
"success": true,
"data": "...",
"timestamp": 1234567890
}
Quota output is a schema-version-1 QuotaDashboard:
{
"schemaVersion": 1,
"effectiveProvider": "zai",
"providers": [
{
"provider": "zai",
"status": "ok",
"categories": [
{ "name": "requests", "unit": "requests", "current": { "remainingPercent": 87.5 } },
{ "name": "tokens", "unit": "tokens", "current": { "remainingPercent": 64.2 } }
]
}
]
}
Doctor output is a schema-version-1 DiagnosticsReport listing every built-in
Provider with its configured state, declared capabilities, probe status, and a
one-line cache summary under the cache field.
Notes
repo searchdefaults to English results. Use--language zhfor Chinese.repo treesupports--path(directory scope) and--depth(expand subtrees).quota --all-providersexits 1 if any configured Provider fails; successful entries are still reported.doctorexits 1 when the effective Provider is unconfigured or any configured probe fails; successful entries are still reported.readreturns a schema-version-1 envelope (content read or extract read) in every output mode.--with-images-summary,--no-gfm, and--keep-img-data-urlare passed through to the Provider request.--max-charsis ignored on extract reads;--full-envelopeis silently deprecated.- Vision tool calls automatically retry transient 5xx/network errors (default: 2 retries). Configure with
ZAI_MCP_VISION_RETRY_COUNT(orZAI_MCP_RETRY_COUNTfor all tools). - Tool discovery can be cached to speed
tools/tool/doctor(default: on, 24h TTL). The cache shares the unified root with the response cache; configure both viaSCOUTLINE_CACHE,SCOUTLINE_CACHE_TTL_MS,SCOUTLINE_CACHE_SIZE_MB, andSCOUTLINE_CACHE_DIR(legacy aliasesZAI_MCP_TOOL_CACHE*,ZAI_MCP_CACHE_DIR, andZAI_CACHE*are accepted silently). - The local cache lives at
~/.scoutline/(cache/for responses,tools/for tool discovery) on every platform. Inspect or clear it withscoutline cache statsandscoutline cache clear.
Repository Exploration (P6)
scoutline repo search, scoutline repo read, and scoutline repo tree
participate in --provider selection. Z.AI advertises the
repository-exploration Capability and supplies it through the Z.AI Repository
Adapter. MiniMax does not advertise it; selecting MiniMax returns
UNSUPPORTED_CAPABILITY before descriptor configuration, Adapter creation,
credential resolution for use, cache identity, or transport construction
with no fallback to Z.AI.
Breaking data-mode migration (v0.2 → v1)
The three repo successes return schema-version-1 structured values in
every output mode. This is an intentional breaking change from the v0.2 raw
Search/File strings and the depth-dependent raw Tree shape:
| Command | v0.2 (legacy, now obsolete) | v1 (current) |
|---|---|---|
repo search |
Raw ZRead text with <excerpt> blocks |
{schemaVersion, repository, query, language, excerpts:[{text}], truncated, originalTextLength} |
repo read |
Raw <file_content>…</file_content> body |
{schemaVersion, repository, path, content, truncated, originalContentLength} |
repo tree |
<structure> block (depth 1 returned split/deep routes) |
{schemaVersion, repository, path, depth, snapshots:[{repository, path, entries:[{name, path, kind}]}]} (structured at every depth, including depth 1) |
data mode emits the exact object above. json and pretty wrap it through
the standard success envelope. Text-oriented modes (compact, markdown,
refs, tty) fall back to the JSON value because the command supplies no
prose presentation override.
Scripting impact: any consumer parsing v0.2 raw ZRead text or the v0.2
split/deep tree shape must switch to the v1 structured fields. The base
scoutline.zai.* raw namespace remains available for callers that need the
legacy grammar; it is not wrapped in the v1 envelope.
Canonical repository paths
- Tree aliases omitted, empty,
/, or.normalize to the root path"". - File paths must be non-root; the root is invalid for
repo read. - Leading
./and leading/are accepted on File; leading and trailing/are stripped and repeated/collapses on both. - Actual
./..segments, backslashes, and ASCII control characters are rejected. Percent escapes (%XX) are never decoded — they remain literal.
--max-chars (deterministic, local)
--max-chars is never a summarization model call. It is presentation
projection applied to the normalized result after caching.
- Absent, zero, or negative → no truncation.
repo read→ truncatescontentwith the existing ellipsis rule; preserves the original length inoriginalContentLengthand setstruncated: true.repo search→ applies one total budget acrossexcerpts[].textin Provider order; the final retained excerpt is truncated and later excerpts are omitted.repo tree→ never character-limited.- Metadata, JSON envelopes, and Tree snapshots are not part of the budget.
Empty results
A future Provider Adapter may explicitly return an empty excerpts/entries
array when its own contract distinguishes a valid empty state. The Z.AI
Adapter requires at least one well-formed <excerpt> block per Search;
unwrapped text is malformed and surfaces as a normalized API_ERROR 502, not
as an empty success. An empty ZRead structure without entries is malformed
the same way.
Cache continuity
Repository results use a new key shape
v2.repository-exploration-<op>.<provider>.<credential-hash>.<request-hash>.json.
The credential hash is supplied by the Adapter (full lowercase SHA-256 hex
digest of the active credential) and is never re-hashed by cache code.
Legacy v0.2 Z.AI cache entries remain readable read-only: their key is
reconstructed from the same Adapter-resolved credential using the exact v0.2
algorithm, and a valid hit is written through to the new key. Old files are
never rewritten, migrated, or deleted. --no-cache performs no reads or
writes. Injected credentials drive the fingerprint and legacy-key
construction; ambient process.env is never reread.
Errors and lifecycle
Encoded MCP error envelopes are recognized before success parsing:
QUOTA_ERROR 429 (exhausted ZRead quota, code 1310) is terminal; transient
429/5xx and a malformed envelope retry once; auth 401/403 and other 4xx are
terminal. Raw Provider response bodies, reset metadata, and error texts are
discarded.
Transport close is best-effort and called once per constructed attempt. A successful operation does not become a failure when close rejects or times out, and a primary failure remains the outward failure when close also fails. Cache hits construct and close no transport.
Diagnostics inventory
sharedCapabilities and zaiOnlyCapabilities are derived from descriptor
metadata (intersection across built-in Providers; Z.AI minus the union of
the others). repository-exploration is therefore zaiOnlyCapabilities while
still participating in Provider selection. Doctor help names MiniMax as
unsupported for repo.
Non-goals
This release does not add MiniMax repository exploration, a Reader migration, automatic summarization, dynamic Provider loading, or an implicit Z.AI fallback for unsupported Providers. The P5 specialized Vision mappings remain independent and are not claimed complete here.
Reader (P7)
scoutline read participates in --provider selection. Z.AI advertises the
reader Capability and supplies it through the Z.AI Reader Adapter. MiniMax
does not advertise it; selecting MiniMax returns UNSUPPORTED_CAPABILITY
before descriptor configuration, Adapter creation, credential resolution for
use, cache identity, or transport construction, with no fallback to Z.AI.
Breaking data-mode migration (v0.2 → v1)
scoutline read returns schema-version-1 structured values in every
output mode. This is an intentional breaking change from the v0.2 raw content
string and the bare extract array:
| Read shape | v0.2 (legacy, now obsolete) | v1 (current) |
|---|---|---|
| Content read (default) | Raw content string | {schemaVersion, url, finalUrl, title, content, contentFormat, truncated, originalContentLength} |
Extract read (--extract <mode>) |
Bare JSON array of items | {schemaVersion, url, finalUrl, mode, items, truncated, originalItemCount} |
url is exactly what the caller passed; finalUrl is the URL the operation
actually fetched, which differs only when a Provider-side rewrite occurred
(e.g. gist.github.com/<id> → gist.github.com/<id>/raw). The v0.2 stderr
rewrite notice is gone — the signal now lives in finalUrl.
The four --extract modes (code, links, tables, headings) and the
shape of each item are unchanged from v0.2. Only the outer envelope changed
(bare array → schema-versioned object with items).
Output-mode behavior
| Mode | Content read | Extract read |
|---|---|---|
data |
The content-read envelope object | The extract-read envelope object |
json |
{success: true, data: <envelope>, timestamp} (indent 0) |
same |
pretty |
{success: true, data: <envelope>, timestamp} (indent 2) |
same |
compact |
The content string directly |
JSON fallback (the envelope object) |
markdown |
The content string directly |
JSON fallback |
refs |
The content string directly |
JSON fallback |
tty |
The content string directly |
JSON fallback |
compact, markdown, refs, and tty exist to give operators a prose form
for human reading. A content read supplies one (the page body). An extract
read does not — extracted items are data, not prose — so those modes fall
back to JSON. This is the deliberate asymmetry from repo, whose results are
always structured data.
Scripting impact: any consumer that did scoutline read URL > file.md,
scoutline read URL | jq -r .content, or scoutline read URL --extract code | jq -c .[] against v0.2 output must switch to the v1 envelope. --max-chars
still truncates the content-read content; it is ignored on extract reads
(extract reports originalItemCount instead). The deprecated
--full-envelope flag is silently accepted and ignored — the envelope is
always returned at v1.
URL rewrite as finalUrl
A Provider-side URL rewrite (today: gist URLs to their raw form) is recorded
as finalUrl in the v1 result. The rewrite is idempotent on URLs already
ending in /raw and preserves fragments. The v0.2 stderr notice is removed.
Cache namespace
Reader results share the partitioned cache namespace and use the
reader-fetch operation suffix:
v2.reader-reader-fetch.<provider>.<credential-hash>.<request-hash>.json
The Adapter resolves its credential once. The canonical request URL is the
rewritten URL so two requests that normalize to the same fetched URL share
one cache entry. Legacy v0.2 Z.AI entries are reconstructed from the same
Adapter-resolved credential using the exact v0.2 args-order algorithm and
remain read-only; a valid hit is written through to the new key; legacy files
are never migrated, rewritten, or deleted. --no-cache performs no reads or
writes. Injected credentials drive the fingerprint and legacy-key
construction; ambient process.env is never reread.
Errors and lifecycle
Encoded MCP error envelopes are recognized before success parsing. The same
taxonomy that governs repo applies: exhausted WebReader quota (code 1310
or explicit exhausted-limit meaning) surfaces as a normalized QUOTA_ERROR
429 and is terminal; transient 429/5xx and a malformed envelope retry once;
auth 401/403 and other 4xx are terminal. Raw Provider body, reset metadata,
and error-text strings are discarded. Transport close is best-effort and
called once per constructed attempt; a close failure never masks a primary
result. Cache hits construct and close no transport.
Diagnostics inventory
sharedCapabilities and zaiOnlyCapabilities are derived from descriptor
metadata. reader is therefore zaiOnlyCapabilities while still
participating in Provider selection, and Doctor help names MiniMax as
unsupported for read.
Non-goals
This release does not add a MiniMax Reader Adapter, automatic summarization,
removal of the deprecated --full-envelope flag, or a future --max-items
truncation policy for extract reads.
Repository Layout
├── docs/ # User, contributor, and maintainer guides
├── packages/scoutline/ # npm package source
├── skills/scoutline/ # Agent skill (SKILL.md)
└── .claude-plugin/ # Claude Code marketplace config
Documentation
Detailed guides are available in docs/:
Development
cd packages/scoutline
npm install
npm run build
npm test
node scripts/bench-tools.mjs
Contributing
See CONTRIBUTING.md for development setup and guidelines.
License
MIT - see LICENSE.