- Move kindred-icons/ to icons/kindred/ (better organization) - Add icons/mappings/ with FCAD.csv (Tango palette) and kindred.csv (Catppuccin Mocha) - Add icons/retheme.py script to remap upstream FreeCAD SVG colors - Generate icons/themed/ with 795 auto-themed SVGs (24,698 color replacements) - Update BitmapFactory.cpp to load icons/kindred (highest priority) then icons/themed (auto-remapped upstream icons) before default FreeCAD icons - Update CMakeLists.txt to install both icon directories - Update all documentation references to new paths The 157-color mapping covers the full Tango palette used across FreeCAD's icon set, interpolating between 4 luminance anchors per color family.
23 KiB
.kc File Format Specification
Version: 1.0-draft Date: February 2026 Status: Specification — Not Started
The .kc format is Kindred Create's native file format. It is a strict superset of FreeCAD's .fcstd format — every .kc file is a valid .fcstd file with an additional silo/ directory containing platform metadata. This design preserves full interoperability with vanilla FreeCAD while enabling Silo integration, version control, compute job attachment, and engineering workflow features.
1. Design Principles
Superset, not fork. A .kc file can be renamed to .fcstd and opened in unmodified FreeCAD. FreeCAD ignores unknown entries in the ZIP archive, so the silo/ directory is invisible to the base document loader. This means upstream FreeCAD merges never break the format.
Silo metadata is a snapshot. The silo/ directory carries a point-in-time copy of server-side state. The Silo server is authoritative. When a .kc file is opened while connected to Silo, the client checks for newer revisions. Offline edits are reconciled on reconnect by comparing revision hashes in silo/manifest.json.
Incremental adoption. Not every silo/ file needs to be populated. The format grows as Silo modules ship. A minimal .kc file only requires silo/manifest.json. All other entries are optional and introduced by their respective modules.
Round-trip safety. FreeCAD's save routine writes only the entries it knows about (Document.xml, GuiDocument.xml, .brp files, thumbnails/). It does not delete unknown entries from the ZIP. The silo/ directory survives FreeCAD save cycles without corruption.
2. Archive Structure
A .kc file is a ZIP archive. Its contents are organized into two zones: the standard FreeCAD zone (inherited as-is) and the Kindred zone (silo/).
part.kc (ZIP archive)
│
│ ── FreeCAD Standard Zone ──────────────────────────
│
├── Document.xml # Feature tree, parameters, object definitions
├── GuiDocument.xml # Visual state (colors, visibility, camera)
├── *.brp # BREP geometry cache (one per shape)
├── thumbnails/
│ └── Thumbnail.png # FreeCAD-generated preview
│
│ ── Kindred Zone ───────────────────────────────────
│
└── silo/
├── manifest.json # Identity, origin, revision, schema version
├── metadata.json # Custom schema fields, tags, lifecycle state
├── history.json # Local revision log (lightweight)
├── approvals.json # ECO / approval state snapshot
├── dependencies.json # Assembly link references by Silo UUID
├── macros/ # Embedded macro references or inline scripts
├── inspection/ # GD&T annotations, tolerance data, CMM linkage
├── jobs/ # Compute job YAML definitions
│ └── default.yaml
└── thumbnails/ # Silo-generated renderings (separate from FreeCAD's)
3. FreeCAD Standard Zone
These entries are identical to a standard .fcstd file. Kindred Create does not modify their structure or semantics.
| Entry | Description |
|---|---|
Document.xml |
Serialized feature tree. Contains all object definitions, parametric properties, sketch geometry, constraints, and inter-object references. This is the canonical representation of the model. |
GuiDocument.xml |
View provider state: object colors, visibility flags, camera position, display modes. Not required for geometry reconstruction. |
*.brp |
OpenCASCADE BREP files. One per shape object. These are a derived cache — they can be regenerated from Document.xml by recomputing the feature tree. |
thumbnails/Thumbnail.png |
FreeCAD's built-in thumbnail, generated on save. 128×128 PNG by default. |
The BREP files are binary and not diffable. Document.xml is XML and structurally diffable (see Silo's Intelligent FCStd Diffing module). GuiDocument.xml is XML but rarely relevant to version control.
4. Kindred Zone (silo/)
All Kindred-specific data lives under silo/. Each entry is described below with its schema, lifecycle, and owning module.
4.1 silo/manifest.json — Required
The only mandatory silo/ entry. Identifies this file within the Silo ecosystem.
{
"kc_version": "1.0",
"silo_instance": "https://silo.example.com",
"part_uuid": "550e8400-e29b-41d4-a716-446655440000",
"revision_hash": "a1b2c3d4e5f6",
"created_at": "2026-02-13T19:00:00Z",
"modified_at": "2026-02-13T20:30:00Z",
"created_by": "joseph"
}
| Field | Type | Description |
|---|---|---|
kc_version |
string | .kc schema version. Used for forward-compatible migrations. |
silo_instance |
string | URL of the originating Silo server. Null for offline-created files. |
part_uuid |
UUID | Globally unique identifier assigned by Silo. Survives renames and moves. |
revision_hash |
string | Hash of the last committed revision. Used for offline reconciliation. |
created_at |
ISO 8601 | Timestamp of initial .kc creation. |
modified_at |
ISO 8601 | Timestamp of last save. |
created_by |
string | Username of the creating user. |
4.2 silo/metadata.json — Optional
Custom schema field values, lifecycle state, and tags. Driven by Silo's user-customizable schema engine.
{
"schema": "mechanical-part-v2",
"lifecycle": "released",
"tags": ["structural", "aluminum"],
"fields": {
"category": "bracket",
"material": "6061-T6",
"finish": "anodized",
"weight_kg": 0.34,
"project": "PRJ-042"
}
}
The schema field references a schema definition stored on the Silo server. Field names, types, and validation rules are defined by that schema. The client renders form fields dynamically based on the schema descriptor fetched from GET /api/schemas/{schema_name}/form.
4.3 silo/history.json — Optional
Lightweight local revision log. The full history lives server-side; this is a portable subset for offline reference.
{
"revisions": [
{
"revision": 3,
"hash": "a1b2c3d4e5f6",
"author": "joseph",
"timestamp": "2026-02-13T20:30:00Z",
"comment": "Added fillet to mounting holes",
"status": "released"
},
{
"revision": 2,
"hash": "f6e5d4c3b2a1",
"author": "joseph",
"timestamp": "2026-02-12T14:00:00Z",
"comment": "Initial geometry",
"status": "draft"
}
]
}
Revisions are listed newest-first. This file is append-only during local editing and reconciled with the server on commit.
4.4 silo/approvals.json — Optional
Snapshot of engineering change order (ECO) and approval workflow state. Server-authoritative — this is a read cache for offline display.
{
"eco": "ECO-2026-047",
"state": "pending_review",
"approvers": [
{
"user": "jane.smith",
"role": "design_lead",
"status": "approved",
"timestamp": "2026-02-13T16:00:00Z"
},
{
"user": "bob.jones",
"role": "quality",
"status": "pending",
"timestamp": null
}
]
}
4.5 silo/dependencies.json — Optional
Assembly link references stored by Silo UUID rather than filesystem path. This decouples assembly structure from local file layout.
{
"links": [
{
"uuid": "660e8400-e29b-41d4-a716-446655440001",
"label": "Base Plate",
"part_number": "KC-BRK-0042",
"revision": 2,
"quantity": 1,
"relationship": "component"
},
{
"uuid": "770e8400-e29b-41d4-a716-446655440002",
"label": "M6 Socket Head Cap Screw",
"part_number": "KC-HDW-0108",
"revision": 1,
"quantity": 4,
"relationship": "component"
}
]
}
When opening an assembly .kc, the Silo workbench resolves UUIDs to local file paths. Missing dependencies trigger a download prompt if the Silo connection is active.
4.6 silo/macros/ — Optional
Embedded macro references or inline Python scripts bound to this part. Files in this directory are registered with Create's macro system on document open.
silo/macros/
├── on_save.py # Hook: runs before save
├── generate_drawing.py # Utility: creates a drawing from this part
└── manifest.json # Macro metadata and execution triggers
Macro manifest:
{
"macros": [
{
"file": "on_save.py",
"trigger": "pre_save",
"description": "Validates wall thickness before save"
},
{
"file": "generate_drawing.py",
"trigger": "manual",
"description": "Generate 3-view drawing with BOM table"
}
]
}
4.7 silo/inspection/ — Optional
GD&T annotations, tolerance data, and CMM device linkage metadata. Structure TBD pending Tier 5 Quality module specification.
Provisional layout:
silo/inspection/
├── gdt_annotations.json # GD&T callouts linked to face/edge references
├── tolerance_stack.json # Statistical tolerance analysis results
└── cmm_program.json # CMM program reference and measurement linkage
4.8 silo/jobs/ — Optional
Compute job YAML definitions attached to this part. These feed into Silo's job queue infrastructure (Tier 3). A part can carry multiple job definitions for different compute workloads.
# silo/jobs/default.yaml
kind: silo/job
version: 1
metadata:
part: bracket-assembly-v3
trigger: on-commit
spec:
tasks:
- name: constraint-check
runner:
labels: [cpu, ondsel-solver]
image: kindred/solver-runner:latest
timeout: 300s
- name: appearance-render
runner:
labels: [gpu, render]
image: kindred/render-runner:latest
depends_on: [constraint-check]
resources:
vram: 8Gi
Job YAMLs use the runner label system described in the Silo Job Queue specification. The trigger field determines when the job executes: on-commit (every Silo commit), on-release (lifecycle transition to released), or manual (user-initiated).
4.9 silo/thumbnails/ — Optional
Silo-generated renderings, separate from FreeCAD's built-in thumbnails/Thumbnail.png. These are produced by the Headless Create module (Tier 1) and may include multiple views or higher-resolution images.
silo/thumbnails/
├── isometric.png # Default isometric view
├── front.png # Front orthographic
├── top.png # Top orthographic
└── exploded.png # Exploded assembly view (assemblies only)
Thumbnail generation policy (single canonical vs. multi-view) is configurable at the Silo instance level.
5. Interoperability
5.1 FCStd → .kc (Import / Promotion)
When a user opens an .fcstd file in Kindred Create, it loads normally through FreeCAD's standard document loader. The file can be "promoted" to .kc through either of two paths:
Manual promotion: User selects File → Save As → .kc. Create generates silo/manifest.json with a new UUID and prompts for schema field selection if connected to Silo.
Silo-triggered promotion: User commits an .fcstd to Silo via the Silo workbench. Silo assigns a UUID, generates the silo/ directory with defaults, and returns a .kc to the client. Subsequent saves default to .kc.
In both cases, no data in the FreeCAD standard zone is modified. The promotion is purely additive.
5.2 .kc → FCStd (Export / Demotion)
File → Export As → .fcstd strips the entire silo/ directory. The resulting file is a valid .fcstd with no Kindred-specific content. This is the recommended path for sharing files with vanilla FreeCAD users.
5.3 Vanilla FreeCAD Behavior
If a .kc file is renamed to .fcstd and opened in vanilla FreeCAD:
- The document loads normally.
Document.xml,GuiDocument.xml, and BREP files are read as expected. - The
silo/directory is ignored (unknown ZIP entries are silently skipped). - On save, FreeCAD writes its standard entries. The
silo/directory survives the save because FreeCAD does not delete unknown ZIP entries. - Caveat: If FreeCAD rewrites the ZIP from scratch (rather than updating in-place), the
silo/directory may be lost. Testing confirms that FreeCAD 1.0+ preserves unknown entries, but this behavior should be monitored across upstream releases.
6. Client Implementation Layers
Implementation in the Create client is organized into four layers, each independently deliverable.
Layer 1: Format Registration (C++)
Register .kc as a recognized file type in FreeCAD's application framework.
Scope:
src/App/Application.cpp— register.kcextension alongside.fcstdin the file type map. Both extensions route to the sameopenDocument()path since the ZIP internals are structurally identical.src/Gui/FileDialog.cpp— add.kcto open/save/export dialogs. New documents default to.kc. "Save As" offers both.kcand.fcstd.src/App/Document.cpp— on save-as-.fcstd, strip thesilo/directory from the ZIP. On save-as-.kc, ensure thesilo/directory exists (createmanifest.jsonwith defaults if missing).- Platform integration —
.kcMIME type registration, file association on Linux (.desktopfile / XDG), macOS (Info.plist), and Windows (registry / NSIS installer).
Risk: Low. FreeCAD already ignores unknown ZIP entries. This layer is purely file dialog and post-save ZIP manipulation.
Acceptance criteria:
.kcfiles open in Create without errors.- "Save As .fcstd" produces a valid
.fcstdwith nosilo/directory. - "Save As .kc" produces a ZIP with at minimum
silo/manifest.json. - Double-clicking a
.kcfile on all platforms opens Create.
Layer 2: Silo Metadata Layer (Python)
A KindredDocument class in src/Mod/Create/ that wraps the loaded App::Document and manages the silo/ directory contents.
Scope:
src/Mod/Create/KindredDocument.py(new) — load/save logic for allsilo/entries.src/Mod/Create/InitGui.py— connect toApp::Documentsignals (signalSaveDocument,signalRestoreDocument) to trigger metadata load/save.
Behavior by operation:
| Operation | Action |
|---|---|
Open .kc |
Parse all silo/ entries. Expose metadata as properties on the document. |
Open .fcstd |
No-op — no silo/ directory present. KindredDocument is inactive. |
Save .kc |
Serialize current metadata into silo/ before FreeCAD writes the ZIP. |
Save .fcstd |
Skip metadata serialization. Strip silo/ if present. |
Promote .fcstd → .kc |
Generate silo/manifest.json with new UUID. Prompt for schema fields. |
Behavior by silo/ entry:
| Entry | On open | On save | On promote |
|---|---|---|---|
manifest.json |
Read instance origin, UUID, revision, schema version | Update modified_at and revision_hash |
Generate with new UUID |
metadata.json |
Load schema fields, tags, lifecycle | Serialize current state | Generate with defaults from selected schema |
history.json |
Load local revision log | Append entry if dirty | Initialize empty |
approvals.json |
Load ECO/approval snapshot | Pass-through (server authoritative) | Initialize empty |
dependencies.json |
Resolve assembly links by UUID | Update from current assembly link objects | Generate from assembly link scan |
macros/ |
Register embedded macros | Serialize bound macros | Empty directory |
inspection/ |
Load GD&T / tolerance data | Serialize annotations | Empty directory |
jobs/ |
Load job definitions for display | Serialize job YAML edits | Empty directory |
thumbnails/ |
Load Silo-rendered previews | No-op (server generates these) | Empty directory |
Risk: Medium. Signal timing relative to FreeCAD's ZIP write must be tested carefully to ensure silo/ entries are written before the archive is finalized.
Acceptance criteria:
- Opening a
.kcwith populatedsilo/metadata.jsonsurfaces schema fields in the Create UI. - Saving a
.kcpersists metadata changes across close/reopen cycles. - Promoting an
.fcstdto.kcassigns a UUID and createssilo/manifest.json.
Layer 3: Silo Workbench Integration (Python)
The Silo workbench (mods/silo/) connects .kc files to the live Silo server.
Scope:
- Commit to Silo — reads
silo/manifest.jsonfor the part UUID, uploads the.kcvia REST. Silo extracts and indexes thesilo/metadata server-side. - Checkout from Silo — downloads a
.kcwith fully populatedsilo/directory.KindredDocumenthydrates metadata on open. - Dependency resolution —
silo/dependencies.jsonstores assembly references by UUID. On opening an assembly, the workbench resolves UUIDs to local paths or triggers downloads for missing components. - Offline reconciliation — on reconnect, compare
manifest.jsonrevision hashes. Server wins on conflict unless the user explicitly forces a local override. Display a diff summary before reconciliation.
Risk: Medium. Depends on Silo server API endpoints existing for each metadata type. Can be built incrementally — start with commit/checkout of the full .kc blob, then add granular metadata sync per module.
Acceptance criteria:
- Commit/checkout round-trips a
.kcwithout metadata loss. - Assembly checkout resolves all
dependencies.jsonUUIDs to local files. - Offline edits reconcile cleanly when connection is restored.
Layer 4: Compute Job Attachment (Python)
UI for managing silo/jobs/ YAML definitions. Ties into Silo's Tier 3 compute modules.
Scope:
- Task panel in the Silo workbench for viewing, editing, and attaching job YAMLs.
- Job trigger configuration (on-commit, on-release, manual).
- Status display for running/completed jobs (fetched from Silo server).
Risk: Low (UI-only on the client side). Depends on Silo job queue infrastructure being operational.
Acceptance criteria:
- Users can attach a job YAML to a
.kcfile via the UI. - Job status is visible in the Silo workbench panel.
7. Implementation Sequence
Layers are ordered by dependency and risk:
-
Layer 1 (Format Registration) — Small C++ diff. Low risk. Immediately lets users open/save
.kcfiles even without Silo running. No functional behavior beyond file association. -
Layer 2 (Metadata Layer) — Bulk of the work. Develop incrementally: start with
manifest.jsononly, add othersilo/entries as their respective Silo modules come online. -
Layer 3 (Silo Integration) — Requires Silo server API endpoints. Build commit/checkout first, add granular metadata sync as modules mature.
-
Layer 4 (Job Attachment) — Deferred until Silo Tier 3 (Job Queue + Compute modules) is operational. The
silo/jobs/directory sits empty until then.
This sequence ensures Create is backwards-compatible with .fcstd at every step. The .kc format grows incrementally as Silo modules ship, matching the tiered dependency structure in the platform roadmap.
8. Version Migration
The kc_version field in silo/manifest.json tracks the schema version. When the .kc spec evolves:
- Additive changes (new optional
silo/entries): No migration needed. Older files simply lack the new entries. - Breaking changes (renamed fields, restructured entries): A migration function in
KindredDocumentupgradessilo/contents on open. The original file is preserved until the user explicitly saves. - Version floor: Create refuses to open
.kcfiles with akc_versionnewer than it supports, displaying an "update Create" message.
9. Security Considerations
Macro execution: silo/macros/ scripts execute with full FreeCAD Python API access. Files from untrusted sources should prompt the user before macro registration. A configurable trust policy (always trust from this Silo instance / never auto-execute / prompt each time) is exposed in Create preferences.
Job YAML injection: silo/jobs/ YAMLs specify container images and resource requests. The Silo server validates job definitions against an allowlist of approved images and resource limits before dispatching. The client does not execute jobs directly.
Metadata tampering: silo/manifest.json contains the revision hash. On commit, Silo validates the hash against its own records. Tampered manifests are rejected with a conflict error requiring re-checkout.
10. Open Questions
-
FreeCAD ZIP rewrite behavior — Confirm that FreeCAD 1.0+ preserves unknown ZIP entries on save across all platforms. If not, the
silo/directory must be re-injected post-save via a signal hook. -
Thumbnail policy — Single canonical isometric thumbnail vs. configurable multi-view renders. Impacts
silo/thumbnails/size and Headless Create compute cost. -
Offline metadata authority — How much of
silo/metadata.json(particularly lifecycle state) can be modified offline? Current proposal: lifecycle transitions require server confirmation; field edits are permitted offline and reconciled on commit. -
Assembly dependency depth — Should
silo/dependencies.jsonbe recursive (full assembly tree) or single-level (direct children only)? Single-level is simpler; recursive enables full offline assembly loading. -
Macro sandboxing — Is a restricted execution environment for
silo/macros/feasible within FreeCAD's Python runtime, or is trust-based policy the only practical option?
Appendix A: MIME Type and File Association
| Property | Value |
|---|---|
| Extension | .kc |
| MIME type | application/x-kindred-create |
| UTI (macOS) | com.kindred-systems.create.document |
| Magic bytes | PK (ZIP header, offset 0) + silo/manifest.json entry present |
| Icon | Kindred Create document icon (from icons/kindred/ asset set) |
Appendix B: Glossary
| Term | Definition |
|---|---|
.fcstd |
FreeCAD Standard file format. ZIP containing Document.xml, GuiDocument.xml, BREP cache, and thumbnails. |
.kc |
Kindred Create file format. Superset of .fcstd with a silo/ directory. |
| BREP | Boundary Representation. OpenCASCADE geometry format stored as .brp files. Derived cache, regenerable from Document.xml. |
| Promotion | Converting an .fcstd to .kc by adding a silo/ directory with at minimum manifest.json. |
| Demotion | Converting a .kc to .fcstd by stripping the silo/ directory. |
| Reconciliation | Process of merging offline .kc edits with server-side state on reconnect. |
| Schema | A Silo-defined template specifying which metadata fields exist for a given part category. |