Skip to main content
A genealogy tree records who sits under whom in your company: each member holds a seat (a node) in a tree, under a parent seat. The fluid genealogy commands read and change those trees through the company genealogy API, /api/company/v2026-10/genealogy/.... They are for company admins and integrators who manage a company’s trees. To build a member’s own view of their team, use the member API instead.

Install and sign in

Install the Fluid CLI and its genealogy plugin from npm, then sign in:
What you can run depends on who is signed in: Placements, moves, and move decisions need an admin’s own sign-in. A company API token is refused for them. Every command except tree prints JSON. A failure prints a JSON error on stderr, with the API’s type and status when there are any, and exits with a non-zero code.

Choose a seat

Most commands take the seat to start from in one of two ways:
  • A node ID, such as 3f6a1c2e-8b4d-4e7a-9c1f-2d5b8e0a7c34.
  • --member <member-id> with --tree <key-or-id>, which uses that member’s seat in the tree. --tree takes a tree key or UUID and defaults to placement.
A member with no seat in the tree, or with more than one, is an error. When a member holds several seats, the error lists them so you can pass the node ID. fluid genealogy show reads one seat with its children_count and downline_count, and fluid genealogy trees lists your company’s tree definitions and their keys.

Read trees

Depths run from 1 to 7. show, parent, root, ancestors, grandchildren, level, descendants, and subtree take --as-of <time> to read the tree as it was recorded at that time. Lists follow every cursor and return the whole list. To read in smaller batches, pass --limit: the output’s next_cursor is set when more rows remain, and you pass it back with --cursor to continue. List reads of seats also take --ids-only to return node IDs alone.
The tree view prints each seat’s member and node:
For each read’s fields and selectors, see the API reference:

Rank legs by headcount

A leg is one direct child of a seat and everything under it. legs lists the seat’s legs, largest first. strong-leg returns the largest and weak-leg the smallest.
  • Legs are measured by headcount only. Each leg counts the child’s seat plus its downline_count. The API has no leg volume.
  • Counts include seats kept for removed members. So a leg’s count can be larger than what children or descendants lists.
  • A named leg with no child is listed with 0 seats, in binary and matrix trees.
  • Each child is one request. The API has no per-leg count, so the CLI reads each direct child’s counts separately. A seat with more than 200 direct children is refused; pass --limit <n> to count up to n.
  • Empty legs need developer.view. Leg names come from the tree definitions. Without that permission, legs still ranks the occupied legs, sets leg_names_known to false, and leaves out empty legs.
  • A pick can be withheld. When some children can’t be listed or empty legs aren’t known, and that could change the answer, strong-leg or weak-leg returns leg: null with best_listed, the pick among the legs it could list.
The counts come from reading a seat and its children.

Change placements

These commands change the live tree. Each one asks you to confirm in an interactive terminal. In a script, or when an agent runs it, pass --yes; without it and without a terminal, nothing changes.

Place a seat

place gives a member a new seat with --member, or places a seat waiting in the holding tank when you pass its node ID. Give --parent <node>, or --root to place a root seat. Under a parent in a binary or matrix tree:
  • --leg names the leg, such as left or right.
  • --rule lets a placement rule choose, such as first_empty.
  • With neither, the tree’s default placement rule applies.
To hold a new seat in the holding tank instead, pass --rule defer with no --parent, --leg, or --reason; give the reason when you place it later. --position applies only to a new seat in a matrix tree that allows several seats per member, and a held seat keeps the position it was held at.
Only an authoritative tree takes placements. See Place a member in a binary or matrix tree and Place a seat waiting in the holding tank.

Move a seat

move puts a seat under a new parent. Pass exactly one of --to <node>, --to-member <member-id> (that member’s seat in --tree), or --to-root. Add --leg for a binary or matrix tree, and --reason to record why. Preview first with --validate (--dry-run does the same). It changes nothing and reports whether the move would be allowed:
Then run it with --yes:
A move applies at once, or returns a receipt: a move request waiting for approval, or a move job that runs later. To retry a move safely, pass the same --idempotency-key each time. Moves have to be enabled for your company. Until they are, moves are refused, and so is a --validate preview. See Preview a company genealogy move and Request a company genealogy move.

Approve or reject move requests

A move that needs a person’s approval waits as a move request until an admin decides. move-requests list shows a tree’s requests; filter with --status, such as pending. show <id> reads one. approve and reject change the live tree, so they ask first unless you pass --yes. reject needs --reason; on approve it’s optional. Approving a large move can return a move job instead of applying it at once.
See List company move requests, Read a company move request, Approve a move request, and Reject a move request.

Follow move jobs

A move that runs later is a move job. move-jobs list shows a tree’s jobs, and --status filters them, for example pending, running, applied, or failed. move-jobs show <id> reads one job’s progress. Both only read.
See List tree move jobs and Read a move job.

Manage trees

fluid genealogy trees lists your company’s tree definitions. trees create, trees update <tree>, and trees delete <tree> change them; <tree> is a key or UUID. Every writable field is a flag, such as --name, --kind, --leg-names, --placement-rule, and --movement-approval; run fluid genealogy trees create --help for the full list. Pass none to clear a field that can be empty. Each write shows the request it will send and asks first, unless you pass --yes. --dry-run prints the request and sends nothing:
  • Create needs --key, --name, --kind, and --authority. A binary or matrix tree also needs --volume-on-move.
  • Update sends only the flags you give. It writes at the tree’s current version, so it fails if someone changed the tree since; pin a version with --lock-version. Once a tree holds seats, only its name can change.
  • Delete fails while the tree holds any seat. The default enrollment and placement trees can’t be deleted.
See List tree definitions, Add a tree definition, Modify a tree definition, and Remove a custom tree definition.