Skip to content

chant workspace ls

chant workspace ls [dir] [--at <rev>] [--json]

chant workspace ls finds the workspace declaration by walking up from dir (default: the current directory) to the git root, validates it and lists what it declares. Each member is shown with its kind, directory and roles, and each example group with its globs and how many projects they match. The record kinds the declaration names are listed with the name each kind file gives itself (#2680).

A member that can’t be read is still listed, with a reason code, and the command still exits 0 (ws-020). A reader can then show the rest of the workspace and explain the gap. Failing on an unreadable member is the job of chant workspace check. Only a declaration that can’t be read exits 1.

chant (chant.workspace.json)
MEMBER KIND DIR ROLES
docs other docs
lexicon-aws other lexicons/aws
core other packages/core
GROUP KIND GLOB PROJECTS
examples examples examples/* 33
lexicon-examples examples lexicons/*/examples/* 95
fixtures examples test/forgejo-preview-e2e test/leftness 2
22 members, 0 unreadable; 3 example groups with 130 projects

The command loads only when it runs. A project without a declaration never loads any of its code.

OptionEffect
dirWhere the walk up to the declaration starts.
--at <rev>Read the declaration and the members’ directories as they were at a commit, from the local git object store. No checkout or network is needed.
--jsonPrint the result as JSON (see Output).
CodeMeaning
0The declaration was read. Some members may be unreadable, and each carries a reason code.
1The declaration couldn’t be read. Nothing is listed.

The output is part of the workspace read contract. With --json, it follows the schema https://intentius.io/chant/schemas/workspace/ls/v1/ls.schema.json, shipped in @intentius/chant at src/workspace/ls.schema.json. Readers ignore fields they don’t know. Fields are only added within a contract version, and the code lists are closed.

{
"$schema": "https://intentius.io/chant/schemas/workspace/ls/v1/ls.schema.json",
"contract": 1,
"chant": "0.80.0",
"at": null,
"workspace": {
"name": "chant",
"root": ".",
"file": "chant.workspace.json",
"schema": 1,
"minReader": null,
"pins": [],
"records": [{ "name": "decision", "path": "decisions/decision.kind.mjs", "kind": "decision", "reason": null, "acceptance": null }],
"agentsFrom": "base"
},
"members": [
{
"name": "lexicon-aws",
"dir": "lexicons/aws",
"kind": "other",
"roles": [],
"upstream": null,
"because": "an npm workspace package with no chant project",
"readable": true,
"reason": null,
"records": [],
"generated": [
{
"path": ".github/workflows/chant-lexicon-aws-production.yml",
"command": "chant build --components --generate github --env production",
"env": "production",
"jobs": ["build", "Deploy to production"]
}
],
"agents": ["aws-agent"]
}
],
"groups": [
{
"name": "lexicon-examples",
"kind": "examples",
"glob": ["lexicons/*/examples/*"],
"matches": ["lexicons/aws/examples/lambda-api"],
"skipped": ["lexicons/gitlab/examples/migrate-from-github"],
"reason": null
}
],
"diagrams": [
{
"name": "architecture",
"title": "Studio architecture",
"source": "docs/diagrams/architecture.d2",
"render": "docs/diagrams/architecture.svg",
"renderer": { "tool": "d2", "version": "0.9.0", "args": ["--layout=elk", "--theme=0", "--pad=40", "--omit-version"] },
"member": "docs"
}
],
"summary": { "members": 22, "unreadable": 0, "groups": 3, "matches": 130 }
}

The example shortens the lists. chant is the version that read the workspace. root is the workspace root relative to the git root. at is the full commit id when --at is given. A group’s matches are the directories its globs match that hold a chant project; skipped are the ones that hold none.

workspace.records holds the workspace’s own record kinds and each member’s records holds the member’s, in file order. They were added within contract 1 by #2680. Each entry has these fields:

FieldValue
namethe name the declaration gives the kind, else the kind file’s own recordKind.name, else null when the file can’t be loaded
paththe kind file from the workspace root
kindthe kind file’s recordKind.name, or null when it can’t be loaded
reasonnull, or why the kind file can’t be loaded: kind-unreadable, kind-invalid, schema-unreadable or schema-id-mismatch, the codes records fails with
acceptancefor a work kind with acceptance criteria, each current item that lists criteria as { item, state, met, total }, read in the tree read (#2772). null for any other kind, and when the kind or its records can’t be read

The kind file is looked for in the tree read, which is the revision under --at. It is loaded from the working tree, which imports it. A kind that can’t be loaded leaves its member readable, and chant workspace check fails on it with WSP115.

Each member’s generated lists the files it generates, sorted by path (#3050, ws-061). It merges the member’s declared generated entries with the record chant build --components --generate and chant run --generate keep in the member’s .chant/generated.json. A hand-written entry is not listed. The fields of an entry are:

FieldValue
pathfrom the repository root, with / separators, which is how a forge reads a CI file. A workspace below the git root has its root in the path
commandthe command that regenerates the file, run in the member’s directory. Empty when a record names none
envthe environment a component pipeline deploys, else null
jobsfor a forge CI file, the check names it declares: a GitHub, Forgejo or Gitea job’s name, else its id, and a GitLab job’s key. null for any other file, for a CI file missing from the tree read, and for one that can’t be parsed

A forge CI file is one in .github/workflows/, .forgejo/workflows/, .gitea/workflows/ or .gitlab/ci/, or the root .gitlab-ci.yml. chant reads the file from the tree read, so --at gives the names at the revision, and runs nothing. A reader that requires checks, such as github-warden, takes them from jobs.

Each member’s agents lists the names of the agent sessions the declaration binds to it, through agents[].member or agents[].members, in declaration order, and is [] when none is (#3615). A session bound to several members is listed on each. A tool that starts an agent for a member sets CHANT_AGENT to one of these names, and needs no parse of the declaration, .json or .jsonc. The sessions are read where chant workspace agent and the write paths read them: the declaration at the base revision (origin/HEAD, main or master), else the working tree’s, so a session added in the working tree is listed once it reaches base. Under --at they are read at that revision. workspace.agentsFrom says which: base, working-tree or at. Both fields are contract 1 additions.

The declaration’s top-level x- keys come back on workspace, and a member’s on that member, as written (#3595). status --json prints those on a box block and its parts. This is a contract 1 addition.

diagrams is one flat array for every declared diagram artifact, a contract 1 addition from #2764. member on each entry says who declares it, null for the workspace’s own. name, title, source, render and renderer come straight off the declaration. source and render are paths from the workspace root. render is null for a mermaid or excalidraw diagram that commits no render, which a reader draws from its source. chant loads nothing to print this and runs no renderer. A missing source or render, or one that drifted, is chant workspace check’s job: it reports those as WSP131 to WSP133.

A failed read prints { "$schema", "contract", "chant", "error": { "code", "message", "location" } } instead. location is { "file", "line", "column" } when the problem is in the file, and null otherwise.

CodeThe member
dir-missinghas no directory at its dir
unknown-kindhas a kind that is neither built in nor supplied by a pinned package; the message lists the known ones
kind-probe-failedisn’t what its kind reads, such as a chant member with no chant config

A group whose globs match no chant project has the reason no-matches.

CodeCause
declaration-missingno declaration between the directory and the git root
declaration-ambiguousboth chant.workspace.json and chant.workspace.jsonc exist
declaration-unparseablenot valid JSON, or not valid JSONC for .jsonc
declaration-invaliddoesn’t match the schema, or repeats a name
placement-invalidbreaks a placement rule
reader-too-oldthe declaration’s minReader is newer than this chant
root-chant-requiredthe declaration pins another chant, which isn’t installed at the root (which chant reads it)
not-a-git-repository--at was given outside a git repository
revision-unknown--at names no commit
Terminal window
# The chant repository's members and example groups
chant workspace ls
# The same, as it was at a commit
chant workspace ls --json --at 91c7547e