PCLI2 Documentation
PCLI2 is the command-line client for the Physna public API: 3D geometry search, asset and folder management, metadata, and batch operations, with output that is built for scripts (JSON, CSV, Excel) as much as for people.
Chapters
- Installation Guide - Installers for every platform, updating, building from source
- Quick Start Guide - Logging in, choosing a tenant, the everyday commands
- Geometric Matching - Finding similar assets, for one asset or a whole folder
- Metadata Operations - Reading, writing and bulk-loading metadata
- Metadata Inference - Propagating metadata to geometrically similar assets
- Scripting and Automation - Machine-friendly output, JSON errors, exit codes, prompts, resumable runs, retries, CI
- Cross-Platform Configuration - Environment variables and file locations
- Documentation Deployment - How this site is built
Features
- Nested sub-commands with short aliases (
pcli2 asset ls,pcli2 folder rm) - Multiple environments (production, staging) and multiple tenants
- OAuth2 client-credentials login with automatic token renewal
- Asset upload, download, listing, deletion, reprocessing and thumbnails
- Folder tree listing, creation, renaming, moving, bulk upload and download
- Geometric, part and visual matching, single-asset or folder-wide, with CSV and Excel reports
- Metadata fields: create, read, delete, bulk-load from CSV, infer from matches
- Resumable runs: downloads skip files already on disk, uploads skip assets already in the folder, folder matches continue from a checkpoint file
- Retries with backoff for transient failures, and exit codes that say what went wrong
- Built for scripts:
--no-input,--error-format json,--safe-csv, andpcli2 doctorfor checking a setup
Start with the Installation Guide, then the Quick Start Guide.
Installation Guide
PCLI2 ships as pre-built binaries for macOS (Intel and Apple Silicon), Linux (x86_64 and aarch64) and Windows (x86_64). No Rust toolchain is needed unless you build from source.
Table of Contents
Installers
macOS and Linux: shell installer
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/jchultarsky101/pcli2/releases/latest/download/pcli2-installer.sh | sh
The script installs pcli2 and pcli2-update into ~/.cargo/bin (or the
directory it reports) and offers to add it to your PATH.
macOS and Linux: Homebrew
Homebrew 6 refuses formulae from taps it has not been told to trust, so the
first step is a one-time brew trust (per machine and user account):
brew trust jchultarsky101/pcli2
brew install jchultarsky101/pcli2/pcli2
Without it, brew install and every later brew upgrade pcli2 stop with
"Refusing to load formula jchultarsky101/pcli2/pcli2 from untrusted tap".
Homebrew 5 has no such check, but the first upgrade after moving to Homebrew 6
will. In CI, set HOMEBREW_NO_REQUIRE_TAP_TRUST=1 instead of trusting
interactively.
Windows: PowerShell installer
powershell -ExecutionPolicy Bypass -c "irm https://github.com/jchultarsky101/pcli2/releases/latest/download/pcli2-installer.ps1 | iex"
Windows: MSI
Download pcli2-x86_64-pc-windows-msvc.msi from the
latest release and run it.
Archives
Every release also carries plain archives (.tar.xz for macOS and Linux, .zip
for Windows) with the binary inside. Extract it and put it on your PATH.
Verifying the Installation
pcli2 --version
pcli2 --help
Shell completions and man pages are generated by the binary itself:
pcli2 completions zsh > ~/.zfunc/_pcli2 # or bash, fish, elvish, powershell
pcli2 man --output-dir ./man
Updating
| Installed with | Update with |
|---|---|
| Shell or PowerShell installer | pcli2-update |
| Homebrew | brew upgrade pcli2 (after the one-time brew trust jchultarsky101/pcli2 on Homebrew 6) |
| MSI | Download and run the newer MSI (the MSI does not ship the updater) |
PCLI2 prints a one-line hint on stderr when a newer release exists (at most once a
day, in terminal sessions only). Set PCLI2_NO_UPDATE_CHECK=1 to turn it off.
Building from Source
Requires a Rust toolchain (1.88 or newer) and, on Linux, pkg-config,
libssl-dev and cmake.
git clone https://github.com/jchultarsky101/pcli2.git
cd pcli2
cargo build --release
# The executable is target/release/pcli2
PCLI2 is not published on crates.io, so cargo install pcli2 does not work.
Troubleshooting
- Command not found: the install directory is not on your
PATH; the installer prints the directory it used. - An old version keeps running:
which -a pcli2(orwhere pcli2on Windows) lists every copy on thePATH; remove the stale one. - Build failures from source: update Rust with
rustup update stable.
If you are stuck, open an issue at GitHub Issues.
Quick Start Guide
This guide will help you get started with PCLI2 quickly by walking through common tasks.
Table of Contents
- Installation
- Authentication
- Basic Navigation
- Working with Assets
- Geometric Matching
- Configuration
- Choosing a Tenant
- Next Steps
- Getting Help
Authentication
Before using most PCLI2 commands, you need to authenticate with your Physna tenant. First, you'll need to obtain your API credentials.
Getting API Credentials
There are two methods to obtain your API credentials:
Method 1: Using the Physna Web Interface (Recommended)
This is the newer, more user-friendly approach available to administrators:
- Log in to your Physna instance
- (Optional) Select a tenant from the tenant selector
- Click on Settings (the gear icon in the top-right corner)
- Navigate to the Users tab
- Create a new service account
- Record the Client ID and Client Secret for use with PCLI2
Method 2: Using the API Documentation Page (Legacy)
This is the original approach using the API documentation interface:
- Navigate to the Physna OpenAPI Documentation page
- Log in with your Physna credentials
- Locate and execute the
POST /users/me/service-accountsendpoint - Record the Client ID and Client Secret from the response
Logging In
Once you have your credentials, you can authenticate with PCLI2:
# Login interactively (prompts for the client ID and secret, with
# masked input so the secret never lands in your shell history)
pcli2 auth login
# Login with client credentials
pcli2 auth login --client-id YOUR_CLIENT_ID --client-secret YOUR_CLIENT_SECRET
# Verify authentication
pcli2 auth get
Basic Navigation
Learn to navigate your Physna tenant using PCLI2:
# List available tenants
pcli2 tenant list
# List folders in the root directory (shows only direct children, not entire subtree)
pcli2 folder list
# List folders in tree format to see the complete hierarchy
pcli2 folder list --format tree
# List assets in a specific folder
pcli2 asset list --folder-path /Home/MyFolder/
Working with Assets
Asset management is a core function of PCLI2. These commands allow you to upload, retrieve, organize, and maintain your 3D models and other assets in Physna.
Uploading Assets
The asset create command uploads individual files to your Physna tenant, placing them in the specified folder path. This is useful for adding single assets to your collection:
# Upload a single asset
pcli2 asset create --input path/to/my/model.stl --folder-path /Home/MyFolder/
# Replace an existing asset (deletes the old one first)
pcli2 asset create --input path/to/my/model.stl --folder-path /Home/MyFolder/ --override
# Replace an existing asset and keep its metadata
pcli2 asset create --input path/to/my/model.stl --folder-path /Home/MyFolder/ --override --restore-metadata
For bulk operations, asset create-batch allows you to upload multiple files at once using glob patterns:
# Upload multiple assets
pcli2 asset create-batch --input "models/*.stl" --folder-path /Home/BatchUpload/
Viewing and Managing Assets
Use these commands to inspect and manage your assets:
# View asset details
pcli2 asset get --path /Home/MyFolder/model.stl
# Delete an asset
pcli2 asset delete --path /Home/MyFolder/model.stl
Geometric Matching
Geometric matching is a powerful feature that allows you to find assets with similar 3D geometry in your Physna tenant. This is particularly useful for identifying duplicate parts, finding design variations, or discovering similar components across different projects.
# Find matches for a single asset
pcli2 asset geometric-match --path /Home/Folder/ReferenceModel.stl --threshold 85.0
# Find matches for all assets in a folder (parallel processing)
pcli2 folder geometric-match --folder-path /Home/SearchFolder/ --threshold 90.0 --format csv --progress
The threshold parameter controls the similarity requirement, where higher values (closer to 100) require closer matches. The progress flag provides visual feedback during long-running operations.
Metadata Operations
Metadata is essential for organizing and searching your assets effectively. PCLI2 supports comprehensive metadata operations including creating, retrieving, updating, and deleting asset metadata. Metadata helps you categorize, filter, and find assets based on custom properties like material, supplier, weight, or any other characteristic relevant to your workflow.
Creating and Updating Metadata
The metadata create command adds or updates a single metadata field on an asset. This is useful for setting specific properties on individual assets:
# Add or update a single metadata field on an asset
pcli2 asset metadata create --path "/Home/Folder/Model.stl" --name "Material" --value "Steel" --type "text"
# Add or update multiple metadata fields on an asset
pcli2 asset metadata create --path "/Home/Folder/Model.stl" --name "Weight" --value "15.5" --type "number"
Retrieving Metadata
Use the metadata get command to view all metadata associated with an asset:
# Get all metadata for an asset
pcli2 asset metadata get --path "/Home/Folder/Model.stl"
Deleting Metadata
The metadata delete command removes specific metadata fields from an asset without affecting other metadata on the same asset:
# Delete specific metadata fields from an asset
pcli2 asset metadata delete --path "/Home/Folder/Model.stl" --name "Material" --name "Weight"
# Delete metadata fields using comma-separated list
pcli2 asset metadata delete --path "/Home/Folder/Model.stl" --name "Material,Weight,Description"
Metadata Inference
Metadata inference automatically applies metadata from a reference asset to geometrically similar assets. This feature helps you efficiently propagate metadata across similar assets, reducing manual work and ensuring consistency in your asset database:
# Apply specific metadata fields from a reference asset to similar assets
pcli2 asset metadata inference --path /Home/Folder/ReferenceModel.stl --name "Material,Cost" --threshold 85.0
# Apply metadata recursively to create chains of similar assets
# Apply multiple metadata fields with different thresholds
pcli2 asset metadata inference --path /Home/Folder/ReferenceModel.stl --name "Material" --name "Finish" --name "Supplier" --threshold 80.0
The metadata operations help you efficiently manage your asset metadata, whether you need to add, update, retrieve, or delete specific metadata fields, or propagate metadata across geometrically similar assets.
Configuration
Manage your PCLI2 configuration:
# Where the configuration file is
pcli2 config get path
# Export configuration for backup
pcli2 config export --output my-config.yaml
Multi-Environment Configuration
PCLI2 supports multiple environment configurations, allowing you to easily switch between different Physna instances (e.g., development, staging, production):
# Add a new environment configuration
pcli2 env add --name "development" \
--api-url "https://dev-api.physna.com/v3" \
--ui-url "https://dev.physna.com" \
--auth-url "https://dev-auth.physna.com/oauth2/token"
# Add a production environment
pcli2 env add --name "production" \
--api-url "https://app-api.physna.com/v3" \
--ui-url "https://app.physna.com" \
--auth-url "https://physna-app.auth.us-east-2.amazoncognito.com/oauth2/token"
# List all environments
pcli2 env list
# Switch to an environment (with interactive selection)
pcli2 env use
# Or switch to an environment by name
pcli2 env use --name development
# Get details of the active environment
pcli2 env get
# Get details of a specific environment
pcli2 env get --name production
# Reset all environment configurations
pcli2 env reset
Each environment can have its own:
- API base URL (for API calls)
- UI base URL (for comparison viewer links)
- Authentication URL (for OAuth2 token requests)
Choosing a Tenant
Most commands act on the active tenant. Pick it once; --tenant overrides it for
a single command.
# List the tenants your credentials can reach
pcli2 tenant list
# Make one active, by short name or by UUID
pcli2 tenant use --name demo
pcli2 tenant use --name 123e4567-e89b-12d3-a456-426614174000
# Show the active tenant
pcli2 tenant get
# Clear it
pcli2 tenant clear
Next Steps
- Geometric Matching for folder-wide match reports
- Metadata Operations for bulk metadata loading from CSV
- Scripting and Automation for exit codes, JSON output and CI use
- Cross-Platform Configuration for environment variables
Getting Help
For help with any command, use the built-in help system:
# Install man pages for offline reference (man pcli2, man pcli2-asset-create, ...)
mkdir -p ~/.local/share/man/man1 && pcli2 man --output-dir ~/.local/share/man/man1
# General help
pcli2 --help
# Help for a specific command group
pcli2 asset --help
# Help for a specific command
pcli2 asset create --help
You can also use the -h or --help flag with any command to get detailed usage information.
Geometric Matching
PCLI2 provides powerful geometric matching capabilities to find similar assets in your Physna tenant. This feature leverages advanced algorithms to identify assets with similar geometries, regardless of their orientation, scale, or position.
Table of Contents
- Overview
- Single Asset Matching
- Folder-Based Matching
- Direct Asset Similarity (Match Scores)
- Threshold Settings
- Performance Options
- Error Handling
- Best Practices
- Advanced Usage
- Troubleshooting
Overview
Geometric matching helps you:
- Find duplicate or near-duplicate assets
- Identify variations of the same part
- Locate similar components across different projects
- Reduce storage costs by identifying redundant assets
- Improve design workflows by finding existing similar parts
Related Features
Geometric matching serves as the foundation for other powerful capabilities:
- Metadata Inference: Automatically propagate metadata from reference assets to geometrically similar assets using
pcli2 asset metadata inference - Metadata Management: Create, update, retrieve, and delete metadata for assets using commands like
pcli2 asset metadata create,pcli2 asset metadata get, andpcli2 asset metadata delete - Part Family Management: Organize and categorize groups of similar components
- Design Optimization: Identify opportunities for part consolidation and standardization
Single Asset Matching
Find geometrically similar assets for a specific reference asset.
Basic Usage
# Find matches for a specific asset
pcli2 asset geometric-match --path /Home/Folder/ReferenceModel.stl --threshold 80.0
# Using asset UUID instead of path
pcli2 asset geometric-match --uuid 123e4567-e89b-12d3-a456-426614174000 --threshold 85.0
# Find matches with CSV output and headers
pcli2 asset geometric-match --path /Home/Folder/ReferenceModel.stl --threshold 80.0 --format csv --headers
# Find matches with CSV output, headers, and metadata
pcli2 asset geometric-match --path /Home/Folder/ReferenceModel.stl --threshold 80.0 --format csv --headers --metadata
Output Formats
JSON Format (Default)
[
{
"referenceAssetName": "ReferenceModel.stl",
"candidateAssetName": "SimilarModel.stl",
"matchPercentage": 95.75,
"referenceAssetPath": "/Home/Folder/ReferenceModel.stl",
"candidateAssetPath": "/Home/DifferentFolder/SimilarModel.stl",
"referenceAssetUuid": "123e4567-e89b-12d3-a456-426614174000",
"candidateAssetUuid": "987fc321-fedc-ba98-7654-43210fedcba9"
}
]
CSV Format
REFERENCE_ASSET_NAME,CANDIDATE_ASSET_NAME,MATCH_PERCENTAGE,REFERENCE_ASSET_PATH,CANDIDATE_ASSET_PATH,REFERENCE_ASSET_UUID,CANDIDATE_ASSET_UUID,COMPARISON_URL
ReferenceModel.stl,SimilarModel.stl,95.75,/Home/Folder/ReferenceModel.stl,/Home/DifferentFolder/SimilarModel.stl,123e4567-e89b-12d3-a456-426614174000,987fc321-fedc-ba98-7654-43210fedcba9,https://app.physna.com/tenants/demo-1/compare?asset1Id=123e4567-e89b-12d3-a456-426614174000&asset2Id=987fc321-fedc-ba98-7654-43210fedcba9&tenant1Id=68555ebf-f09c-4861-96b1-692d2ec10de7&tenant2Id=68555ebf-f09c-4861-96b1-692d2ec10de7&searchType=geometric&matchPercentage=95.75
CSV Format with Metadata
When using the --metadata flag, the output includes metadata fields from both the reference and candidate assets. This produces CSV output with additional metadata columns prefixed with REF_ for reference asset metadata and CAN_ for candidate asset metadata. The output also includes a COMPARISON_URL column that provides a link to view the comparison in the Physna UI:
REFERENCE_ASSET_PATH,CANDIDATE_ASSET_PATH,MATCH_PERCENTAGE,REFERENCE_ASSET_UUID,CANDIDATE_ASSET_UUID,COMPARISON_URL,REF_MATERIAL,CAN_MATERIAL,REF_COLOR,CAN_COLOR
/Home/Folder/ReferenceModel.stl,/Home/DifferentFolder/SimilarModel.stl,95.75,123e4567-e89b-12d3-a456-426614174000,987fc321-fedc-ba98-7654-43210fedcba9,https://app.physna.com/tenants/demo-1/compare?asset1Id=123e4567-e89b-12d3-a456-426614174000&asset2Id=987fc321-fedc-ba98-7654-43210fedcba9&tenant1Id=68555ebf-f09c-4861-96b1-692d2ec10de7&tenant2Id=68555ebf-f09c-4861-96b1-692d2ec10de7&searchType=geometric&matchPercentage=95.75,Steel,Aluminum,Red,Blue
All metadata fields from all matched assets are included as columns, with empty values for assets that don't have a particular metadata field.
Complete Examples
Here are complete examples showing the command with and without the --metadata flag:
Without metadata:
pcli2 asset geometric-match --path /Home/Folder/ReferenceModel.stl --threshold 80.0 --format csv --headers
Output:
REFERENCE_ASSET_PATH,CANDIDATE_ASSET_PATH,MATCH_PERCENTAGE,REFERENCE_ASSET_UUID,CANDIDATE_ASSET_UUID,COMPARISON_URL
/Home/Folder/ReferenceModel.stl,/Home/DifferentFolder/SimilarModel.stl,95.75,123e4567-e89b-12d3-a456-426614174000,987fc321-fedc-ba98-7654-43210fedcba9,https://app.physna.com/tenants/demo-1/compare?asset1Id=123e4567-e89b-12d3-a456-426614174000&asset2Id=987fc321-fedc-ba98-7654-43210fedcba9&tenant1Id=68555ebf-f09c-4861-96b1-692d2ec10de7&tenant2Id=68555ebf-f09c-4861-96b1-692d2ec10de7&searchType=geometric&matchPercentage=95.75
With metadata:
pcli2 asset geometric-match --path /Home/Folder/ReferenceModel.stl --threshold 80.0 --format csv --headers --metadata
Output:
REFERENCE_ASSET_PATH,CANDIDATE_ASSET_PATH,MATCH_PERCENTAGE,REFERENCE_ASSET_UUID,CANDIDATE_ASSET_UUID,COMPARISON_URL,REF_MATERIAL,CAN_MATERIAL,REF_COLOR,CAN_COLOR
/Home/Folder/ReferenceModel.stl,/Home/DifferentFolder/SimilarModel.stl,95.75,123e4567-e89b-12d3-a456-426614174000,987fc321-fedc-ba98-7654-43210fedcba9,https://app.physna.com/tenants/demo-1/compare?asset1Id=123e4567-e89b-12d3-a456-426614174000&asset2Id=987fc321-fedc-ba98-7654-43210fedcba9&tenant1Id=68555ebf-f09c-4861-96b1-692d2ec10de7&tenant2Id=68555ebf-f09c-4861-96b1-692d2ec10de7&searchType=geometric&matchPercentage=95.75,Steel,Aluminum,Red,Blue
Threshold Settings
The threshold parameter controls the minimum similarity percentage required for a match:
- 0.0 - Return all possible matches (may include unrelated assets)
- 50.0 - Very loose matching (many potential matches)
- 80.0 - Default setting (good balance of accuracy and recall)
- 90.0 - Strict matching (high confidence matches)
- 95.0+ - Very strict matching (near duplicates only)
Folder-Based Matching
Find geometrically similar assets for all assets in a specified folder. This command processes assets in parallel for improved performance.
Basic Usage
# Find matches for all assets in a folder
pcli2 folder geometric-match --folder-path /Home/SearchFolder/ --threshold 85.0
Including Subfolders
By default only the assets sitting directly in the named folder are matched. A folder that holds nothing but subfolders therefore produces no report:
# /Creo Files contains 8 subfolders and no assets of its own
pcli2 folder geometric-match --folder-path "/Creo Files" --threshold 85.0
# ❌ Error: No assets found directly in the specified folder(s)
# 1. The folder(s) contain 8 subfolder(s) - pass --recursive to include the assets in them
Pass --recursive (-R) to walk the whole subtree:
# Matches every asset under /Creo Files, including all of its subfolders
pcli2 folder geometric-match --folder-path "/Creo Files" --threshold 85.0 --recursive
--recursivecan widen the scope dramatically — a folder with one asset of its own may have thousands underneath it, and each one costs a search. Raise--concurrent(up to 10) to speed it up, or name a deeper folder to narrow the scope.
The same flag is available on folder part-match and folder visual-match.
Comparison Viewer URL
Both geometric-match and folder geometric-match commands include a comparison URL in their output that allows you to view the geometric match in the Physna UI. The URL is available in both JSON and CSV formats:
- JSON: The field is named
comparisonUrl - CSV: The column is named
COMPARISON_URL
The URL follows this format:
https://app.physna.com/tenants/{tenant_short_name}/compare?asset1Id={reference_asset_uuid}&asset2Id={candidate_asset_uuid}&tenant1Id={tenant_uuid}&tenant2Id={tenant_uuid}&searchType=geometric&matchPercentage={match_percentage}
Excel (XLSX) Output
In addition to json and csv, the folder match command supports --format xls,
which writes a color-highlighted Excel workbook designed for a human reader.
It contains exactly the same columns, in the same order, as the CSV output
(always including the REF_/CAN_ metadata pairs), rendered with visual aids
that make a large report easy to scan:
- Frozen headers and identity columns — the two header rows and the leading reference path, candidate path, and match-percentage columns stay in view while you scroll a wide, tall report.
- Grouped metadata pairs — each
REF_<field>/CAN_<field>pair is boxed and labeled once with the field name (e.g.MATERIALover aREFand aCANsub-column), so the reference/candidate pairs stand out among the plain columns. - Metadata diff highlighting — for every pair, both cells are shaded: 🟩 green when the two values match, 🟥 red when they differ, and 🟨 amber when a value is present on only one side.
- Match-score heat map — the
MATCH_PERCENTAGEcolumn is shaded on a gradient (cool at 0%, through yellow at 50%, to red-hot at 100%) and the rows are sorted by match percentage, highest first. - Clickable comparison links —
COMPARISON_URLis the last column (its long value is rarely read, so the metadata columns come before it), written as a hyperlink you can click to open the side-by-side comparison in a browser.
Because Excel is a binary format, xls writes to a file rather than standard
output. Use --output (or -o) to choose the path; if omitted, the workbook is
written to match_report.xlsx in the current directory. The extension is always
normalized to .xlsx (the modern Office Open XML format); if it had to be
changed, a warning is printed to stderr. On success the command follows the
UNIX convention of printing nothing to stdout.
# Write a highlighted Excel report for a folder
pcli2 folder geometric-match --folder-path /Home/SearchFolder/ --threshold 80.0 --format xls --output report.xlsx
# Multiple folders, default output filename (match_report.xlsx)
pcli2 folder geometric-match --folder-path /Home/FolderA/ --folder-path /Home/FolderB/ --format xls
The
xlsformat always includes metadata (the metadata diff is its whole point), so the--metadataflag is implied and does not need to be passed.
Performance Options
Concurrency Control
Control how many simultaneous operations are performed (range: 1-10, default: 1):
# Use 8 concurrent operations (default is 1, maximum is 10)
pcli2 folder geometric-match --folder-path /Home/SearchFolder/ --concurrent 8
# Use the default (1 concurrent operation)
pcli2 folder geometric-match --folder-path /Home/SearchFolder/
# Invalid values will cause the command to fail
pcli2 folder geometric-match --folder-path /Home/SearchFolder/ --concurrent 15
# This will show an error: "Invalid value for '--concurrent': must be between 1 and 10, got 15"
Progress Tracking
Display progress information during long-running operations:
# Show progress information
pcli2 folder geometric-match --folder-path /Home/SearchFolder/ --progress
# Combine with concurrency to show multiple progress bars (one per concurrent operation)
pcli2 folder geometric-match --folder-path /Home/SearchFolder/ --concurrent 8 --progress
When using both --concurrent and --progress flags together, the command will display:
- An overall progress bar showing the total completion percentage
- Individual progress bars for each concurrent operation showing which assets are being processed
- Status messages indicating the current stage of each operation (starting search, processing matches, completion)
With --recursive, --progress also covers the folder scan that happens before
any matching starts. A deep tree costs one API call per folder, so this phase can
run for a while on its own:
⠹ Scanning /Creo Files: 46/312 folders, 1174 assets found
followed by a summary once the scan completes:
Scanned 1 folder path(s), found 3182 asset(s) to match
All of this goes to stderr, so piping stdout to a file or another command is
unaffected. Without --progress the scan is silent.
Performance Options
Concurrency and Progress Combined
For optimal performance monitoring, combine both options:
# Use 10 concurrent operations with detailed progress tracking
pcli2 folder geometric-match --folder-path /Home/SearchFolder/ --concurrent 10 --progress
# Combine with other options
pcli2 folder geometric-match --folder-path /Home/SearchFolder/ --threshold 85.0 --concurrent 8 --progress
Resuming an Interrupted Run
A match over a large tenant can run for hours, and until the report is written
nothing has been saved. --checkpoint FILE changes that: every asset's result
is appended to FILE the moment its search finishes, and re-running the same
command with the same file reuses what was recorded and searches only the
assets that are left.
# First attempt - interrupted after two hours
pcli2 folder geometric-match --folder-path "/Creo Files" --recursive \
--threshold 85 --concurrent 8 --progress \
--checkpoint creo-match.jsonl --format csv --headers > creo-matches.csv
# Same command again: picks up where it stopped
pcli2 folder geometric-match --folder-path "/Creo Files" --recursive \
--threshold 85 --concurrent 8 --progress \
--checkpoint creo-match.jsonl --format csv --headers > creo-matches.csv
On the second run stderr reports what was reused:
Resuming from checkpoint 'creo-match.jsonl': 2,431 of 3,182 asset(s) already searched
Points worth knowing:
- The file is tied to the exact run: search type, tenant, folder paths,
--threshold,--recursive,--exclusiveand (for visual search)--limit. A file written by a different combination is refused with a message naming the run it belongs to; delete it or pick another path. - Only successful searches are recorded. An asset whose search failed is
searched again on the next run, which is also how a run that stopped on
authentication failures is completed after
pcli2 auth login. - The file is deleted once the report has been written successfully. It stays if the report fails - for example an Excel workbook too tall for a worksheet - so the same searches are not repeated after fixing the output options.
- The output format is not part of the fingerprint: an interrupted CSV run can be finished as JSON or Excel.
- Assets added to the folder between runs are searched; assets removed are dropped from the report.
part-match and visual-match take the same option.
Handling Large Folders
For folders with many assets, consider these strategies:
- Use a checkpoint:
--checkpoint FILEmakes an interruption cost minutes instead of hours - Adjust threshold: Higher thresholds reduce processing time
- Increase concurrency: Use more concurrent operations (but watch resource usage)
- Process in batches: Break large folders into smaller subfolders
Direct Asset Similarity (Match Scores)
While geometric-match searches your tenant for assets similar to a single
reference, asset similarity compares two specific assets and returns the
pairwise match scores between them. Use it when you already know both assets you
want to compare.
Each asset can be identified by either its UUID or its path — PCLI2 resolves paths to UUIDs automatically:
- Reference (source) asset:
--reference-uuidor--reference-path - Candidate (target) asset:
--candidate-uuidor--candidate-path
Both assets must be 3D models in a finished state, and they must be different assets (comparing an asset with itself is rejected by the API).
Basic Usage
# Compare two assets by path
pcli2 asset similarity \
--reference-path /Home/Folder/block1.stl \
--candidate-path /Home/Folder/block2.stl
# Mix identifiers: reference by UUID, candidate by path
pcli2 asset similarity \
--reference-uuid 123e4567-e89b-12d3-a456-426614174000 \
--candidate-path /Home/Folder/block2.stl
# CSV output with headers
pcli2 asset similarity \
--reference-path /Home/Folder/block1.stl \
--candidate-path /Home/Folder/block2.stl \
--format csv --headers
The command is also available under the alias
pcli2 asset match-scores.
Output Formats
JSON Format (Default)
{
"referenceAssetPath": "/Home/Folder/block1.stl",
"referenceAssetUuid": "123e4567-e89b-12d3-a456-426614174000",
"candidateAssetPath": "/Home/Folder/block2.stl",
"candidateAssetUuid": "987fc321-fedc-ba98-7654-43210fedcba9",
"geometric": {
"matchPercentage": 90.21,
"forwardMatchPercentage": 86.58,
"reverseMatchPercentage": 86.58
},
"comparisonUrl": "https://app.physna.com/tenants/demo-1/compare?asset1Id=123e4567-e89b-12d3-a456-426614174000&asset2Id=987fc321-fedc-ba98-7654-43210fedcba9&tenant1Id=tenant-uuid&tenant2Id=tenant-uuid&searchType=geometric&matchPercentage=90.21"
}
The geometric scores describe how similar the two models are:
- matchPercentage: Overall geometric similarity (100% = geometrically identical)
- forwardMatchPercentage: How much of the reference asset's geometry exists in the candidate
- reverseMatchPercentage: How much of the candidate asset's geometry exists in the reference
A volumetric object (with its own matchPercentage) is included only when
volumetric scoring is enabled for your tenant; otherwise it is omitted. Contact
Physna sales to enable volumetric scoring.
CSV Format
REFERENCE_ASSET_PATH,CANDIDATE_ASSET_PATH,MATCH_PERCENTAGE,FORWARD_MATCH_PERCENTAGE,REVERSE_MATCH_PERCENTAGE,VOLUMETRIC_MATCH_PERCENTAGE,REFERENCE_ASSET_UUID,CANDIDATE_ASSET_UUID,COMPARISON_URL
/Home/Folder/block1.stl,/Home/Folder/block2.stl,90.21,86.58,86.58,,123e4567-e89b-12d3-a456-426614174000,987fc321-fedc-ba98-7654-43210fedcba9,https://app.physna.com/tenants/demo-1/compare?asset1Id=123e4567-e89b-12d3-a456-426614174000&asset2Id=987fc321-fedc-ba98-7654-43210fedcba9&tenant1Id=tenant-uuid&tenant2Id=tenant-uuid&searchType=geometric&matchPercentage=90.21
The VOLUMETRIC_MATCH_PERCENTAGE column is empty unless volumetric scoring is
enabled for your tenant.
Error Handling
Common Errors
HTTP 409 Conflict
A 409 from the search endpoint means the asset cannot be searched in its current state: it is still indexing, has no 3D data, or failed to index. This is a property of the tenant, not of the run, so the asset is counted as "not searchable" in the summary and the run continues; it is not retried. Transient failures (connection errors, 408/429/502/503/504) are retried with backoff, and a 401/403 triggers one token renewal and retry. A run that loses more than 10% of its searches to operational failures, or that is stopped by repeated authentication failures, exits 69 rather than producing a report that looks complete.
Permission Denied
When you don't have permission to perform geometric search:
ERROR: Error: Access forbidden. You don't have permission to perform geometric search on this asset.
Check your tenant permissions and API credentials.
Asset Not Found
When the specified asset or folder cannot be found:
ERROR: The asset with ID 'XXX' cannot be found in tenant 'YYY'
Verify the asset path or UUID is correct.
Best Practices
Optimizing Performance
- Use appropriate thresholds: Start with 80-85% and adjust based on results
- Limit search scope: Use specific folders rather than searching entire tenants
- Monitor resource usage: Adjust concurrency based on your system capabilities
- Use progress tracking: Monitor long-running operations
Interpreting Results
- High match percentages (>95%): Likely duplicates or very similar assets
- Medium match percentages (80-95%): Similar geometry with variations
- Low match percentages (<80%): May be false positives or loosely related
Automation Tips
- Schedule regular deduplication: Run geometric matching periodically to identify duplicates
- Integrate with CI/CD: Use geometric matching in automated workflows
- Export results: Use CSV format for easy analysis in spreadsheets
Advanced Usage
Scripting Examples
Bash Script for Regular Deduplication
#!/bin/bash
# deduplicate.sh
FOLDERS=("/Home/ProjectA/" "/Home/ProjectB/" "/Home/Archive/")
THRESHOLD=95.0
CONCURRENT=8 # Number of concurrent operations
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
for folder in "${FOLDERS[@]}"; do
echo "Processing folder: $folder"
pcli2 folder geometric-match \
--folder-path "$folder" \
--threshold $THRESHOLD \
--concurrent $CONCURRENT \
--format csv \
--progress \
> "duplicates_${folder//\//_}_$TIMESTAMP.csv"
done
echo "Deduplication complete. Results saved to CSV files."
PowerShell Script for Windows
# deduplicate.ps1
$Folders = @("/Home/ProjectA/", "/Home/ProjectB/", "/Home/Archive/")
$Threshold = 95.0
$Concurrent = 8 # Number of concurrent operations
$Timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
foreach ($folder in $Folders) {
Write-Host "Processing folder: $folder"
pcli2 folder geometric-match `
--folder-path $folder `
--threshold $Threshold `
--concurrent $Concurrent `
--format csv `
--progress `
> "duplicates_$($folder.Replace('/', '_'))_$Timestamp.csv"
}
Write-Host "Deduplication complete. Results saved to CSV files."
Troubleshooting
Performance Issues
If matching operations are taking too long:
- Reduce concurrency: Lower the
--concurrentvalue - Increase threshold: Use higher threshold values to reduce matches
- Check network: Ensure good connectivity to the Physna API
- Monitor server status: Check if the Physna service is experiencing issues
Incomplete Results
If you're not seeing expected matches:
- Lower threshold: Try lower threshold values
- Check asset types: Ensure assets are compatible geometric file types
- Verify permissions: Confirm you have access to all assets in the search scope
- Contact support: If issues persist, reach out to Physna support
Related Commands
asset geometric-match- Find matches for a single assetfolder geometric-match- Find matches for all assets in a folderasset similarity- Get pairwise match scores between two specific assets (alias:asset match-scores)asset list- List assets in a folderasset get- Get detailed asset information
Use pcli2 asset geometric-match --help, pcli2 folder geometric-match --help, and pcli2 asset similarity --help for detailed command information.
Metadata Operations
PCLI2 provides comprehensive metadata operations for managing asset metadata including creating, retrieving, updating, and deleting asset metadata.
Overview
Metadata is essential for organizing and searching your assets effectively. PCLI2 supports comprehensive metadata operations to help you manage your asset metadata efficiently.
Metadata Operations
PCLI2 provides several commands for working with asset metadata:
1. Create/Update Individual Asset Metadata
Add or update a single metadata field on an asset:
# Add or update a single metadata field on an asset
pcli2 asset metadata create --path "/Home/Folder/Model.stl" --name "Material" --value "Steel" --type "text"
# Add or update a single metadata field on an asset by UUID
pcli2 asset metadata create --uuid "123e4567-e89b-12d3-a456-426614174000" --name "Weight" --value "15.5" --type "number"
2. Retrieve Asset Metadata
Get all metadata for an asset:
# Get all metadata for an asset in JSON format (default)
pcli2 asset metadata get --path "/Home/Folder/Model.stl"
# Get all metadata for an asset in CSV format (suitable for batch operations)
pcli2 asset metadata get --uuid "123e4567-e89b-12d3-a456-426614174000" --format csv
3. Delete Asset Metadata
Delete specific metadata fields from an asset:
# Delete specific metadata fields from an asset
pcli2 asset metadata delete --path "/Home/Folder/Model.stl" --name "Material" --name "Weight"
# Delete metadata fields using comma-separated list
pcli2 asset metadata delete --uuid "123e4567-e89b-12d3-a456-426614174000" --name "Material,Weight,Description"
The delete command now uses the dedicated API endpoint to properly remove metadata fields from assets, rather than fetching all metadata and re-updating the asset without the specified fields. This provides more efficient and accurate metadata deletion.
4. Create/Update Metadata for Multiple Assets
Create or update metadata for multiple assets from a CSV file:
# Create or update metadata for multiple assets from a CSV file
pcli2 asset metadata create-batch --input "metadata.csv"
CSV Formats for Batch Metadata Operations
The create-batch command accepts two CSV layouts. The layout is detected automatically from the header row: if any column name starts with metadata:, the file is treated as the UI (horizontal) format; otherwise it is treated as the classic (vertical) format. You can also force a layout explicitly with --csv-format classic or --csv-format ui (the default is --csv-format auto).
In both layouts, empty values are skipped by default: the existing metadata field on the asset, if any, is left untouched, so a sparse file can be used to incrementally add or update fields. Pass --delete-if-empty to instead delete a metadata field from the asset when the file contains an empty value for it — useful when replacing an asset's metadata wholesale.
Classic (Vertical) Format
The classic CSV format used by asset metadata get --format csv and asset metadata create-batch --input is designed for seamless round-trip operations:
ASSET_PATH,NAME,VALUE,TYPE
/Home/Folder/Model1.stl,Material,Steel,text
/Home/Folder/Model1.stl,Weight,15.5,number
/Home/Folder/Model2.ipt,Inventory Qty,42,number
/Home/Folder/Model2.ipt,Supplier Link,https://example.com/,url
/Home/Folder/Model2.ipt,Exportable,true,boolean
The CSV format specifications:
- Header Row: Must contain
ASSET_PATH,NAME,VALUEin that order, optionally followed byTYPE - ASSET_PATH: Path to the asset in Physna (e.g.,
/Home/Folder/Model.stl). A leading/Home— the name Physna shows for the root folder — is treated as the root, so/Home/NX/part.prt,/NX/part.prt, andNX/part.prtall refer to the same asset - NAME: Name of the metadata field to set
- VALUE: Value to assign to the metadata field. Values are automatically coerced to the field's type (see Metadata Field Types). An empty value is skipped by default, or deletes the field from the asset when
--delete-if-emptyis passed - TYPE (optional): One of
text(default),number,boolean, orurl. This only governs the type used when registering a new field; for a field that already exists in Physna, the existing registered type is authoritative and theTYPEcolumn is ignored. The column is optional per row — some rows may include it and others may omit it - File Encoding: Must be UTF-8 encoded
- Quoting: Values containing commas, quotes, or newlines must be enclosed in double quotes
- Escaping: Double quotes within values must be escaped by doubling them (e.g.,
"15.5"" diameter") - Empty Rows: Will be ignored during processing
- Multiple Fields: If an asset has multiple metadata fields to update, include multiple rows with the same ASSET_PATH but different NAME and VALUE combinations
Example Command:
# Create/update metadata for multiple assets from a CSV file
pcli2 asset metadata create-batch --input "metadata.csv"
Deleting metadata fields via CSV:
Pass --delete-if-empty and leave the VALUE column empty to remove a metadata field from an asset:
ASSET_PATH,NAME,VALUE
/Home/Folder/Model1.stl,ObsoleteField,
/Home/Folder/Model1.stl,Material,Steel
pcli2 asset metadata create-batch --input "metadata.csv" --delete-if-empty
In the example above, ObsoleteField is deleted and Material is set to Steel in a single pass. Without --delete-if-empty, the ObsoleteField row would be skipped with a warning and only Material would be updated.
Note: The create-batch command groups all rows by asset path, then issues deletes (empty values, when --delete-if-empty is passed) followed by updates (non-empty values) per asset in one batch. Multiple rows with the same ASSET_PATH are combined into a single API interaction.
UI (Horizontal) Format
The Physna web UI's bulk metadata upload uses a horizontal layout with one row per asset and one column per metadata field. create-batch accepts these files directly:
"path","id","metadata:Material","metadata:Color","metadata:Weight"
"/domain/assets/part1.sldprt","123e4567-e89b-12d3-a456-426614174000","Steel","Blue","2.5kg"
"/domain/assets/part2.step","","Aluminum","Red","1.2kg"
"/domain/assets/assembly.sldasm","","Mixed","",""
The UI format specifications:
- path: Full path to the asset in Physna
- id: Optional asset UUID. When present and non-empty, it takes precedence over the path and is used directly, without path resolution. An invalid UUID is an error (there is no fallback to the path, since that could silently target a different asset)
- metadata:<field name>: One column per metadata field. The
metadata:prefix is stripped to obtain the field name - Empty metadata cells: Skipped by default — the existing field value on the asset, if any, is left untouched. With
--delete-if-empty, an empty cell deletes the field from the asset instead - Other columns: Any column that is not
path,id, ormetadata:*is ignored, with a warning listing the ignored columns - Row identification: Each row must provide a UUID or a path; a row with neither is an error
The whole file is parsed and validated before any API call is made, so a malformed file (e.g. an invalid UUID) fails fast with a line-numbered error instead of half-applying.
# Auto-detected from the header row
pcli2 asset metadata create-batch --input "ui-export.csv"
# Or forced explicitly
pcli2 asset metadata create-batch --input "ui-export.csv" --csv-format ui
Listing a Tenant's Registered Metadata Fields
Metadata fields are registered per tenant, each with a name and a type. Use
tenant metadata list to see every field currently registered in the active
tenant:
# JSON (default)
pcli2 tenant metadata list
# CSV, ready to turn into a create-batch file
pcli2 tenant metadata list --format csv --headers
The CSV output uses the same column headers as the classic create-batch
input (ASSET_PATH,NAME,VALUE,TYPE), with NAME and TYPE filled from the
registry and ASSET_PATH and VALUE left blank:
ASSET_PATH,NAME,VALUE,TYPE
,Description,,text
,Exportable,,boolean
,Inventory Qty,,number
,Supplier Link,,url
,Unit Price ($),,number
This makes it easy to build a batch-upload template: save the listing, then for
each asset fill in ASSET_PATH and VALUE (replicating the field rows per
asset). Because values are coerced to each field's registered type, you do not
need to touch the TYPE column for fields that already exist.
# Save the field list as a starting template
pcli2 tenant metadata list --format csv --headers > fields.csv
Advanced Metadata Workflow: Export, Modify, Reimport
One of the most powerful features of PCLI2 is the ability to export metadata, modify it externally, and reimport it:
-
Export Metadata:
# Export all metadata for an asset to a CSV file pcli2 asset metadata get --path "/Home/Folder/Model.stl" --format csv > model_metadata.csv # Export metadata for multiple assets in a folder pcli2 asset list --folder-path "/Home/Folder/" --metadata --format csv > folder_metadata.csv -
Modify Metadata Externally:
- Open the CSV file in a spreadsheet application (Excel, Google Sheets, etc.)
- Make the desired changes to metadata values
- To delete a field, clear its VALUE cell (leave it blank) and reimport with
--delete-if-empty - Save the file in CSV format
-
Reimport Modified Metadata:
# Update assets with modified metadata (blank values are skipped) pcli2 asset metadata create-batch --input "modified_metadata.csv" # Or replace metadata wholesale: blank values delete the field from the asset pcli2 asset metadata create-batch --input "modified_metadata.csv" --delete-if-empty
This workflow enables powerful bulk metadata operations while maintaining the flexibility to use familiar spreadsheet tools for data manipulation.
Metadata Field Types
PCLI2 supports four metadata field types:
-
Text (default): String values
pcli2 asset metadata create --path "/Home/Model.stl" --name "Description" --value "Sample part description" --type "text" -
Number: Numeric values
pcli2 asset metadata create --path "/Home/Model.stl" --name "Weight" --value "15.5" --type "number" -
Boolean: True/False values
pcli2 asset metadata create --path "/Home/Model.stl" --name "Approved" --value "true" --type "boolean" -
URL: Link values (stored as a string)
pcli2 asset metadata create --path "/Home/Model.stl" --name "Supplier Link" --value "https://example.com/" --type "url"
Automatic type coercion
Every metadata field in a tenant is registered with a type, and the Physna API
rejects a value whose JSON type does not match. Because a CSV cell is just text,
PCLI2 coerces each value to the field's registered type before sending it —
so create-batch works against typed fields without you having to declare
anything:
- A
numberfield receives18(a JSON number) rather than the string"18";84.50is sent as84.5 - A
booleanfield acceptstrue/false,1/0,yes/no,on/off(case-insensitive) textandurlfields store the value as a string
If a value cannot be represented as the field's type — for example the text
N/A for a number field — that row is a type conflict and is reported as
an error (see create-batch Error Behavior).
The registered type always wins. The
--typeflag (singlecreate) and theTYPEcolumn (batch) only decide the type used when a field is registered for the first time; they cannot change the type of an existing field. To change a field's type, delete and recreate it.
Best Practices
- Use Descriptive Names: Choose clear, consistent names for metadata fields across your organization
- Validate Data Types: Ensure values match the expected data type for each field
- Batch Operations: Use CSV batch operations for large-scale metadata updates
- Backup Before Bulk Operations: Export metadata before performing bulk deletions
- Test First: Use small test sets before applying operations to large asset collections
- Use Proper Authentication: Ensure your credentials have appropriate permissions for metadata operations
Error Handling
Metadata operations provide detailed error messages, retry transient network failures internally, and validate input formats before processing.
create-batch Error Behavior
By default, asset metadata create-batch stops on the first error and prints a summary of how many assets were processed successfully. This makes failures visible instead of letting a batch silently complete with partial results.
Specifically:
- CSV parsing errors: always terminate immediately — the input file is expected to be well-formed
- Unresolvable asset paths (asset not found): by default, terminates the batch. Pass
--continue-on-errorto skip the failing asset and continue with the remaining rows - Metadata update/delete failures, including type conflicts (a value that cannot be represented as the field's registered type): by default, terminate the batch. Pass
--continue-on-errorto skip the offending asset and continue with the remaining rows - Authentication failures: always terminate with a remediation message directing the user to re-authenticate, regardless of
--continue-on-error
With --continue-on-error, skipped assets are reported with a concise warning as they are encountered, and the final summary reports how many assets succeeded and how many failed.
Example — skip both unresolvable paths and conflicting values:
pcli2 asset metadata create-batch --input "metadata.csv" --continue-on-error
On completion (or termination), a summary is printed to stderr showing the number of successful and failed assets.
Performance Considerations
Large-Scale Operations
For bulk metadata operations:
# Process during off-peak hours
pcli2 asset metadata create-batch --input "large_metadata.csv"
Monitoring Progress
Monitor progress during long-running operations:
# Show progress during batch operations
pcli2 asset metadata create-batch --input "metadata.csv" --progress
Integration with Other Commands
Metadata operations work seamlessly with other PCLI2 commands:
# Chain with asset operations
pcli2 asset list --folder-path "/Home/Parts/" --format csv | \
pcli2 asset metadata create-batch --input "metadata_updates.csv"
# Export results for auditing
pcli2 asset metadata get --path "/Home/Parts/Model.stl" --format csv > metadata_export.csv
Limitations
- API Rate Limits: Extensive operations may be rate-limited by the Physna API
- Processing Time: Large batch operations can take considerable time
- Metadata Types: Supports text, number, boolean, and url metadata fields
- Asset Access: Can only process assets accessible to your authenticated user
- Field Names: Metadata field names must be unique per asset and follow Physna naming conventions
Always test operations on a small scale before running them on large datasets.
Metadata Inference
The metadata inference feature allows you to automatically apply metadata from a reference asset to geometrically similar assets, significantly reducing manual metadata entry work.
Overview
Metadata inference works by:
- Taking a reference asset and specified metadata fields
- Finding geometrically similar assets using the Physna geometric search
- Applying the reference metadata to matching assets
This is particularly useful for applying common metadata like materials, categories, suppliers, or costs to families of similar parts.
Basic Usage
Apply metadata from a reference asset to similar assets:
pcli2 asset metadata inference --path /Home/Parts/Bolt-M8x20.stl --name "Material" --threshold 90.0
This command will:
- Find the asset at
/Home/Parts/Bolt-M8x20.stl - Extract the "Material" metadata field value
- Find all assets with 90% or higher geometric similarity
- Apply the same "Material" value to all matching assets
Specifying Multiple Metadata Fields
You can apply multiple metadata fields in a single operation:
# Using comma-separated values
pcli2 asset metadata inference --path /Home/Parts/BaseModel.stl --name "Material,Cost,Supplier" --threshold 85.0
# Using multiple --name flags
pcli2 asset metadata inference --path /Home/Parts/BaseModel.stl --name "Material" --name "Cost" --name "Supplier" --threshold 85.0
Threshold Values
The threshold parameter controls the similarity requirement for matching assets:
- Range: 0.00 to 100.00
- Higher values: More stringent matching (fewer but more similar matches)
- Lower values: More permissive matching (more but less similar matches)
- Recommended starting point: 80.00-85.00 for most use cases
# Very strict matching (high similarity required)
pcli2 asset metadata inference --path /Home/Parts/Reference.stl --name "CriticalField" --threshold 95.0
# Liberal matching (find more potential matches)
pcli2 asset metadata inference --path /Home/Parts/Reference.stl --name "GeneralField" --threshold 75.0
Practical Examples
Applying Standard Materials
# Apply standard material to a family of similar bolts
pcli2 asset metadata inference --path /Home/StandardParts/Bolt-M8x20.stl --name "Material" --threshold 92.0
Categorizing Product Lines
# Assign category and supplier information to a product family
pcli2 asset metadata inference --path /Home/ProductLine/MainAssembly.stl --name "Category,Supplier,Division" --threshold 85.0
Cost Propagation
# Apply estimated costs to similar components
pcli2 asset metadata inference --path /Home/Components/ReferenceBracket.stl --name "EstimatedCost,Currency" --threshold 88.0
Best Practices
1. Start with Conservative Thresholds
Begin with higher threshold values (85-90%) to ensure high-quality matches, then adjust based on results:
pcli2 asset metadata inference --path /Home/Parts/Reference.stl --name "Material" --threshold 90.0
2. Test with Non-Critical Metadata
Start by applying metadata to non-critical fields to understand the matching behavior:
pcli2 asset metadata inference --path /Home/Test/Reference.stl --name "TestTag" --threshold 85.0
3. Combine with Geometric Matching
Use geometric matching first to preview results, then apply metadata inference:
# Preview matches
pcli2 asset geometric-match --path /Home/Parts/Reference.stl --threshold 85.0 --format csv
# Apply metadata if preview looks good
pcli2 asset metadata inference --path /Home/Parts/Reference.stl --name "Material" --threshold 85.0
Error Handling
The metadata inference command is designed to be resilient:
- Continues processing even if individual asset operations fail
- Provides detailed error messages for troubleshooting
- Automatically skips inaccessible assets
Common error scenarios and their handling:
- Missing reference asset: Command aborts with clear error message
- Network failures: Individual operations retry, overall process continues
- Permission issues: Skips problematic assets with warning messages
- Invalid metadata: Logs error but continues processing other assets
Performance Considerations
Large-Scale Operations
For bulk metadata inference operations:
# Process during off-peak hours
pcli2 asset metadata inference --path /Home/LargeAssembly/Reference.stl --name "Category" --threshold 80.0
Monitoring Progress
Monitor progress during long-running operations using the available flags:
pcli2 asset metadata inference --path /Home/Parts/Reference.stl --name "Material" --threshold 85.0
Integration with Other Commands
Metadata inference works seamlessly with other PCLI2 commands:
# Chain with folder operations
pcli2 folder list --folder-path /Home/ProductLine/ | \
pcli2 asset metadata inference --name "ProductLine" --threshold 85.0
# Export results for auditing
pcli2 asset metadata inference --path /Home/Parts/Reference.stl --name "Category" --threshold 85.0 \
--format csv > metadata_propagation_log.csv
Limitations
- API Rate Limits: Large operations may be rate-limited by the Physna API
- Processing Time: Large operations can take considerable time
- Metadata Types: Only supports text, number, and boolean metadata fields
- Asset Access: Can only process assets accessible to your authenticated user
Always test operations on a small scale before running them on large datasets.
Scripting and Automation
PCLI2 is designed to work well in shell scripts, cron jobs, and CI/CD pipelines. This page collects the features that matter when no human is watching the terminal.
Table of Contents
- Machine-Friendly Output
- Skipping Prompts
- Dry Run Mode
- Exit Codes
- Verbosity Control
- Automatic Retries
- Update Notifications
- CI/CD Example
Machine-Friendly Output
Colors, spinners, and progress bars are shown only when the output is a terminal. When you pipe or redirect output, you get clean text automatically:
# Clean JSON, no ANSI escape codes
pcli2 asset list --folder-path "/Home/Models/" --format json | jq '.[].name'
# CSV with headers for spreadsheets
pcli2 asset list --folder-path "/Home/Models/" --format csv --headers > assets.csv
To disable colors explicitly, use the --no-color flag or set the
NO_COLOR (or PCLI2_NO_COLOR) environment variable.
The same rules apply to diagnostics on stderr: warnings and --verbose
logs captured with 2> warnings.log are plain text with no ANSI escape
codes, so they can be grepped and parsed directly.
Safe CSV for Spreadsheets
A CSV cell that starts with =, +, - or @ is evaluated as a formula by
Excel, LibreOffice and Google Sheets when the file is opened, and asset names
and metadata values come from whoever uploaded them. With --safe-csv (or
PCLI2_SAFE_CSV=1) such cells are written with a leading single quote, which
spreadsheets show as plain text. Values that are numbers, such as -5, are
left alone. The default is off because the quote is visible to every other
consumer of the file.
pcli2 asset list --folder-path "/Home/Parts" --format csv --headers --safe-csv > parts.csv
Excel workbooks written with --format xls are not affected: their cells are
stored as strings and are never evaluated.
Machine-Readable Errors
With --error-format json (or PCLI2_ERROR_FORMAT=json) everything pcli2
writes to stderr is one JSON object per line: errors, their hints, warnings,
--verbose log lines and the --stats summary. The last object of a failed
run carries the exit code and its class:
$ pcli2 --error-format json asset delete --path /Home/Parts/nope.stl
{"level":"ERROR","code":67,"kind":"not_found","message":"API error: Path not found: /Home/Parts/nope.stl"}
$ echo $?
67
| Field | Meaning |
|---|---|
level | ERROR, WARN, INFO or DEBUG, matching the log lines |
code | The process exit code, on the final error object |
kind | The failure class: usage, data, no_input, not_found, unavailable, temp_fail, software, os, config, auth, network, api |
message | The same text the human-readable error would show |
hint | What to do about it, when pcli2 knows |
http_status | The HTTP status behind an API error, when there is one |
steps | Remediation steps, on errors that list them |
Progress bars and the upload/download statistics reports are not JSON; leave
--progress off in scripts that parse stderr.
# Read the exit code and message of a failed run
if ! out=$(pcli2 --error-format json asset list --folder-path "/Nope" 2>&1 >/dev/null); then
echo "$out" | tail -n 1 | jq -r '"\(.kind): \(.message)"'
fi
Skipping Prompts
Destructive commands ask for confirmation when run interactively. In
scripts, pass --yes:
pcli2 folder delete --folder-path "/Home/Scratch/" --force --yes
pcli2 cache clear --yes
A prompt that cannot be shown is refused rather than answered for you: when
stdin is not a terminal, or --no-input (or PCLI2_NO_INPUT=1) is set, a
command that would have to ask exits 64 and says which flag to pass instead.
tenant use and env use without --name fail the same way instead of
showing a menu nobody can answer. Set PCLI2_NO_INPUT=1 in CI so a forgotten
--yes fails fast rather than hanging on a prompt.
Authentication credentials can be passed as flags for non-interactive use:
pcli2 auth login --client-id "$PHYSNA_CLIENT_ID" --client-secret "$PHYSNA_CLIENT_SECRET"
Dry Run Mode
Preview destructive or bulk operations without changing anything on the
server. Supported by asset delete, folder delete, asset create,
asset create-batch, and folder upload:
# List exactly which files a batch upload would send, and where
pcli2 asset create-batch --input "build/*.stl" --folder-path "/Home/CI Builds/" --dry-run
# Confirm what a forced folder delete would remove
pcli2 folder delete --folder-path "/Home/Old Projects/" --force --dry-run
Exit Codes
PCLI2 uses distinct exit codes (following BSD sysexits.h conventions
where possible) so scripts can react to specific failure classes:
| Code | Meaning |
|---|---|
| 0 | Success |
| 64 | Command line usage error |
| 65 | Data format error |
| 66 | Cannot open input file |
| 67 | Resource not found |
| 69 | Temporary failure |
| 70 | Internal software error |
| 71 | Operating system error |
| 78 | Configuration error |
| 100 | Authentication error |
| 101 | Network communication error |
| 102 | Remote API error |
A usage error rejected by the argument parser also exits 64. Batch commands that finished with some items failed, and folder matches whose report would be incomplete, exit 69.
pcli2 asset get --path "/Home/Models/part.stl" --format json
case $? in
0) echo "found" ;;
100) pcli2 auth login ;;
101) echo "network problem, try again later" ;;
*) echo "failed" ;;
esac
Verbosity Control
The global --quiet flag limits diagnostics to errors; --verbose (-v)
enables debug-level logging. Both work on every command and take
precedence over the PCLI2_LOG_LEVEL and RUST_LOG environment
variables:
pcli2 --quiet asset create-batch --input "build/*.stl" --folder-path "/Home/CI Builds/"
PCLI2_LOG_LEVEL=trace pcli2 folder list
Automatic Retries
Transient failures (network timeouts, connection errors, and HTTP
408/429/502/503/504 responses) are retried automatically with exponential
backoff, honoring the server's Retry-After header. The default is 2
retries; tune it with PCLI2_MAX_RETRIES (0 disables retries):
PCLI2_MAX_RETRIES=5 pcli2 folder download --folder-path "/Home/Models/" --output ./downloads
The request timeout defaults to 30 minutes (large model files take that
long to transfer). Lower it with PCLI2_TIMEOUT (seconds) if you prefer
fast failures over patience:
PCLI2_TIMEOUT=120 pcli2 asset list --folder-path "/Home/Models/"
Note that timeouts abort-and-retry only read requests (GETs); a timed-out write is never retried automatically because the server may have already processed it.
Resuming Interrupted Runs
Long runs in a script should be written so that a retry does not redo finished work:
# Downloads skip files already on disk
pcli2 folder download --folder-path "/Home/Parts" --output ./parts --resume
# Uploads skip files whose name is already in the folder
pcli2 asset create-batch --input "parts/*.stl" --folder-path "/Home/Parts" --skip-existing
# Folder matches record each completed search; the same command continues the run
pcli2 folder geometric-match --folder-path "/Home/Parts" --recursive \
--checkpoint parts.jsonl --format csv --headers > parts.csv
The checkpoint file is removed when the report is written, so a loop that retries until the command exits 0 needs no cleanup of its own.
Request Statistics
Add --stats to any command to get one line on stderr at exit with the number
of API requests made, how many were retried, how many token renewals happened,
and the elapsed time. It is the quickest way to see whether a batch is doing
more work than it should:
pcli2 --stats asset metadata create-batch --input metadata.csv
# 📊 5,102 API request(s), 2 retried, 1 token renewal(s) in 3m41s
Checking the Setup
pcli2 doctor prints the local state in one screen (binary and PATH,
configuration, environment, credentials, token expiry, tenant, caches, API and
auth-server reachability, update state) and exits non-zero when something is
wrong: 78 for a local problem, 68 when a server cannot be reached.
--format json makes it machine-readable.
Update Notifications
In interactive terminal sessions, PCLI2 prints a one-line hint on stderr
when a newer release is available (checked at most once per day). The
check never runs in CI (detected via the CI environment variable) or
when output is redirected. To opt out entirely:
export PCLI2_NO_UPDATE_CHECK=1
CI/CD Example
A GitHub Actions job that uploads build artifacts to Physna:
jobs:
upload-models:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install pcli2
run: curl --proto '=https' --tlsv1.2 -LsSf https://github.com/jchultarsky101/pcli2/releases/latest/download/pcli2-installer.sh | sh
- name: Authenticate
run: pcli2 auth login --client-id "${{ secrets.PHYSNA_CLIENT_ID }}" --client-secret "${{ secrets.PHYSNA_CLIENT_SECRET }}"
- name: Upload models
run: |
pcli2 tenant use --name my-tenant
pcli2 asset create-batch --input "build/*.stl" \
--folder-path "/Home/CI Builds/" --quiet --format json
Cross-Platform Configuration
PCLI2 reads a small set of environment variables. They are useful for WSL users running a Windows executable, for CI jobs, and for anyone who wants configuration and cache files somewhere other than the platform defaults.
# Where config.yml and the credentials file live
export PCLI2_CONFIG_DIR="/custom/path/to/config"
# Where the folder, tenant and metadata caches live
export PCLI2_CACHE_DIR="/custom/path/to/cache"
# Useful for WSL users running Windows executables
export PCLI2_CONFIG_DIR="/home/$USER/.pcli2"
export PCLI2_CACHE_DIR="/home/$USER/.pcli2/cache"
| Variable | Effect |
|---|---|
PCLI2_CONFIG_DIR | Directory holding config.yml and dev_credentials.json. Default: the platform configuration directory (pcli2 config get path prints it). |
PCLI2_CACHE_DIR | Directory for all cache files. Default: the platform cache directory. |
PCLI2_FORMAT | Default --format when the flag is not given on the command line. |
PCLI2_HEADERS | Default --headers when the flag is not given (1/0, yes/no). |
PCLI2_LOG_LEVEL | Log level: error, warn (default), info, debug, trace. RUST_LOG takes precedence when set. |
PCLI2_TIMEOUT | Total request timeout in seconds (default 1800, to allow very large transfers). Connections time out after 15 seconds and a read after 300 seconds of silence regardless. |
PCLI2_MAX_RETRIES | Retries for transient failures: connection errors, 408/429/502/503/504 (default 2; 0 disables). |
PCLI2_NO_COLOR, NO_COLOR | Disable colored output. PCLI2_NO_COLOR follows the pcli2 boolean rule (empty, 0, false, no, off mean off, anything else on); NO_COLOR disables when set to anything non-empty, per no-color.org. |
PCLI2_SAFE_CSV | Guard CSV output against spreadsheet formula injection. Same as --safe-csv. |
PCLI2_NO_INPUT | Never prompt; a command that would need an answer exits 64 instead. Same as --no-input. |
PCLI2_ERROR_FORMAT | text (default) or json. With json, every error, hint and log line on stderr is one JSON object; the last one carries the exit code. Same as --error-format. |
PCLI2_NO_UPDATE_CHECK, CI | Disable the once-a-day new-version hint. |
API, UI and authentication URLs are not read from the environment. They belong to
an environment definition: pcli2 env add --name staging --api-url ..., then
pcli2 env use --name staging.
Paths are the same on every platform: /Home/Parts/Bracket.stl, where /Home
(the name Physna shows for the root folder) is optional. Folder path matching is
case-insensitive.
Documentation Deployment Instructions
GitHub Pages Setup
To deploy the Oranda-generated documentation to GitHub Pages, follow these steps:
-
Enable GitHub Pages:
- Go to your repository settings: https://github.com/jchultarsky101/pcli2/settings
- Scroll down to the "Pages" section
- Under "Source", select "GitHub Actions" as the source
- Click "Save"
-
Trigger the Documentation Deployment:
- Push a commit to the main branch to trigger the documentation workflow
- Or manually trigger the workflow from the GitHub Actions page
-
Access Your Documentation:
- Once the workflow completes successfully, your documentation will be available at: https://jchultarsky101.github.io/pcli2
Local Development
To preview the documentation locally:
# Install Oranda if you haven't already
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/oranda/releases/latest/download/oranda-installer.sh | sh
# Build the documentation
oranda build
# Serve locally (if you have a simple HTTP server)
cd public
python3 -m http.server 8000
# Then visit http://localhost:8000
Workflow Details
The documentation workflow (documentation.yml) will:
- Automatically build documentation on pushes to the main branch
- Deploy the documentation to GitHub Pages
- Run on manual triggers via workflow_dispatch
Troubleshooting
If the documentation doesn't appear:
- Check that GitHub Pages is set to use "GitHub Actions" as the source
- Verify the documentation workflow ran successfully
- Check the workflow logs for any errors