One commanddoes it all.
A company’s model is a folder of Markdown files in a repository of its own. The command line makes that folder, checks it, keeps its vocabulary current and puts the Obsidian plugin beside it, all from one menu.
Nothing here is installed from a registry. The command runs straight from a release on GitHub, and #semver:* is what picks it: npm reads the repository’s release tags as version numbers and takes the highest, so it runs the newest release on the day you run it. The quotes keep the shell from reading the * as a file pattern, and --yes answers the question npx asks before any release it has not run before. It needs Node 22 or newer.
From nothing to a model
For someone who has none of this yet. The steps are the same on macOS, Windows and Linux, from an empty folder to a model that passes its checks.
What you need first. A terminal: Terminal on macOS, PowerShell on Windows, the shell you use on Linux. Node 22 or newer, which brings npx with it. Git, for the command as the steps write it, because npm reads the releases through it and stops with spawn git ENOENT without it; step 2 says how to run a release without git. The model itself needs no git: a folder on your machine or an Obsidian vault is enough. Nothing else is needed to make and check a model. Obsidian is for writing it in, a GitHub account is for running its checks on every push, Claude Code is for the skills the model is written for, and Python 3 is for two of those skills.
See what is there. Open a terminal and ask for both versions. Where the first says no version, install git from its download page, which has a way in for each system; on macOS the command itself offers to install the command line developer tools, which bring git. Where the second says a version older than 22, or no version, install Node from its download page. Then open a new terminal.
git --version node --version
Open the menu. Run the command from any folder. The first run takes a moment, since npm fetches the tooling before it starts.
npx --yes 'github:companygraph/meta-model#semver:*'
Without git, run a release by its name instead: take the newest from the release page and write it for
<release>. The same address then stands in for'github:companygraph/meta-model#semver:*'in every command on this page, and it stays on that release until you write a newer one.npx --yes 'https://github.com/companygraph/meta-model/archive/refs/tags/<release>.tar.gz'
Make the model. Pick 1, Make a model. Give it a folder,
~/git/acmefor example, which it makes if it is missing, and the company’s name. It writes the model there and says what it wrote.Open it in Obsidian, if you write there. When it asks whether to make the folder a vault, say yes: it installs the plugin and offers to open the vault. Trust the vault’s author when Obsidian asks; what Obsidian still asks covers the rest. Without Obsidian, any editor that writes Markdown will do.
Write the company. Start with
model/identity.mdandmodel/vision.md, which are already there. Each folder’s README names the schema its files follow, and in Claude Code the model’s own skills write to those schemas.Check it. Pick 2, Check a model, whenever the model changes, or run the check by name in the model’s folder. It says what passes and names what does not, by file.
cd ~/git/acme npx --yes 'github:companygraph/meta-model#semver:*' check
Keep it in git, if you want its history. The model is plain files, so it works without git, and git keeps its history when you want one. Commit it, then push it to an empty repository on GitHub; from then on the workflow it came with runs the same checks on every push and pull request.
cd ~/git/acme git init -b main git add -A git commit -m "The model starts"
Take a new release when one comes. Pick 3, Move a model. It shows every file it would change before it writes one.
Let Claude read the company’s site. In Claude Code, opened in the model’s folder, run
/companygraph-companyand give it the company’s web address. It reads the site, the company’s GitHub organization and its public pages, shows what it found as a ledger you keep or strike row by row, records the terms and consents each source is used under, writes what you kept and checks it. It commits nothing; the commit is yours.
Where it runs. The steps should run the same on Windows and Linux, and the tooling’s automated tests run there too, but the walk itself has been run by hand on macOS only. If a step fails on your machine, open an issue with the command and what it printed, as the Feature request process describes, or send the fix as a pull request through the Contribution process.
Which agent. The model is written for Claude: init writes an AGENTS.md, a CLAUDE.md and the skills for Claude Code, and Claude is the only agent it writes for today. Others are planned. If you work with another agent and would like the model written for it too, its files are welcome as a pull request through the Contribution process.
Run it
In a terminal, from any folder. It opens a menu, asks for what it needs, and says what it did. Then the menu comes back, with the latest pick above it, green when it went through and red when not, until you pick Quit, type q or press Ctrl+C. At any of its questions, b or Ctrl+C comes back to the menu.
npx --yes 'github:companygraph/meta-model#semver:*'
$ npx --yes 'github:companygraph/meta-model#semver:*'
CompanyGraph tooling <release> · companygraph.io
1 Make a model a new instance in a folder, or beside the files already in one 2 Check a model the mechanical checks, as its CI runs them 3 Move a model to <release> its vendored core, skills, manifest and workflow tag together 4 Obsidian make an instance a vault: the plugins, the graph, the panes, and Obsidian itself 5 Report by seat the history's commits, by the seat that made them 6 Hold a repository a site or service with no model: the form check, and the workflow or hooks the chosen gate writes 7 Report pins which of a repository's pins are behind; nothing moves 8 Quit or q, or Ctrl+C › Pick 1-8 (b or Ctrl+C at any question comes back here)
What the menu does
1 · Make a model. It asks for a folder, the company’s name and how every change is checked, and writes the instance there: the vocabulary under meta/core/, a manifest with a hash for every file it owns, a folder for each type with a README naming its schema, the entities no instance passes without, the workflow or hooks of its gate, and for Claude an AGENTS.md, a CLAUDE.md and the skills that write to the schemas. The gate is what checks every change before it lands: by default a workflow on GitHub, hooks in git for a repository that never reaches GitHub, and nothing for a folder nothing can gate, such as one without git. A folder that already holds files, a repository or an Obsidian vault, is added to only once you say yes, and nothing in it is written over. Then it offers to make the folder a vault.
2 · Check a model. The mechanical checks, the same ones its gate runs: the workflow on every push and pull request once the folder is a repository on GitHub, or the hooks on every commit on the git gate. They apply the rules of the vocabulary the instance copied in, never a newer one. Then it holds the repository’s Markdown to one form, as the gate does too, and names each file out of it; form --fix writes what it can into the form. Whether an entity keeps its schema’s writing rules is judged by reading, which the companygraph-validate skill does.
3 · Move a model to a newer release. A release lands in the vocabulary, the skills, the manifest and the workflow’s pin, or the gate’s hooks on the git gate, so it moves them together. Before it moves anything, it holds the Markdown to the form of the release it moves to, and where a file is out of form it stops and names form --fix. It first shows every file it would write or remove, and writes only once you say yes. A vocabulary file edited inside the instance stops it and is named; the model itself, AGENTS.md and CLAUDE.md are never touched.
4 · Obsidian. An instance is a folder of Markdown files, which is what an Obsidian vault is, so this makes it one. It installs the plugin, which checks the model as you type, completes what the schemas declare and marks what breaks where it is written. The plugin is not in Obsidian’s community directory, so the newest release goes into .obsidian/plugins/companygraph/, switched on, and any plugin already on stays on. It offers two more by name, Claudian, which is Claude Code in a pane and needs Claude Code on the machine, and Terminal, a shell in one. It writes a graph view of the model and the panes, the identity open and the plugin’s views beside it, where the vault has none yet. Then it looks for Obsidian, and where it is missing asks to install it through Homebrew on a Mac or winget on Windows, or names the download on Linux, and offers to open the vault. Run again, it updates the plugins and keeps their settings.
What Obsidian still asks. The first time it opens the vault, Obsidian asks whether you trust the vault’s author; say yes. If the plugin is still not under Installed plugins, the vault was once opened in restricted mode: Settings → Community plugins → Turn on community plugins. Obsidian keeps that switch outside the vault, so no command can set it.
5 · Report by seat. It reads the model’s history back by the seat that made each commit. An agent’s commit is authored by the seat it held and a person’s under their own address, which is what the commit hook init writes holds each commit to. Commits from before that hook was released count as the owner’s own, since no seat can be read from them.
6 · Hold a repository. A site or a service that draws a model but holds none of its own is held to what a model is held to, without the vocabulary. It asks how every change is checked, as 1 does, and writes what that gate needs: a workflow that checks the one Markdown form on every push and pull request, or hooks that check it on every commit and then run the commands its pins.json lists under verify, and with either the commit hook. It also writes a pins.json that declares the release of the tooling it runs. From then on, 2 checks it for the form alone, and 3 moves its tooling, and its workflow where it has one, to a newer release without copying any vocabulary in. In a folder that holds a model, it stops and points at 3.
7 · Report pins. A repository’s pins.json declares what it takes from other repositories, each at a release or a commit. It asks the source of each, without cloning it, for its newest release tag or its latest commit, and says of each pin whether it is current or behind, with the newest beside it, or whether its source could not be reached. A pin that is behind is a choice until its owner says otherwise, so the report moves nothing and goes through; it fails only when pins.json cannot be read or names a line that is not there.
Without the menu
Each entry is also a command, for a script or a CI step, and its flags say what the menu asks. Without a terminal, in a pipe or in CI, the bare command only prints what it can do.
npx --yes 'github:companygraph/meta-model#semver:*' init ~/git/acme --name "Acme" --agent claude npx --yes 'github:companygraph/meta-model#semver:*' check ~/git/acme npx --yes 'github:companygraph/meta-model#semver:*' upgrade ~/git/acme --dry-run npx --yes 'github:companygraph/meta-model#semver:*' obsidian ~/git/acme
The flags. init takes --here to write into a folder that already holds files, and --folders values,processes to write only the types named. init and adopt take --gate with github, git or none to choose what checks every change, github unless it is given. upgrade takes --dry-run, which only shows, --gate, which moves the repository from one gate to another, and --force, which overwrites an edited vocabulary file and says so, moves even where the Markdown is out of form, and removes a gate hook that was edited, where a move would otherwise stop on it. form takes --fix, which writes into the form what it can and names the rest. obsidian takes --release for one release of the plugin, --plugins or --no-plugins to answer both offers at once, and --open to open the vault unasked. The meta-model’s README names them all.