Skip to main content

DevQL GraphQL

DevQL is exposed as a GraphQL-compatible schema. The CLI, dashboard, and HTTP/WebSocket clients all execute the same schema, so there is one typed contract for queries, mutations, subscriptions, and capability-pack extensions.

Surface Summary

When the Bitloops daemon is running, DevQL exposes these routes:

RouteMethodPurpose
/devqlPOSTGraphQL queries and mutations
/devqlGETDevQL Explorer UI
/devql/playgroundGETDevQL Explorer UI
/devql/sdlGETGenerated schema SDL
/devql/wsWebSocketGraphQL subscriptions

The checked-in schema snapshot lives at bitloops/schema.graphql. The canonical runtime schema is whatever GET /devql/sdl returns.

CLI Query Modes

bitloops devql query executes against the local Bitloops daemon. It supports two input styles:

  • DevQL DSL pipelines when the query contains ->
  • Raw GraphQL by default for any other input

--graphql remains available as an explicit override when you want to force raw GraphQL execution.

# DSL pipeline compiled to GraphQL before execution
bitloops devql query 'repo("bitloops")->artefacts(kind:"function")->limit(5)'

# Raw GraphQL is the default when there is no `->`
bitloops devql query '{ repo(name: "bitloops") { artefacts(first: 5) { edges { node { path symbolFqn canonicalKind } } } } }'

# Emit compact JSON instead of pretty JSON or table output
bitloops devql query --compact '{ health { relational { backend connected } } }'

Without --compact, raw GraphQL output is printed as formatted JSON. DSL queries keep the CLI table rendering where that still fits the result shape.

Connection fields support both forward and reverse cursor pagination:

  • Forward: first with optional after
  • Reverse: last with optional before

Do not mix the two modes in the same field call.

Query Examples

Repository artefacts

{
repo(name: "bitloops") {
artefacts(first: 10, filter: { kind: FUNCTION }) {
edges {
node {
path
symbolFqn
canonicalKind
startLine
endLine
}
}
}
}
}

Monorepo project scope

{
repo(name: "bitloops") {
project(path: "bitloops/src/graphql") {
artefacts(first: 10) {
edges {
node {
path
symbolFqn
}
}
}
}
}
}

Historical query with asOf

{
repo(name: "bitloops") {
asOf(input: { ref: "main" }) {
artefacts(first: 5, filter: { kind: FUNCTION }) {
edges {
node {
path
symbolFqn
}
}
}
}
}
}

Knowledge and capability-pack enrichments

{
repo(name: "bitloops") {
knowledge(first: 10, provider: JIRA) {
edges {
node {
title
externalUrl
latestVersion {
title
bodyPreview
}
}
}
}
}
}
{
repo(name: "bitloops") {
project(path: "bitloops/src") {
tests(first: 10, filter: { kind: FUNCTION }, minConfidence: 0.7) {
artefact {
filePath
name
}
summary {
totalCoveringTests
}
}
coverage(first: 10, filter: { kind: FUNCTION }) {
artefact {
filePath
name
}
summary {
uncoveredLineCount
uncoveredBranchCount
}
}
}
}
}

Reverse pagination

{
repo(name: "bitloops") {
commits(last: 10, before: "commit-sha-cursor") {
pageInfo {
hasNextPage
hasPreviousPage
}
edges {
node {
sha
commitMessage
}
}
}
}
}

Mutations

The CLI write commands now execute GraphQL mutations in-process:

  • bitloops devql initinitSchema
  • bitloops devql ingestingest
  • bitloops devql knowledge addaddKnowledge
  • bitloops devql knowledge associateassociateKnowledge
  • bitloops devql knowledge refreshrefreshKnowledge

Example mutation:

mutation Ingest($input: IngestInput!) {
ingest(input: $input) {
success
checkpointsProcessed
eventsInserted
artefactsUpserted
}
}
{
"input": {
"init": true,
"maxCheckpoints": 200
}
}

Capability-pack migrations are also exposed through GraphQL:

mutation {
applyMigrations {
success
migrationsApplied {
packId
migrationName
appliedAt
}
}
}

Subscriptions

DevQL currently exposes two subscription fields:

  • checkpointIngested(repoName: String!)
  • ingestionProgress(repoName: String!)

Example subscription:

subscription IngestProgress {
ingestionProgress(repoName: "bitloops") {
phase
checkpointsProcessed
checkpointsTotal
currentCommitSha
}
}

Use the WebSocket endpoint at /devql/ws. The DevQL Explorer page is already configured to use that endpoint.

SDL Export And Versioning

The schema is versioned in two places:

  • Generated at runtime from the async-graphql schema
  • Checked in as bitloops/schema.graphql for review and client code generation

Export the current schema snapshot from the repository root with:

cargo run --manifest-path bitloops/Cargo.toml --example export-schema > bitloops/schema.graphql

The test suite asserts that the checked-in snapshot still matches the runtime SDL.

Capability-Pack Extension Points

DevQL exposes capability-pack functionality in three ways:

  • Typed fields such as knowledge, tests, coverage, and clones
  • Generic extension(stage:, args:, first:) fields on Project and Artefact
  • applyMigrations for capability-pack schema migrations

extension() expects a stage name plus an optional JSON object whose values are strings, numbers, booleans, or null. The GraphQL extension() adapter forwards those scalar values to the stage without stringifying them. Unsupported or ambiguous stage names fail before execution.

Error Codes And Limits

DevQL currently emits these structured GraphQL error codes from resolver code:

CodeMeaning
BAD_USER_INPUTInvalid field arguments, invalid temporal scope input, invalid references, or unsupported combinations
BAD_CURSORInvalid pagination cursor
BACKEND_ERRORBackend configuration, execution, migration, provider, or serialisation failures

The schema also enforces global limits:

  • Maximum query depth: 16
  • Maximum query complexity: 256

Depth and complexity rejections come from the GraphQL runtime and may not include a custom extensions.code.

Testing And Migration Notes

GraphQL accuracy is covered directly in the repository:

  • bitloops/src/api/tests.rs covers routes, SDL, mutations, subscriptions, limits, and dashboard wrappers
  • bitloops/tests/graphql/verification.rs checks end-to-end CLI parity between DSL and raw GraphQL
  • bitloops/schema.graphql is asserted against the runtime schema

The dashboard still serves legacy /api/* routes for compatibility, but those wrappers now execute the DevQL GraphQL schema internally rather than maintaining a separate SQL-style read path.