tygen
Skill6 starsChanged 9 days agoApache-2.0View on GitHub
Generate a typed client for one CDF data model in a Dune or Flows app, and use it to search, aggregate and query instances with the model's property names and types. Use only when the TyGen alpha flag is explicitly enabled.
In this repository34 other files it gives its agents.
- aura-reviewSkill
- call-cognite-functionSkill
- code-qualitySkill
- connect-atlas-mcpSkill
- correctness-and-error-handlingSkill
- create-agentSkill
- create-client-toolSkill
- dependencies-auditSkill
- designSkill
- dm-graph-traversalSkill
- dm-limits-and-best-practicesSkill
- flows-app-briefSkill
- flows-code-reviewSkill
- flows-design-reviewSkill
- flows-external-app-submitSkill
- flows-review-checksSkill
- graph-viewerSkill
- handle-startup-stateSkill
- hide-show-shellSkill
- integrate-atlas-chatSkill
- integrate-file-viewerSkill
- integrate-fusion-agentSkill
- integrate-todo-listSkill
- migrate-app-to-flowsSkill
- performanceSkill
- pull-changes-resolve-conflictsSkill
- reveal-3dSkill
- securitySkill
- setup-flows-authSkill
- setup-python-toolsSkill
- skill-creatorSkill
- start-flows-appSkill
- test-coverageSkill
- use-topbarSkill
The file
We split this skill into the rules it gives an agent
4 rules. About 0 are common, 1 is distinctive, and 3 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
3
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 29
When the data-model reference is unknown, cognite api datamodels list lists the models.
- Distinctive: line 32
Commit the generated output.
- Very specific: line 38
Import from the generated index.ts, and bind the client once:
- Very specific: line 62
Search is eventually consistent: writes made right before may not be found yet.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
TyGen
TyGen generates a typed client from one version of a CDF data model. Use it to read instances with short property names and result types that follow the request, instead of the nested properties[space]['View/version'] objects of the native @cognite/sdk.
Availability
TyGen is experimental and is not part of the normal app workflow. Before suggesting, running, or editing code that depends on generated output, verify that COGNITE_ALPHA_ENABLE_TYGEN is explicitly set to true for the command environment. If it is not enabled, explain that TyGen is an opt-in alpha capability and continue with the native @cognite/sdk types and APIs already used by the app.
If you introduce TyGen as an option, confirm the user wants to use it before running it. An explicit request to generate types is sufficient confirmation. Do not enable the flag, add it to a repository, or change deployment configuration without the user's explicit approval.
Without the flag the CLI reports unknown command 'tygen'. That means the flag is not set, not that the CLI is too old.
Generate
From the app directory (it has an app.json):
npx @cognite/cli@latest tygen generate --data-model mySpace:myModel:v1- In an interactive terminal, omit
--data-modelto pick a versioned model from the project.--interactivecontrols browser authentication, independently of the model picker. - The command uses the app configuration and the saved
cognite auth loginsession. Use--base-urland--projectto generate outside an app directory. - When the data-model reference is unknown,
cognite api datamodels listlists the models. It requires the separateCOGNITE_ALPHA_ENABLE_API=trueflag; check that it is already enabled before running it. - Output goes to
src/generated_types/<externalId>/:index.ts(the entry point),types.ts,views.ts,tygen-views.ts,tygen-interface.ts,methods/andinternal/. Do not write application code there, and do not edit generated files. - Generating again into the same folder replaces it. To keep two versions of a model side by side, generate the second with
-o src/generated_types/<externalId>-<version>. - Commit the generated output. After a data-model change, regenerate, inspect the diff, and run the app's typecheck and tests.
Generated code needs TypeScript 5.4 or later.
Use
Import from the generated index.ts, and bind the client once:
import { initTygen } from './generated_types/PlantModel';
const tygen = initTygen(client); // client from useCogniteSdk()Each view of the model is a property of tygen, such as tygen.equipment, with search, aggregate and query. A view that only edges use has no query. In filter, sort, select and groupBy, a property is just its name, such as 'status'. filter and sort also take an instance field such as 'externalId'; select only takes the view's properties. A typo is a compile error.
Search
Full-text search over one view. Items carry the view's properties directly in item.properties.
const found = await tygen.equipment.search({
query: 'pump',
properties: ['name'], // properties to search in
filter: { equals: { property: 'status', value: 'active' } },
limit: 10,
});
found.items.map((item) => item.properties.name);Search is eventually consistent: writes made right before may not be found yet. Use query when that matters.
Aggregate
const counts = await tygen.equipment.aggregate({ groupBy: ['isCritical'], aggregates: [{ count: {} }] });
for (const item of counts.items) {
const isCritical = item.group?.isCritical; // typed from the model
const count = item.aggregates[0]?.aggregate === 'count' ? item.aggregates[0].value : undefined;
}groupBy only accepts text, number, boolean and direct-relation properties, lists of text or direct relations, and externalId, space and version. The API rejects enum, timestamp, date, JSON, file, time series and sequence properties, lists of numbers or booleans, and createdTime/lastUpdatedTime, so the types do too. To count by an enum, run one aggregate per value, with a count and an equals filter on that value.
Query
query reads one view, with an exact, up-to-date result. It can return selected properties only, filter on a related instance, and return the instances a direct relation points to.
const page = await tygen.workOrder.query({
filter: { nested: { scope: 'mainAsset', filter: { equals: { property: 'name', value: '43-PT-1027D' } } } },
select: ['name', 'status'],
include: { mainAsset: { select: ['name'] }, affectedLocations: { select: ['name'] } },
limit: 20,
});
const rows = page.items.map((item) => ({
...item.properties, // Pick<WorkOrder, 'name' | 'status'>
location: item.related.mainAsset?.properties?.name, // one relation: an instance or undefined
affected: item.related.affectedLocations.map((l) => l.properties?.name), // a list relation: an array
}));selectlists the properties to return. Without it, all of them are returned.nested.scopeand the keys ofincludeare direct relations of the view, to another view of the model. Theirfilterandselectuse the property names of the target view. A related instance may have no data in the target view, so itspropertiesmay beundefined.- An
includeentry may beundefined, such asinclude: { mainAsset: showAsset ? {} : undefined }. Thenrelated.mainAssetis optional. includereturns at most 10,000 related instances per relation, across all items. With more, the query throws. Lowerlimit.includealso reads the target view. Without read access to it or its space, the whole query is likely to fail with a 403, not return fewer related instances. A query that works withoutincludeand fails with it points to this, or to the 10,000 limit.- Items that point to the same instance share one related object. Copy it before changing it.
- It returns 100 items by default and has no cursor. To page, or to follow inward relations or edges, use
tygen.query.
Raw typed query
tygen.query takes a native instances.query request with full property paths, [space, 'View/version', 'property'], and types the result from it. Use it for paging with cursors, inward relations, edges and set operations. Its results keep the native nesting under space and View/version.
Patterns
- Build a filter in steps by spreading in the conditions that are set, each ending in
as constso its property names stay literal:
The generated SDK exports no per-view filter type to annotate the array with. Withoutconst conditions = [ ...(type ? [{ equals: { property: 'workOrderType', value: type } } as const] : []), ...(location ? [{ nested: { scope: 'mainAsset', filter: { equals: { property: 'name', value: location } } } } as const] : []), ]; await tygen.workOrder.query({ filter: { and: conditions }, select: ['name'] });as const, the property names widen tostring, and the call fails with a longStrictKeyserror. A misspelled property is still a compile error. When no condition is set,conditionsis empty, which is fine, see below. - An empty
andis treated as no filter, and an emptyorreturns no items without a request. - Requests kept in a variable need
as const, oras const satisfies QueryInputfortygen.query. - Optional parts of a request, such as a cursor, are spread in:
...(cursor ? { cursors: { orders: cursor } } : {}). - Relations to views outside the model, such as
CogniteSourceSystemfrom a model that does not include it, have no shortscopeorincludename. Usetygen.querywith full paths.
Known API limits
- A
nestedfilter withprefixon a large view can time out (408). Preferequals, or filter the target view first. - A
sorton a property without an index, or aqueryover a very large view, can time out. Search is usually safer when you do not control the indexes. - The query API rejects
inon an enum property. Useequals, or anorofequals. - The API cannot traverse a list of direct relations inwards.
- Reverse relations and edges are not in the per-view types; use
tygen.query. instances.listand writes stay on the native@cognite/sdk. Pass generated view references to it (sources: [{ source: EquipmentView }]).
Explore data from the terminal
With COGNITE_ALPHA_ENABLE_API=true, cognite api instances search|aggregate|query --view space:externalId/version runs the same requests with short property names and prints a table, or JSON with --json. Without --view, an interactive terminal lets you pick the data model and view. Use it to check property names and values before writing app code.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

