/SKILL.md
# blq MCP Tools - Agent Usage Guide blq captures, stores, and queries build/test logs. Both humans (via CLI) and agents (via MCP) share the same database, enabling collaborative debugging workflows. **Documentation:** https://blq-cli.readthedocs.io/en/latest/ ## Key Concept: Shared State The blq database (`.lq/blq.duckdb`) is shared between CLI and MCP: ``` Human runs: blq run build → stored in .lq/ Agent queries: blq.events(...) → reads from .lq/ Agent runs: blq.
npx skillsauth add teaguesterling/blq-cli blq-cliInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
blq captures, stores, and queries build/test logs. Both humans (via CLI) and agents (via MCP) share the same database, enabling collaborative debugging workflows.
Documentation: https://blq-cli.readthedocs.io/en/latest/
The blq database (.lq/blq.duckdb) is shared between CLI and MCP:
Human runs: blq run build → stored in .lq/
Agent queries: blq.events(...) → reads from .lq/
Agent runs: blq.run(command="test") → stored in .lq/
Human queries: blq errors → reads from .lq/
This means:
blq run build in their terminal, then ask the agent to analyze the errorsblq errors or blq historyblq.commands()
If this returns commands, you're ready. If it returns an empty list or error, the project may need initialization (user should run blq init).
blq.commands()
# Returns: {"commands": [{"name": "build", "cmd": "make -j8"}, {"name": "test", "tpl": "pytest {path}", "defaults": {"path": "tests/"}}]}
blq.status()
# Returns status of each registered command's last run
Bash gives you raw text:
src/main.c:42:15: error: expected ';' before '}' token
blq gives you structured data:
{
"ref": "build:1:1",
"ref_file": "src/main.c",
"ref_line": 42,
"ref_column": 15,
"message": "expected ';' before '}' token",
"severity": "error",
"fingerprint": "gcc_error_a1b2c3"
}
blq parses 60+ log formats automatically:
Every run is stored with git context (commit, branch, dirty state). Compare runs to find regressions:
blq.diff(run1=5, run2=6)
# Returns: {"fixed": [...], "new": [...], "unchanged": [...]}
You may not have access to the project's source files. blq stores:
Use inspect() to understand errors without reading source files directly.
blq.status() # Overview of all sources
blq.commands() # What commands are registered
If you need fresh results:
blq.run(command="build") # Run registered command
blq.run(command="test")
Or analyze existing results (from user's CLI runs):
blq.events(severity="error") # Recent errors
blq.history() # Past runs
# Quick view with log context around each error
blq.info(ref="build:3", context=5)
# Returns compact format:
# {
# "run_ref": "build:3",
# "status": "FAIL",
# "error_count": 2,
# "errors_by_category": {"lint": 1, "test": 1},
# "events": [
# {"ref": "3:1", "location": "src/main.py:42", "context": "...>>> 42 | error line..."},
# {"ref": "3:2", "location": "tests/test_main.py:15", "context": "..."}
# ]
# }
# Or get full event details for deeper investigation
blq.events(severity="error", limit=10) # Get error list with all fields
blq.inspect(ref="build:3:2") # Full details with log + source context
blq.output(run_id=3, tail=50) # Raw output if parsing missed something
blq.diff(run1=3, run2=4) # What changed between runs?
| Format | Example | Meaning |
|--------|---------|---------|
| tag:serial | build:3 | Run #3 (globally), tagged "build" |
| tag:serial:event | build:3:2 | Event #2 in run #3 |
| serial:event | 5:2 | Event #2 in run #5 (no tag) |
| Tool | Purpose |
|------|---------|
| run(command, ...) | Run a registered command (supports batch mode with commands param) |
| status() | Quick overview of all sources |
| commands() | List registered commands |
| info(ref, context) | Detailed info for a run (omit ref for most recent) |
| history(limit, source) | Run history |
run Tool OutputThe run tool returns a concise response optimized for token efficiency:
blq.run(command="test")
# Returns:
{
"run_ref": "test:47",
"cmd": "pytest tests/ -v",
"status": "FAIL",
"exit_code": 1,
"summary": {"error_count": 2, "warning_count": 5},
"errors": [...], # Only if errors exist
"preview": [...] # Head + tail of output on failure (see below)
}
Preview behavior:
output(run_id=N) to see the full loginfo Tool with context=NWhen you pass context=N to info, you get a compact event format optimized for quick understanding:
blq.info(ref="test:47", context=3)
# Returns:
{
"run_ref": "test:47",
"status": "FAIL",
"error_count": 2,
"errors_by_category": {"test": 2},
"events": [
{
"ref": "47:242", # Short format (no tag prefix)
"location": "tests/test_main.py:251", # Combined file:line
"context": " 248 | ...PASSED...\n>>> 251 | ...FAILED...\n 252 | ..."
}
],
"summary": {
"by_fingerprint": [
{"fingerprint": "abc123", "count": 2, "example_message": "AssertionError"}
],
"by_file": [
{"file": "tests/test_main.py", "count": 2}
],
"affected_commits": [
{"hash": "abc1234", "author": "[email protected]", "message": "Refactor tests"}
]
}
}
For failed runs, info includes an aggregated summary with:
by_fingerprint: Error counts grouped by fingerprint (for deduplication)by_file: Error counts grouped by fileaffected_commits: Recent git commits that touched files with errorsThis is the recommended starting point - you can see errors with their surrounding log context in one call. Use inspect(ref) only when you need additional details like source code context or error codes.
| Tool | Purpose |
|------|---------|
| events(severity, limit, run_id, ...) | Get events (use severity="error" for errors, severity="warning" for warnings) |
| inspect(ref, lines, ...) | Full details with log/source context and optional enrichment (git, fingerprint) |
| output(run_id, stream, tail, head, grep, context, lines, debug_formats) | Raw stdout/stderr with search and filtering |
| diff(run1, run2) | Compare errors between runs |
| query(sql, filter, limit) | Query with SQL or filter expressions (e.g., filter="severity=error") |
output ToolThe output tool retrieves raw build output with optional search and filtering:
# Basic usage
blq.output(run_id=3) # Full output
blq.output(run_id=3, tail=50) # Last 50 lines
blq.output(run_id=3, head=20) # First 20 lines
blq.output(run_id=3, stream="stderr") # Only stderr
# Search with grep
blq.output(run_id=3, grep="error|warning") # Find matches
blq.output(run_id=3, grep="FAIL", context=3) # With 3 lines context
blq.output(run_id=3, grep="undefined", context=5) # Find undefined refs
# Line selection (requires read_lines extension)
blq.output(run_id=3, lines="100-200") # Lines 100-200
blq.output(run_id=3, lines="42 +/-5") # Lines 37-47 (around line 42)
# Format debugging (shows which parsers were tried)
blq.output(run_id=3, debug_formats=True)
| Parameter | Description |
|-----------|-------------|
| run_id | Run serial number or ref (e.g., 3 or "build:3") |
| stream | Filter by stream: "stdout", "stderr", or "combined" (default) |
| tail | Show only last N lines |
| head | Show only first N lines |
| grep | Regex pattern to search for in output |
| context | Lines of context around grep matches (default: 0) |
| lines | Line spec like "100-200" or "42 +/-5" (requires read_lines) |
| debug_formats | Show format detection diagnosis (which parsers matched)
queryThe filter parameter supports simple expressions:
key=value - exact match (severity=error)key=v1,v2 - multiple values (severity=error,warning)key~pattern - contains (ref_file~test)key!=value - not equal (tool_name!=mypy)Multiple filters are AND'd together (space or comma separated):
blq.query(filter="severity=error ref_file~test") # Errors in test files
blq.query(filter="tool_name=pytest category=test") # pytest test failures
inspectThe inspect tool supports optional enrichment to provide deeper context:
| Parameter | Description |
|-----------|-------------|
| include_source_context | Source file lines around error location (default: true) |
| include_git_context | Git blame and recent commits for the file |
| include_fingerprint_history | Error occurrence history and regression detection |
# Basic inspect (log + source context)
blq.inspect(ref="build:1:3")
# With git context (who last modified, recent commits)
blq.inspect(ref="build:1:3", include_git_context=True)
# With fingerprint history (is this error new or recurring?)
blq.inspect(ref="build:1:3", include_fingerprint_history=True)
# Full enrichment
blq.inspect(
ref="build:1:3",
include_source_context=True,
include_git_context=True,
include_fingerprint_history=True
)
# Batch mode with enrichment
blq.inspect(
ref="build:1:1",
refs=["build:1:1", "build:1:2", "build:1:3"],
include_git_context=True
)
Git context shows who last modified the error location and recent file changes:
{
"git_context": {
"file": "src/main.py",
"line": 42,
"blame": {"author": "[email protected]", "commit": "abc1234"},
"recent_commits": [{"hash": "abc1234", "message": "Refactor data processing"}]
}
}
Fingerprint history tracks error occurrences and detects regressions:
{
"fingerprint_history": {
"fingerprint": "7f3a2b1c4d5e...",
"first_seen": {"run_ref": "build:1"},
"occurrences": 4,
"is_regression": true
}
}
| Tool | Purpose |
|------|---------|
| report(ref, baseline, ...) | Generate markdown report (for PRs, summaries) |
| ci_check(baseline, fail_on_any) | Check for regressions vs baseline |
| ci_generate(commands, shell) | Generate standalone CI shell scripts |
report ToolGenerates a formatted markdown report suitable for PR descriptions or CI summaries:
# Report for latest run
blq.report()
# Report with baseline comparison
blq.report(baseline="main")
# Summary only (no individual error details)
blq.report(summary_only=True, warnings=True)
Returns {"report": "# Build Report...", "run_id": 5, "total_errors": 3, ...}
ci_check ToolChecks for regressions by comparing error fingerprints against a baseline:
# Auto-detect baseline (tries main, then master)
blq.ci_check()
# Compare against specific branch
blq.ci_check(baseline="main")
# Fail on any errors (no baseline needed)
blq.ci_check(fail_on_any=True)
Returns {"status": "OK"|"FAIL", "has_new_errors": true, "new_count": 2, ...}
ci_generate ToolGenerates shell scripts from registered commands for CI environments without blq:
# Generate scripts for all commands
blq.ci_generate()
# Specific commands only
blq.ci_generate(commands=["build", "test"])
# Different shell
blq.ci_generate(shell="sh")
Returns script content (not written to disk) so you can review or save as needed.
| Tool | Purpose |
|------|---------|
| register_command(name, cmd, run_now) | Register and optionally run a command |
| unregister_command(name) | Remove a command |
| clean(mode, confirm, days) | Database cleanup (data, prune, schema, full) |
Several tools support batch operations via additional parameters:
# Run multiple commands in sequence
blq.run(command="ignored", commands=["build", "test"])
# Get events from multiple runs
blq.events(run_ids=[1, 2, 3], severity="error")
# Inspect multiple events at once
blq.inspect(ref="build:1:1", refs=["build:1:1", "build:1:2", "build:1:3"])
If a project doesn't have commands registered, help the user set them up:
blq.register_command(
name="build",
cmd="make -j8",
description="Build the project"
)
blq.register_command(
name="test",
cmd="pytest tests/ -v",
description="Run test suite"
)
register_command is idempotent for same name + same command:
# First call: registers the command
blq.register_command(name="build", cmd="make -j8")
# → Registers, auto-detects format (e.g., "gcc")
# Second call: detects identical command, returns existing (no error)
blq.register_command(name="build", cmd="make -j8")
# → Returns existing command
# Different name, same command: returns error (use force=True to override)
blq.register_command(name="compile", cmd="make -j8")
# → Error: "Command already registered as 'build'"
Use run_now=True to register and immediately run:
# Register (if needed) and run in one call
blq.register_command(
name="test",
cmd="pytest tests/ -v",
run_now=True
)
This is the recommended pattern for agents - it ensures clean refs while being efficient.
Benefits of registration:
build:1:3 vs the full command string)Some commands use templates with {param} placeholders instead of fixed commands. These appear in commands() output with tpl instead of cmd:
blq.commands()
# Returns:
{
"commands": [
{"name": "build", "cmd": "make -j8"},
{"name": "test", "tpl": "pytest {path} {flags}", "defaults": {"path": "tests/", "flags": "-v"}}
]
}
Running template commands:
Use the args parameter to provide values for template placeholders:
# Run with defaults (pytest tests/ -v)
blq.run(command="test")
# Override a parameter
blq.run(command="test", args={"path": "tests/unit/"})
# → pytest tests/unit/ -v
# Override multiple parameters
blq.run(command="test", args={"path": "tests/integration/", "flags": "-vvs --tb=short"})
# → pytest tests/integration/ -vvs --tb=short
Required parameters:
If a template has parameters without defaults, they must be provided:
# Given: {"name": "test-file", "tpl": "pytest {file} -v"}
blq.run(command="test-file")
# → Error: Missing required param 'file'
blq.run(command="test-file", args={"file": "test_main.py"})
# → pytest test_main.py -v
Registering template commands:
Use tpl instead of cmd, and provide defaults for optional parameters:
blq.register_command(
name="test",
tpl="pytest {path} {flags}",
defaults={"path": "tests/", "flags": "-v"},
description="Run tests"
)
Or via CLI:
blq commands register test --tpl "pytest {path} {flags}" --defaults path=tests/ --defaults flags=-v
Or by editing .lq/commands.toml:
[commands.test]
tpl = "pytest {path} {flags}"
defaults = { path = "tests/", flags = "-v" }
description = "Run tests"
Do NOT use shell pipes, redirects, or command chains in run or exec commands.
Commands like exec(command="pytest tests/ | tail -20") will be rejected because
commands are executed directly, not through a shell.
# Step 1: Run the command
result = blq.run(command="test")
# Step 2: Filter the captured output using output()
blq.output(run_id=47, tail=20) # Last 20 lines
blq.output(run_id=47, head=10) # First 10 lines
blq.output(run_id=47, grep="FAILED", context=3) # Search with context
blq.output(run_id=47, grep="error|warning") # Regex search
blq.output(run_id=47, lines="100-200") # Specific line range
output() tool handles grep, context lines, and line selection nativelyFor advanced use cases that genuinely need shell interpretation:
blq.exec(command="echo hello && echo world", shell=True)
This bypasses pipe detection and passes the command to a shell. Prefer the two-step workflow above unless you have a specific reason to use shell syntax.
status() or commands() to understand current stateinfo(context=5) to see errors with surrounding log context in one calldiff() after fixes to verify no regressionsinspect() only when you need additional details (source context, error codes)output() with grep/tail/head to filter captured logs| tail, | grep, > file)events() then inspect() for each error - use info(context=N) insteadblq.clean(mode="data", confirm=True) # Clear runs, keep commands
blq.clean(mode="prune", days=30, confirm=True) # Remove data older than 30 days
blq.clean(mode="schema", confirm=True) # Recreate database
blq.clean(mode="full", confirm=True) # Full reinitialize
# User ran: blq run build (from terminal)
# Agent is asked to help with the errors
# 1. See what happened with context around each error
blq.info(ref="build:5", context=3)
# → {
# "run_ref": "build:5",
# "status": "FAIL",
# "error_count": 3,
# "errors_by_category": {"compile": 3},
# "events": [
# {"ref": "5:1", "location": "src/main.c:42", "context": "...>>> 42 | error..."},
# ...
# ],
# "summary": {
# "by_fingerprint": [...],
# "by_file": [{"file": "src/main.c", "count": 3}],
# "affected_commits": [{"hash": "abc1234", "message": "Refactor core"}]
# }
# }
# 2. If you need more details on a specific error
blq.inspect(ref="build:5:1")
# → Full error details including message, code, log_context, source_context
# 3. After user fixes the code, they run: blq run build
# Agent verifies the fix:
blq.diff(run1=5, run2=6)
# → {"fixed": 3, "new": 0} - Success!
In addition to tools, blq provides read-only resources:
| Resource | Description |
|----------|-------------|
| blq://guide | This guide |
| blq://status | Current status summary (JSON) |
| blq://errors | Recent errors (JSON) |
| blq://errors/{serial} | Errors for a specific run |
| blq://warnings | Recent warnings (JSON) |
| blq://warnings/{serial} | Warnings for a specific run |
| blq://context/{ref} | Log context around an event |
| blq://commands | Registered commands (JSON) |
Resources are useful for embedding data in prompts or quick reads without calling tools.
If blq's Claude Code hooks are installed (via blq hooks install claude-code), the agent will receive suggestions when Bash commands match registered blq commands:
Tip: Use blq MCP tool run(command="test") instead.
Using the blq MCP run tool parses output into structured events,
reducing context usage. Query errors with events() or inspect().
This helps guide agents toward using blq's structured tools instead of raw Bash output.
blq provides structured access to build/test results that both humans and agents can query. Use the MCP tools to:
Always prefer blq tools over Bash for build/test/lint operations.
tools
Use when work should span one or more detached tasks but still behave like one job with a single owner context. TaskFlow is the durable flow substrate under authoring layers like Lobster, ACPX, plugins, or plain code. Keep conditional logic in the caller; use TaskFlow for flow identity, child-task linkage, waiting state, revision-checked mutations, and user-facing emergence.
tools
# Lobster Lobster executes multi-step workflows with approval checkpoints. Use it when: - User wants a repeatable automation (triage, monitor, sync) - Actions need human approval before executing (send, post, delete) - Multiple tool calls should run as one deterministic operation ## When to use Lobster | User intent | Use Lobster? | | ------------------------------------------------------ | --------------------------
tools
# Lobster Lobster executes multi-step workflows with approval checkpoints. Use it when: - User wants a repeatable automation (triage, monitor, sync) - Actions need human approval before executing (send, post, delete) - Multiple tool calls should run as one deterministic operation ## When to use Lobster | User intent | Use Lobster? | | ------------------------------------------------------ | --------------------------
tools
A CLI tool for making authenticated requests to the X (Twitter) API. Use this skill when you need to post tweets, reply, quote, search, read posts, manage followers, send DMs, upload media, or interact with any X API v2 endpoint.