Concourse Command Language (CCL)
The Concourse Command Language (CCL) is the language for
interacting with Concourse. CCL is built around commands
— human-readable statements that read, write, query, and
manage data. All CCL keywords are case-insensitive .
select name, age from 1 where active = true order by name
Commands can include conditions to filter records,
timestamps for time travel, ordering to sort results,
and pagination to limit output.
Separate multiple commands with semicolons:
add name as "Jeff" in 1; set age as 30 in 1; select from 1
Leading, trailing, and consecutive semicolons are tolerated.
Commands
Every CCL command begins with a verb that identifies the
operation, followed by parameters specific to that operation.
The general pattern is:
verb [ keys ] [ preposition ] [ records ] [ where condition ]
[ at timestamp ] [ order by ...] [ skip N ] [ limit N ]
Not all clauses apply to every command. The sections below
document each command’s specific syntax.
Read Commands
SELECT
Return all values for key(s) in record(s) or matching records.
select name from 1
select [name, age] from 1
select 1
select 1, 2, 3
select name where age > 30
select where age > 30
select name from 1 at "yesterday"
select name from 1 as of "2025-01-01"
select where age > 30 order by name limit 10
GET
Return the most recent value for key(s). Same syntax as
select.
get name from 1
get [name, age] from [1, 2, 3]
get name where age > 30
get where age > 30
get from 1
get 1
FIND
Return the IDs of records matching a condition.
find age > 30
find name = "Jeff" and active = true
find age > 30 order by name
find age > 30 skip 20 limit 10
find name = "Jeff" at "yesterday"
SEARCH
Full-text search for a query string within a key.
search name for " Jeff "
search description for " distributed database "
BROWSE
Return an inverted index of all values for a key.
browse name
browse [name, age]
browse name at "yesterday"
NAVIGATE
Traverse links and return data from linked records.
navigate friends.name from 1
navigate [friends.name, age] from [1, 2]
navigate friends.name where age > 30
navigate friends.name from 1 at "yesterday"
DESCRIBE
List the keys that have values in a record.
describe
describe 1
describe [1, 2, 3]
describe 1 at "yesterday"
VERIFY
Check whether a specific key-value pair exists.
verify name as "Jeff" in 1
verify name as "Jeff" in 1 at "yesterday"
HOLDS
Check whether records contain any data.
INVENTORY
Return the IDs of all records in the database.
JSONIFY
Export records as JSON. The $id$ key is included by default;
use without $id$ to exclude it.
jsonify 1
jsonify [ 1 , 2 , 3 ]
jsonify 1 without $ id $
jsonify 1 at "yesterday"
Write Commands
ADD
Append a value to a key. If no record is specified, a new record
is created.
add name as "Jeff Nelson"
add name as "Jeff Nelson" in 1
add name as "Jeff Nelson" to [1, 2, 3]
SET
Atomically replace all values for a key with a single new value.
set email as "jeff@cinchapi.com" in 1
set status as "active" within [ 1, 2, 3 ]
REMOVE
Remove a specific value from a key.
remove tag as "beta" from 1
remove tag as "beta" from [1, 2, 3]
CLEAR
Remove all values for key(s) in record(s), or clear entire
records.
clear 1
clear [1, 2, 3]
clear name from 1
clear [name, age] from [1, 2, 3]
INSERT
Insert a JSON document as a new record, or into existing
record(s).
insert '{"name": "Jeff", "age": 30}'
insert '{"status": "active"}' in 1
insert '{"role": "admin"}' into [1, 2, 3]
VERIFY_AND_SWAP
Atomic compare-and-swap: replace a value only if the expected
value is currently stored.
verifyAndSwap balance as 100 in 1 with 90
verify_and_swap status as "pending" in 42 with "active"
VERIFY_OR_SET
Ensure a field contains exactly one specific value, making
changes only if necessary.
verifyOrSet status as "active" in 1
verify_or_set name as "Jeff" in 1
RECONCILE
Synchronize a field to contain exactly the specified values.
reconcile tags in 1 with [database, nosql, java]
FIND_OR_ADD
Find the unique record where a key equals a value, or add a new
one if none exists.
findOrAdd email as "jeff@example.com"
find_or_add name as "Jeff"
FIND_OR_INSERT
Find the unique record matching a condition, or insert JSON if
none exists.
findOrInsert age > 30 '{"name": "Jeff", "age": 35}'
find_or_insert name = "Jeff" '{"name": "Jeff"}'
CONSOLIDATE
Merge two or more records into one.
consolidate 1 2
consolidate 1 [2, 3, 4]
Link Commands
LINK
Create a directed link from a source record to a destination.
link friends from 1 to 2
link friends from 1 to [2, 3, 4]
UNLINK
Remove a link.
unlink friends from 1 to 2
Historical Commands
AUDIT
View the complete revision history for a record or field.
audit 1
audit name in 1
audit 1 from "last month" to "today"
audit name in 1 from "2025-01-01" to "2025-06-01"
CHRONICLE
View a time series of a field’s values after every change.
chronicle name in 1
chronicle name in 1 from "2025-01-01" to "2025-06-01"
DIFF
Compute the net changes between two points in time.
diff 1 from "yesterday"
diff 1 from "yesterday" to "today"
diff name in 1 from "yesterday" to "today"
diff name from "last week" to "today"
REVERT
Restore key(s) in record(s) to their state at a previous
timestamp.
revert name in 1 at "yesterday"
revert name in [1, 2, 3] at "2025-01-01"
revert [name, age] in 1 at "last week"
TRACE
Find all incoming links to a record.
trace 1
trace [1, 2, 3]
trace 1 at "yesterday"
Aggregation Commands
CALCULATE
Perform aggregate calculations over values.
calculate sum age
calculate avg score in 1
calculate count name within [1, 2, 3]
calculate sum salary where department = "Engineering"
calculate avg score where score > 50 at "yesterday"
calculate count $id$ where active = true
Supported functions: avg (or average), sum, count,
min, max.
Transaction Commands
STAGE
Begin a transaction. Subsequent commands are buffered until
committed or aborted.
COMMIT
Commit the current transaction.
ABORT
Abort the current transaction and discard all buffered changes.
Utility Commands
PING
Server health check.
Conditions
A condition is a boolean expression used within commands to
filter which records are affected. Conditions appear after the
where keyword in commands like find, select, get,
navigate, and calculate.
find age > 30 and active = true
select name where department = "Engineering"
calculate avg salary where role = "Engineer"
Relational Expressions
The basic unit of a condition is a relational expression:
Examples:
name = "Jeff Nelson"
age > 30
score >= 90
email != "admin@example.com"
Operators
Comparison Operators
Operator
Aliases
Description
=
==, eq, equals
Equals
!=
ne, not_equals
Not equals
>
gt, greater_than
Greater than
>=
gte, greater_than_or_equals
Greater than or equal
<
lt, less_than
Less than
<=
lte, less_than_or_equals
Less than or equal
Range Operator
Operator
Aliases
Description
><
bw, between
Between two values (inclusive)
The between operator requires two values:
age bw 18 65
score between 80 100
Pattern Operators
Operator
Aliases
Description
regex
Regular expression match
nregex
not_regex
Negated regex match
like
SQL-style pattern match
nlike
not_like
Negated pattern match
name regex "[A-Z][a-z]+"
email like "%@example.com"
name not_like "%test%"
Search Operators
Operator
Aliases
Description
~
contains, search_match
Full-text search match
!~
not_contains, search_exclude
Negated full-text search
bio contains "distributed systems"
name !~ "admin"
These operators perform full-text search against the search
index rather than exact string comparison. See
Search .
Link Operator
Operator
Aliases
Description
->
lnk2, lnks2, links_to
Links to a record
employer -> 100
friends lnk2 42
See Graph for details.
Logical Connectives
Combine expressions with and and or:
Connective
Aliases
Description
and
&&, &
Both must be true
or
\|\|
Either must be true
age > 30 and department = "Engineering"
status = "active" or status = "pending"
Parenthetical Grouping
Use parentheses to override default precedence:
(department = "Engineering" or department = "Design")
and active = true
Operator Precedence
Parentheses ()
Relational operators — =, !=, >, etc.
AND — and, &&, &
OR — or, ||
AND binds more tightly than OR:
a = 1 or b = 2 and c = 3
-- equivalent to:
a = 1 or (b = 2 and c = 3)
Temporal Conditions
Append a timestamp to evaluate a condition against historical
data:
name = "Jeff" at "yesterday"
age > 30 on "2025-01-01"
score >= 90 during "last week"
Keys
Simple Keys
Alphanumeric identifiers:
name
age
favorite_color
$ id $
Navigation Keys
Dot-separated paths that traverse links between records:
employer.name
friends.age
employer.address.city
Navigation keys work anywhere a simple key is accepted,
including in conditions:
find employer.name = "Cinchapi"
select friends.age from 1
navigate employer.ceo.name from 1
See Graph for details.
Function Keys
A key piped to an aggregation function using |:
score | avg > 80
age | sum > 1000
items | count > 5
Values
Strings
Syntax
Example
Double-quoted
"Jeff Nelson"
Single-quoted
'Jeff Nelson'
Backtick-quoted
`Jeff Nelson`
Unquoted
Jeff (single word, no keyword conflict)
Unquoted multi-word values are supported when unambiguous:
Numbers
42 -- int eger
- 7 -- signed int eger
3.14 -- decimal
- 2.5 -- signed decimal
Record Identifiers
Positive integers reference records by ID:
select name from 1
get name from 42
Collections
Multiple items use brackets or commas:
select name from [1, 2, 3]
select name from 1, 2, 3
clear [name, age] from 1
The $id$ Key
The special $id$ key refers to a record’s unique identifier:
calculate count $ id $ where active = true
jsonify 1 without $ id $
Variable References
Values prefixed with $ are resolved from a provided data
context:
age bw $minAge $maxAge
name = $targetName
Escape Sequences
Sequence
Result
\"
Literal " inside double-quoted strings
\'
Literal ' inside single-quoted strings
\$
Literal $ (prevents variable resolution)
\@
Literal @
Timestamps
Timestamps enable time travel — querying
and reading data as it existed at a previous point in time.
Keywords
Keyword
Context
at
All contexts
on
All contexts
during
All contexts
in
Conditions
as of
Read commands only
Values
Natural language:
"yesterday"
"3 days ago"
"last week"
"last Tuesday"
"January 1, 2025"
Date strings:
"2025-01-15"
"2025-01-15 10:30:00"
Microsecond epoch: A numeric value representing microseconds
since the Unix epoch.
In Commands
select name from 1 at "yesterday"
get name from 1 as of "2025-01-01"
find age > 30 at "last month"
describe 1 at "yesterday"
In Conditions
name = "Jeff" at "yesterday"
age > 30 on "2025-01-01"
Time Ranges
Some commands support ranges with from and to:
audit 1 from "last month" to "today"
chronicle name in 1 from "2025-01-01" to "2025-06-01"
diff 1 from "yesterday" to "today"
Ordering
The order by clause sorts results returned by read commands.
Direction
Syntax
Meaning
asc (default)
Ascending (word suffix)
desc
Descending (word suffix)
<
Ascending (symbolic prefix)
>
Descending (symbolic prefix)
Examples
order by name
order by name asc
order by age desc
order by <name
order by >age
Multi-Key Ordering
order by department asc, name asc
order by >age, <name
Temporal Ordering
Sort by the value at a specific timestamp:
order by name at "yesterday"
order by score desc at "2025-01-01"
Control which subset of results to return.
Keyword
Alias
Description
skip
offset
Number of results to skip (0-indexed)
limit
Maximum number of results
skip 20 limit 10
limit 10 skip 20
offset 0 limit 50
The parts can appear in either order.
Combined with Ordering
find age > 30 order by name asc skip 20 limit 10
select name where active = true order by name limit 25
Functions
Functions compute aggregate values. They can appear within
conditions or as standalone calculate commands.
Supported Functions
avg (or average), sum, count, min, max
Pipe Syntax (Implicit Key)
score | avg
score | avg > 80
age | sum > 1000
Call Syntax (Explicit)
Across all records:
avg(score)
age > avg(age)
With timestamp:
age > avg(age, at "yesterday")
Over specific records:
avg(score, 1, 2, 3)
sum(score, [1, 2, 3])
sum(score, [1, 2, 3], at "yesterday")
Over records matching a condition:
avg(age, department = "Engineering")
sum(score, status = "active", at "last week")
Prepositions
CCL accepts semantically appropriate prepositions before record
references. Prepositions within each group are interchangeable.
Commands
Accepted Prepositions
ADD, INSERT
in, to, within, into
SET
in, within
SELECT, GET, NAVIGATE, CALCULATE
from, in, within
REMOVE, CLEAR
from, in, within
VERIFY, CHRONICLE, DIFF, AUDIT, REVERT, RECONCILE
in, within
LINK, UNLINK
from … to
Quick Reference
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42 -- Read data
select name , age from 1
get name from 1 at "yesterday"
find age > 30 and active = true
find age > 30 order by name skip 20 limit 10
search name for "Jeff"
browse name
navigate employer . name from 1
describe 1
holds 1
inventory
-- Write data
add name as "Jeff" in 1
set status as "active" in 1
remove tag as "beta" from 1
clear name from 1
insert '{"name": "Jeff", "age": 30}'
link friends from 1 to 2
-- Atomic operations
verifyAndSwap balance as 100 in 1 with 90
verifyOrSet status as "active" in 1
findOrAdd email as "jeff@example.com"
reconcile tags in 1 with [ v1, stable, release ]
consolidate 1 [ 2, 3 ]
-- Time travel
audit 1
chronicle name in 1
diff 1 from "yesterday" to "today"
revert name in 1 at "last week"
trace 1
-- Aggregation
calculate avg salary where department = "Engineering"
calculate count $ id $ where active = true
-- Transactions
stage
commit
abort