cirql Language Specification

Version: 0.1.0-draft Status: Pre-implementation Draft Date: 2026-03-14


1. Abstract

cirql is a domain-specific language (DSL) and runtime for composing JSON data pipelines. It combines jq-style data transformation with pluggable source stages — including GraphQL queries, REST/HTTP endpoints, local files, and stdin — enabling users to chain data sources, post-process results, propagate variables between stages, and dynamically reshape data, all from an interactive REPL or CLI tool called cq.

The pipeline engine operates on JSON. Source stages (query, http, file, stdin) produce JSON; transform stages (map, filter, reduce, sort, flatMap, limit, uniq) reshape it. Any source that produces JSON can feed into the same pipeline.

The cirql service at api.cirql.io provides a hosted execution environment for cirql pipelines, enabling team collaboration, saved pipelines, and managed endpoint connections.


2. Feasibility Assessment

2.1 Technical Feasibility

Rating: High

Each component of cirql maps to well-understood engineering problems:

ComponentFeasibilityRationale
Parser / ASTProvenGo has excellent parser tooling (participle, pigeon, hand-rolled recursive descent). Pipeline syntax is keyword-dispatched and unambiguous.
Expression evaluatorProvenjq-style field access and arithmetic are straightforward to implement. Libraries like govaluate handle expression evaluation. A custom evaluator for .field access + basic operators is ~500 LOC.
HTTP / file / stdin sourcesProvenHTTP fetching is trivial in Go (net/http). File and stdin reading are standard library operations. JSON decoding with encoding/json is mature.
GraphQL executionProvenmachinebox/graphql and hasura/go-graphql-client are mature Go clients. This is one of several source stage implementations.
Pipeline runtimeProvenSequential stage execution with []map[string]any is a standard pattern. Variable propagation is map-threading.
REPL / CLIProvenGo has liner, readline, bubbletea for interactive CLIs. Schema introspection for autocomplete is a solved problem via the __schema query.
Query optimizationModerateQuery fusion and batching require dependency analysis. This is non-trivial but well-studied in database query planning literature. Can be deferred to later milestones.
Dynamic query generationModerateGenerating GraphQL from runtime data requires careful template handling and injection prevention. Achievable with AST-level query construction rather than string interpolation.

2.2 Language Design Feasibility

The pipeline operator | is syntactically unambiguous because every stage begins with a distinguishing token that enables simple prefix-based dispatch. In practice this is either a keyword (query, http, file, stdin, map, filter, etc.) or a leading { for inline query blocks. The parser can cleanly separate:

The main design risk is type inference across stages: ensuring that field references in map/filter expressions match the shape of the previous stage’s output. This can be addressed with runtime checking initially, with optional static analysis later.

2.3 Implementation Estimate

A minimal viable cq REPL with http/file/stdin sources, basic map/filter/reduce, and JSON output is achievable in ~3,000-5,000 lines of Go. The full system with GraphQL support, optimization, and multi-source pipelines is ~10,000-15,000 lines.


3. Competitive Landscape

3.1 Direct Competitors

No direct competitor exists that combines all of: pluggable JSON sources (GraphQL, REST, files, stdin), jq-style pipeline composition, variable propagation between stages, and a dedicated REPL. This is cirql’s primary opportunity.

Notably, Hasura’s own RFC #10058 explicitly requests query chaining — the ability to use output from one query as input to the next. This validates the demand for exactly what cirql provides, but as a client-side tool that works against any endpoint.

3.2 Adjacent Tools by Category

GraphQL Federation / Gateway Platforms

ToolWhat It DoesHow cirql Differs
Apollo GraphOS / RouterEnterprise API orchestration. Composes subgraphs into a federated supergraph via a Rust runtime.Server-side gateway for API producers. cirql is a client-side tool for API consumers. No jq-style post-processing or pipeline chaining.
Grafbase GatewayHigh-performance federation gateway (Rust). Lowest memory footprint among gateways.Same category as Apollo — infrastructure-level federation, not a query composition DSL.
WunderGraph / CosmoBFF framework. Introspects GraphQL, REST, gRPC, Kafka APIs into a unified schema. Go-based, Apache 2.0.Build-time schema composition with code generation. cirql is runtime, ad-hoc, interactive.
HasuraInstant GraphQL API over databases. Has an open RFC for query chaining (#10058) but it is not implemented.Server-side engine. cirql delivers what their RFC requests — as a client-side tool.
StepZen (IBM)Declarative GraphQL composition using @rest, @dbquery, @graphql directives.Schema-level declarative composition. No runtime post-processing.
BrambleLightweight federated GraphQL gateway in Go (MIT).Gateway-level federation. No query scripting.

GraphQL CLI Tools

ToolWhat It DoesHow cirql Differs
graphqurl (Hasura)“curl for GraphQL.” CLI (gq) for executing queries with autocomplete and subscriptions.Single-query execution only. No pipeline chaining, no post-processing, no variable propagation. cirql is awk + xargs for GraphQL; graphqurl is curl.
GraphQL CLI (The Guild)Plugin-based CLI for codegen, schema management, project scaffolding.Development tooling, not a query execution/composition tool.
gql-cli (Python)Python CLI for executing GraphQL queries. Supports stdin piping.Single-query execution. No built-in pipeline composition or transformation DSL.

JSON Processing Tools

ToolWhat It DoesHow cirql Differs
jq / gojq / jaqJSON processing with map/filter/reduce and pipes.No built-in data fetching. Requires separate curl for HTTP and manual bash glue to chain requests. cirql unifies fetching and transforming in one expression.
JSONataJSON query and transformation language (XPath-inspired).Same gap as jq — transforms only, no built-in data fetching or variable propagation between stages.
emutoSmall language inspired by both jq and GraphQL for manipulating JSON.Uses GraphQL syntax to query JSON files, not to compose API calls or chain data sources.
fxInteractive JSON processing with JavaScript expressions.Transforms only, no built-in data fetching or pipeline chaining.
xargs + curlShell pipeline: curl | jq | xargs curl.Fragile shell quoting, no variable propagation, no type safety. cirql replaces the entire curl | jq | xargs curl pattern with a single pipeline.

GraphQL Query Composition Libraries

ToolWhat It DoesHow cirql Differs
Relay CompilerAhead-of-time compilation of colocated fragments into optimized queries. Fragment arguments enable scoped variable passing.Build-time, React-specific, fragment-level. cirql composes entire queries at runtime.
Apollo Client Document TransformsChainable document transformation pipeline within Apollo Client.Client-side JavaScript, transforms the query document (not results), tightly coupled to Apollo.
AWS AppSync Pipeline ResolversServer-side pipeline resolvers where each stage passes state to the next.Same pipeline concept but server-side only, requires AppSync infrastructure and VTL/JS resolver code. cirql works against any endpoint.

Data Pipeline Tools

ToolWhat It DoesHow cirql Differs
DagsterData orchestration platform (created by GraphQL’s creator). Uses GraphQL as its control API.Uses GraphQL to control data pipelines, not to be a pipeline language.
GROQ (Sanity)Content query language with pipeline-like syntax.Sanity-specific, not GraphQL-compatible. Similar philosophy but platform-locked.

3.3 Gap Analysis

No existing tool combines all of cirql’s capabilities:

CapabilitygraphqurljqApolloWunderGraphAppSync PipelinesRelaycirql
GraphQL query executionYesNoYesYesYesYesYes
Multi-query chainingNoNoNoBuild-timeServer-sideNoYes
Variable propagation between stagesNoN/ANoBuild-timeServer-sideFragments onlyYes
jq-style post-processingNoYesNoTypeScriptVTL/JSNoYes
map/filter/reduce on resultsNoYesNoTypeScriptLimitedNoYes
Dynamic query generationNoNoNoCodegenNoCompilerYes
CLI / REPLYesYesRover (schema only)NoNoNoYes
Works against any endpointYesN/AOwn gatewayOwn gatewayAppSync onlyReact appsYes
Non-GraphQL sources (REST, file, stdin)Novia curlNoREST stitchingNoNoYes
No infrastructure requiredYesYesNoNoNoBuild stepYes

3.4 Competitive Positioning

cirql occupies a unique position at the intersection of:

                    CLI / Scriptable
                         │
                    ┌────┼────┐
                    │  cirql  │
                    └────┼────┘
                         │
  Any JSON source ───────┼────── Pipeline composition
  (GraphQL, REST,        │
   files, stdin)    Data transforms

The closest workflow today requires: curljq → manual variable extraction → xargs → another curl → more jq. cirql collapses this entire pattern into a single composable expression that works with any JSON-producing source.

3.5 Competitive Risks


4. Utility Assessment

4.1 Highest-Value Use Cases

  1. API exploration and prototyping — Developers exploring unfamiliar APIs (REST or GraphQL) can iteratively fetch, inspect, and refine — faster than any GUI tool.

  2. Data extraction pipelines — Pull data from APIs or files, transform it, and output JSON/CSV for analysis. Replaces ad-hoc scripts.

  3. REST API scripting — Pipe REST endpoints through transforms without writing bash glue. Replace curl | jq | xargs curl with a single cirql pipeline.

  4. Cross-source queries — Fetch users from a REST API, then query each user’s details via GraphQL, then aggregate. Multi-hop, multi-source patterns are natural in cirql.

  5. CI/CD and automation — Scriptable API queries for deployment checks, data validation, monitoring dashboards.

  6. API testing — Chain sources to test workflows (create user → fetch user → update user → verify).

  7. Microservice orchestration from the CLI — When you have multiple services (GraphQL, REST, or both) and need to compose calls across them ad-hoc, without deploying a gateway.

4.2 Target Audience

AudienceNeedcirql Value
Backend developersExplore and debug APIsFast, scriptable, no GUI needed
DevOps / SREAutomate API-based checksPipeable, composable, CI-friendly
Data engineersExtract and transform API/file dataPipeline semantics match mental model
API consumersNavigate complex APIsIntrospection + autocomplete + chaining
Shell power usersCompose multi-step API callsReplaces curl|jq|xargs chains with a single expression
QA engineersTest multi-step API workflowsPipeline = test scenario

4.3 Why Now


5. Language Specification

5.1 Grammar (EBNF)

pipeline      = stage { "|" stage } ;
stage         = query_stage | http_stage | file_stage | stdin_stage
              | map_stage | filter_stage | reduce_stage
              | sort_stage | flatmap_stage | limit_stage | uniq_stage ;

query_stage   = [ "query" ] query_body [ "(" var_bindings ")" ] ;
query_body    = "{" selection_set "}" ;
selection_set = field { field } ;
field         = name [ "(" arguments ")" ] [ "{" selection_set "}" ] ;
arguments     = argument { "," argument } ;
argument      = name ":" value ;
value         = variable | string | number | boolean | null
              | "[" [ value { "," value } ] "]"
              | "{" [ name ":" value { "," name ":" value } ] "}" ;
variable      = "$" name ;
header_value  = string | variable ;

http_stage    = "http" ( string | variable ) [ http_options ] ;
http_options  = "(" http_opt { "," http_opt } ")" ;
http_opt      = "method" ":" string
              | "headers" ":" "{" [ name ":" header_value { "," name ":" header_value } ] "}"
              | "body" ":" ( string | variable ) ;

file_stage    = "file" string ;

stdin_stage   = "stdin" ;

var_bindings  = var_binding { "," var_binding } ;
var_binding   = "$" name "=" expr ;

map_stage     = "map" "{" mapping { "," mapping } "}" ;
mapping       = name ":" expr ;

filter_stage  = "filter" expr ;
reduce_stage  = "reduce" reduce_op [ "(" expr ")" ] ;
reduce_op     = "count" | "sum" | "min" | "max" | "avg" | "first" | "last"
              | "group_by" | "collect" ;
              (* group_by(expr) returns an Object keyed by the expr value,
                 each value being a List of matching objects.
                 collect(expr) returns a List of the expr value from each object.
                 first/last return the first/last object in the result set. *)

sort_stage    = "sort" expr [ "asc" | "desc" ] ;
flatmap_stage = "flatMap" "{" mapping { "," mapping } "}" ;
limit_stage   = "limit" integer ;
uniq_stage    = "uniq" [ expr ] ;

expr          = or_expr ;
or_expr       = and_expr { "||" and_expr } ;
and_expr      = cmp_expr { "&&" cmp_expr } ;
cmp_expr      = add_expr { ( "==" | "!=" | ">" | "<" | ">=" | "<=" ) add_expr } ;
add_expr      = mul_expr { ( "+" | "-" ) mul_expr } ;
mul_expr      = unary_expr { ( "*" | "/" | "%" ) unary_expr } ;
unary_expr    = "!" unary_expr | primary ;
primary       = field_access | variable | literal | func_call | "(" expr ")" ;
field_access  = "." name { "." name | "[" "]" } ;
literal       = string | number | boolean | null ;
func_call     = name "(" [ expr { "," expr } ] ")" ;

name          = letter { letter | digit | "_" } ;
string        = '"' { char } '"' ;
number        = [ "-" ] digit { digit } [ "." digit { digit } ] ;
boolean       = "true" | "false" ;
null          = "null" ;
integer       = digit { digit } ;

5.2 Type System

cirql operates on a dynamic type system with the following value types:

TypeDescriptionExample
NullAbsence of valuenull
BoolBooleantrue, false
Int64-bit integer42, -1
Float64-bit float3.14, -0.5
StringUTF-8 string"hello"
ListOrdered collection[1, 2, 3]
ObjectKey-value map{"id": 1, "name": "Ada"}

Type coercion rules:

5.3 Pipeline Semantics

A pipeline is an ordered sequence of stages. Data flows left to right through the | operator.

Data model: The fundamental data unit flowing between stages is a result set — a List of Object values. Each stage receives a result set and produces a result set.

Source stages (produce a result set from external data):

StageInputOutputDescription
queryResult set (for variable binding) or emptyResult set from GraphQL responseExecute a GraphQL query
httpResult set (for variable interpolation) or emptyResult set from HTTP JSON responseFetch JSON from any URL
fileNoneResult set from a local JSON fileRead a JSON file
stdinNoneResult set from piped inputRead JSON from stdin

Transform stages (reshape a result set):

StageInputOutputCardinality
mapResult setTransformed result set1:1
filterResult setSubset of result setN:≤N
reduceResult setSingle-element result setN:1
sortResult setReordered result setN:N
flatMapResult setFlattened transformed result set (see below)N:M
limitResult setTruncated result setN:≤N
uniqResult setDeduplicated result setN:≤N

Source normalization: If the JSON response is a single object (not an array), it is wrapped in a single-element list to produce a valid result set. If the response is an array of primitives, each element is wrapped as {"value": <element>}.

flatMap semantics: flatMap works like map but when any mapping expression evaluates to a List, the result is expanded into multiple output objects (one per list element). This is the primary mechanism for navigating nested JSON structures and GraphQL connection edges. For example, if .variants.edges is a list of 3 items, flatMap { name: .title, qty: .variants.edges[].node.qty } produces 3 output objects, one per edge.

5.4 Variable Propagation

Variables are extracted from the previous stage’s result set and injected into subsequent source stages.

http "https://api.example.com/users"
| map { login: .username }
| query { user(login: $login) { bio followers { totalCount } } }
http "https://api.example.com/orgs"
| map { url: .repos_url }
| http $url
| flatMap { name: .name, stars: .stargazers_count }

Propagation rules:

  1. $var references are resolved against each object in the current result set
  2. If the result set has multiple objects, the source stage executes once per object (fan-out) or batches where possible
  3. The optimizer MAY fuse fan-out queries into a single batched query when the target field accepts list types
  4. Variables can interpolate into http URLs (http $url) and query arguments (query { user(login: $login) { ... } })

5.5 Built-in Functions

FunctionDescriptionExample
length(x)Length of string or listlength(.name)
keys(x)Keys of an objectkeys(.)
values(x)Values of an objectvalues(.)
type(x)Type name as stringtype(.id)
toInt(x)Convert to integertoInt(.count)
toFloat(x)Convert to floattoFloat(.price)
toString(x)Convert to stringtoString(.id)
upper(x)Uppercase stringupper(.name)
lower(x)Lowercase stringlower(.name)
trim(x)Trim whitespacetrim(.bio)
split(x, d)Split stringsplit(.tags, ",")
join(x, d)Join list to stringjoin(.names, ", ")
contains(x, y)Membership testcontains(.roles, "admin")
startsWith(x, y)Prefix teststartsWith(.name, "A")
now()Current timestampnow()
flatten(x)Flatten nested listsflatten(.items)
distinct(x)Unique valuesdistinct(.tags)
coalesce(x, y)First non-nullcoalesce(.nickname, .name)

5.6 Output Formats

The cq CLI supports multiple output formats:

FlagFormatDescription
(default)Pretty JSONIndented, colorized JSON
--compact / -cCompact JSONSingle-line JSON
--table / -tTableASCII table for flat results
--csvCSVComma-separated values
--tsvTSVTab-separated values
--raw / -rRawUnquoted string values

5.7 REPL Features

5.8 Error Handling

Error ClassBehaviorExample
Parse errorAbort with source locationerror at line 1:15: expected '}'
Type errorAbort with type contextcannot compare String with Int at filter stage
Network errorRetry with backoff, then aborthttp stage failed after 3 retries: connection refused
GraphQL errorSurface server errors, continue if partialfield 'repos' not found on type 'User'
HTTP errorAbort with status code and bodyhttp stage: 404 Not Found
File not foundAbort with pathfile stage: no such file: data/users.json
Stdin emptyAbort with messagestdin stage: no input (pipe JSON to cq)
JSON parse errorAbort with source contexthttp stage: invalid JSON at byte 142
Field access errorReturn null (jq semantics).missing_field yields null
Division by zeroReturn null with warningwarning: division by zero at map stage

6. Architecture

6.1 System Components

┌─────────────────────────────────────────────────────┐
│                     cq CLI / REPL                   │
│  ┌──────────┐  ┌──────────┐  ┌──────────────────┐  │
│  │  Readline │  │  History │  │  Schema Cache    │  │
│  └──────────┘  └──────────┘  └──────────────────┘  │
└────────────────────────┬────────────────────────────┘
                         │ input text
                         ▼
┌─────────────────────────────────────────────────────┐
│                      Parser                         │
│  ┌──────────┐  ┌──────────┐  ┌──────────────────┐  │
│  │  Lexer   │  │  Grammar │  │  AST Builder     │  │
│  └──────────┘  └──────────┘  └──────────────────┘  │
└────────────────────────┬────────────────────────────┘
                         │ Pipeline AST
                         ▼
┌─────────────────────────────────────────────────────┐
│                 Planner / Optimizer                  │
│  ┌──────────┐  ┌──────────┐  ┌──────────────────┐  │
│  │  Batcher │  │  Fuser   │  │  Dependency Anlz │  │
│  └──────────┘  └──────────┘  └──────────────────┘  │
└────────────────────────┬────────────────────────────┘
                         │ Execution Plan
                         ▼
┌─────────────────────────────────────────────────────┐
│                  Execution Engine                    │
│  ┌──────────┐  ┌──────────┐  ┌──────────────────┐  │
│  │  GraphQL │  │   HTTP   │  │  File / Stdin     │  │
│  │  Client  │  │  Client  │  │  Reader           │  │
│  └──────────┘  └──────────┘  └──────────────────┘  │
│  ┌──────────┐  ┌──────────────────────────────────┐ │
│  │  Batch   │  │  Fan-out Controller              │ │
│  │  Runner  │  │                                  │ │
│  └──────────┘  └──────────────────────────────────┘ │
└────────────────────────┬────────────────────────────┘
                         │ raw results
                         ▼
┌─────────────────────────────────────────────────────┐
│                  Post-Processor                     │
│  ┌──────────┐  ┌──────────┐  ┌──────────────────┐  │
│  │  Expr    │  │  Map /   │  │  Reduce /         │  │
│  │  Eval    │  │  Filter  │  │  Aggregate        │  │
│  └──────────┘  └──────────┘  └──────────────────┘  │
└────────────────────────┬────────────────────────────┘
                         │ processed results
                         ▼
┌─────────────────────────────────────────────────────┐
│                 Output Formatter                    │
│  ┌──────────┐  ┌──────────┐  ┌──────────────────┐  │
│  │  JSON    │  │  Table   │  │  CSV / TSV        │  │
│  └──────────┘  └──────────┘  └──────────────────┘  │
└────────────────────────┬────────────────────────────┘
                         │ formatted output
                         ▼
                      stdout

6.2 API Service (api.cirql.io)

The hosted service provides:

EndpointMethodDescription
/v1/executePOSTExecute a cirql pipeline
/v1/parsePOSTParse and return AST (for tooling)
/v1/validatePOSTValidate pipeline against schema
/v1/pipelinesCRUDSave/load/list named pipelines
/v1/endpointsCRUDManage saved endpoint connections
/v1/schemaGETIntrospect a GraphQL endpoint’s schema

Request format:

{
  "pipeline": "http \"https://api.example.com/users\" | filter .active == true | reduce count",
  "endpoint": "https://api.example.com/graphql",
  "variables": {},
  "format": "json"
}

The endpoint field is required only for pipelines containing query stages. Pipelines using http, file, or stdin sources do not require it.

6.3 Core Types (Go)

package cirql

// Value represents any cirql runtime value.
type Value = any

// Object is a key-value map.
type Object map[string]Value

// ResultSet is the data flowing between pipeline stages.
type ResultSet []Object

// Stage is a single step in a pipeline.
type Stage interface {
    Execute(input ResultSet) (ResultSet, error)
    String() string
}

// Pipeline is an ordered sequence of stages.
type Pipeline struct {
    Stages []Stage
    Vars   map[string]Value
}

// Argument is a named value in a GraphQL field call.
type Argument struct {
    Name  string
    Value Value
}

// Mapping is a key-expression pair used in map/flatMap stages.
type Mapping struct {
    Key  string
    Expr Expr
}

// QueryStage executes a GraphQL query.
type QueryStage struct {
    Query     string
    Arguments []Argument
    Endpoint  string
}

// HttpStage fetches JSON from an HTTP endpoint.
type HttpStage struct {
    URL     Expr              // string literal or $variable
    Method  string            // default "GET"
    Headers map[string]string
    Body    Expr              // optional, for POST/PUT
}

// FileStage reads JSON from a local file.
type FileStage struct {
    Path string
}

// StdinStage reads JSON from standard input.
type StdinStage struct{}

// MapStage transforms each object in the result set.
type MapStage struct {
    Mappings []Mapping
}

// FlatMapStage transforms and flattens — list-valued expressions
// expand into multiple output objects.
type FlatMapStage struct {
    Mappings []Mapping
}

// FilterStage selects objects matching a condition.
type FilterStage struct {
    Condition Expr
}

// ReduceStage aggregates a result set.
type ReduceStage struct {
    Op   ReduceOp
    Expr Expr // optional: field to aggregate
}

// SortStage reorders the result set.
type SortStage struct {
    Expr Expr
    Desc bool
}

// LimitStage truncates the result set to at most N objects.
type LimitStage struct {
    N int
}

// UniqStage deduplicates the result set.
// If Expr is non-nil, uniqueness is determined by that expression;
// otherwise full object equality is used.
type UniqStage struct {
    Expr Expr // optional
}

// Expr represents an expression in the cirql AST.
type Expr interface {
    Eval(obj Object) (Value, error)
}

// FieldAccess represents .field.subfield or .field[].subfield
type FieldAccess struct {
    // Each segment is either a field name (string) or array
    // iteration marker.
    Path []PathSegment
}

// PathSegment is either a named field or an array iterator [].
type PathSegment struct {
    Name     string // field name, empty if IsIter
    IsIter   bool   // true for []
}

// VarRef represents a $variable reference in an expression.
type VarRef struct {
    Name string
}

// UnaryExpr represents !expr.
type UnaryExpr struct {
    Op      Operator
    Operand Expr
}

// BinaryExpr represents left op right.
type BinaryExpr struct {
    Left  Expr
    Op    Operator
    Right Expr
}

// FuncCall represents name(args...).
type FuncCall struct {
    Name string
    Args []Expr
}

// Literal represents a constant value.
type Literal struct {
    Value Value
}

7. Implementation Milestones

Milestone 1: Parser + AST

Milestone 2: Expression Evaluator

Milestone 3: Core Pipeline Runtime

Milestone 4: Source Stages

Milestone 5: CLI / REPL (cq)

Milestone 6: Schema Introspection

Milestone 7: Optimizer

Milestone 8: API Service

Milestone 9: Advanced Features


8. Configuration

8.1 CLI Configuration (~/.config/cq/config.toml)

[defaults]
format = "pretty"         # pretty | compact | table | csv | tsv
color = true

[endpoints.github]
url = "https://api.github.com/graphql"
headers = { Authorization = "Bearer ${GITHUB_TOKEN}" }

[endpoints.shopify]
url = "https://mystore.myshopify.com/admin/api/2025-01/graphql.json"
headers = { X-Shopify-Access-Token = "${SHOPIFY_TOKEN}" }

[http.defaults]
timeout = "30s"
headers = { User-Agent = "cq/0.1" }

[history]
max_entries = 10000
file = "~/.config/cq/history"

[cache]
enabled = true
ttl = "5m"
max_size = "100MB"

8.2 Environment Variables

VariableDescription
CQ_ENDPOINTDefault GraphQL endpoint URL
CQ_TOKENDefault bearer token
CQ_FORMATDefault output format
CQ_CONFIGConfig file path override
CQ_NO_COLORDisable colorized output
CQ_HTTP_TIMEOUTDefault HTTP timeout for http stage

9. Example Pipelines

REST API: GitHub contributors (no GraphQL)

http "https://api.github.com/repos/golang/go/contributors"
| filter .contributions > 100
| map { login: .login, commits: .contributions }
| sort .commits desc
| limit 10

Local file: Analyze package.json dependencies

file "package.json"
| map { deps: keys(.dependencies) }
| flatMap { dep: .deps }
| sort .dep asc

stdin: Count log levels from piped input

cat app.log | jq -R 'fromjson?' | cq '
  stdin
  | map { level: .level }
  | reduce group_by(.level)
'

Mixed sources: Enrich REST data with GraphQL

http "https://api.example.com/users"
| map { login: .username }
| query { user(login: $login) { bio followers { totalCount } } }
| map { login: $login, bio: .user.bio, followers: .user.followers.totalCount }
| sort .followers desc

GitHub: Top contributors by stars (GraphQL)

query {
  organization(login: "golang") {
    repositories(first: 50, orderBy: {field: STARGAZERS, direction: DESC}) {
      nodes { name stargazerCount }
    }
  }
}
| map { name: .organization.repositories.nodes[].name,
        stars: .organization.repositories.nodes[].stargazerCount }
| filter .stars > 1000
| sort .stars desc
| limit 10

Shopify: Low-stock products

query {
  products(first: 100) {
    edges {
      node { title variants(first: 10) { edges { node { inventoryQuantity } } } }
    }
  }
}
| flatMap { title: .node.title, qty: .node.variants.edges[].node.inventoryQuantity }
| filter .qty < 5
| sort .qty asc

Multi-hop: Users and their open issues

query { users(first: 20) { nodes { login id } } }
| map { login: .nodes[].login, uid: .nodes[].id }
| query { user(login: $login) { issues(states: OPEN, first: 5) { totalCount } } }
| map { user: $login, open_issues: .user.issues.totalCount }
| filter .open_issues > 0
| sort .open_issues desc

10. speckit Metadata

speckit:
  name: cirql
  version: 0.1.0-draft
  type: language-and-tool
  components:
    - name: cq
      type: cli
      language: go
      description: "cirql REPL and CLI tool"
    - name: cirql-core
      type: library
      language: go
      description: "Parser, AST, evaluator, source stages, and pipeline runtime"
    - name: api.cirql.io
      type: service
      language: go
      description: "Hosted cirql pipeline execution service"
  dependencies:
    go: ">=1.22"
    modules:
      - github.com/machinebox/graphql
      - github.com/alecthomas/participle/v2
      - github.com/chzyer/readline
      - github.com/fatih/color
  repository: https://github.com/nicerobot/cirql
  website: https://cirql.io
  license: MIT