ostruct-cli 0.7.1__tar.gz → 0.8.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. {ostruct_cli-0.7.1 → ostruct_cli-0.8.0}/LICENSE +2 -0
  2. ostruct_cli-0.8.0/PKG-INFO +633 -0
  3. ostruct_cli-0.8.0/README.md +571 -0
  4. ostruct_cli-0.8.0/pyproject.toml +141 -0
  5. {ostruct_cli-0.7.1 → ostruct_cli-0.8.0}/src/ostruct/cli/__init__.py +21 -3
  6. {ostruct_cli-0.7.1 → ostruct_cli-0.8.0}/src/ostruct/cli/base_errors.py +1 -1
  7. ostruct_cli-0.8.0/src/ostruct/cli/cli.py +141 -0
  8. ostruct_cli-0.8.0/src/ostruct/cli/click_options.py +807 -0
  9. ostruct_cli-0.8.0/src/ostruct/cli/code_interpreter.py +238 -0
  10. ostruct_cli-0.8.0/src/ostruct/cli/commands/__init__.py +32 -0
  11. ostruct_cli-0.8.0/src/ostruct/cli/commands/list_models.py +128 -0
  12. ostruct_cli-0.8.0/src/ostruct/cli/commands/quick_ref.py +50 -0
  13. ostruct_cli-0.8.0/src/ostruct/cli/commands/run.py +137 -0
  14. ostruct_cli-0.8.0/src/ostruct/cli/commands/update_registry.py +71 -0
  15. ostruct_cli-0.8.0/src/ostruct/cli/config.py +277 -0
  16. ostruct_cli-0.8.0/src/ostruct/cli/cost_estimation.py +134 -0
  17. {ostruct_cli-0.7.1 → ostruct_cli-0.8.0}/src/ostruct/cli/errors.py +310 -6
  18. {ostruct_cli-0.7.1 → ostruct_cli-0.8.0}/src/ostruct/cli/exit_codes.py +1 -0
  19. ostruct_cli-0.8.0/src/ostruct/cli/explicit_file_processor.py +548 -0
  20. ostruct_cli-0.8.0/src/ostruct/cli/field_utils.py +69 -0
  21. {ostruct_cli-0.7.1 → ostruct_cli-0.8.0}/src/ostruct/cli/file_info.py +42 -9
  22. ostruct_cli-0.8.0/src/ostruct/cli/file_list.py +525 -0
  23. ostruct_cli-0.8.0/src/ostruct/cli/file_search.py +455 -0
  24. {ostruct_cli-0.7.1 → ostruct_cli-0.8.0}/src/ostruct/cli/file_utils.py +47 -13
  25. ostruct_cli-0.8.0/src/ostruct/cli/mcp_integration.py +541 -0
  26. {ostruct_cli-0.7.1 → ostruct_cli-0.8.0}/src/ostruct/cli/model_creation.py +150 -1
  27. ostruct_cli-0.8.0/src/ostruct/cli/model_validation.py +204 -0
  28. ostruct_cli-0.8.0/src/ostruct/cli/progress_reporting.py +398 -0
  29. {ostruct_cli-0.7.1 → ostruct_cli-0.8.0}/src/ostruct/cli/registry_updates.py +14 -9
  30. ostruct_cli-0.8.0/src/ostruct/cli/runner.py +1418 -0
  31. ostruct_cli-0.8.0/src/ostruct/cli/schema_utils.py +113 -0
  32. ostruct_cli-0.8.0/src/ostruct/cli/services.py +626 -0
  33. ostruct_cli-0.8.0/src/ostruct/cli/template_debug.py +748 -0
  34. ostruct_cli-0.8.0/src/ostruct/cli/template_debug_help.py +162 -0
  35. {ostruct_cli-0.7.1 → ostruct_cli-0.8.0}/src/ostruct/cli/template_env.py +15 -6
  36. {ostruct_cli-0.7.1 → ostruct_cli-0.8.0}/src/ostruct/cli/template_filters.py +55 -3
  37. ostruct_cli-0.8.0/src/ostruct/cli/template_optimizer.py +474 -0
  38. ostruct_cli-0.8.0/src/ostruct/cli/template_processor.py +1080 -0
  39. {ostruct_cli-0.7.1 → ostruct_cli-0.8.0}/src/ostruct/cli/template_rendering.py +69 -34
  40. ostruct_cli-0.8.0/src/ostruct/cli/token_validation.py +286 -0
  41. ostruct_cli-0.8.0/src/ostruct/cli/types.py +78 -0
  42. ostruct_cli-0.8.0/src/ostruct/cli/unattended_operation.py +269 -0
  43. ostruct_cli-0.8.0/src/ostruct/cli/validators.py +496 -0
  44. ostruct_cli-0.7.1/PKG-INFO +0 -369
  45. ostruct_cli-0.7.1/README.md +0 -340
  46. ostruct_cli-0.7.1/pyproject.toml +0 -126
  47. ostruct_cli-0.7.1/src/ostruct/cli/cli.py +0 -2058
  48. ostruct_cli-0.7.1/src/ostruct/cli/click_options.py +0 -375
  49. ostruct_cli-0.7.1/src/ostruct/cli/file_list.py +0 -326
  50. ostruct_cli-0.7.1/src/ostruct/cli/validators.py +0 -113
  51. {ostruct_cli-0.7.1 → ostruct_cli-0.8.0}/src/ostruct/__init__.py +0 -0
  52. {ostruct_cli-0.7.1 → ostruct_cli-0.8.0}/src/ostruct/cli/cache_manager.py +0 -0
  53. {ostruct_cli-0.7.1 → ostruct_cli-0.8.0}/src/ostruct/cli/path_utils.py +0 -0
  54. {ostruct_cli-0.7.1 → ostruct_cli-0.8.0}/src/ostruct/cli/progress.py +0 -0
  55. {ostruct_cli-0.7.1 → ostruct_cli-0.8.0}/src/ostruct/cli/schema_validation.py +0 -0
  56. {ostruct_cli-0.7.1 → ostruct_cli-0.8.0}/src/ostruct/cli/security/__init__.py +0 -0
  57. {ostruct_cli-0.7.1 → ostruct_cli-0.8.0}/src/ostruct/cli/security/allowed_checker.py +0 -0
  58. {ostruct_cli-0.7.1 → ostruct_cli-0.8.0}/src/ostruct/cli/security/base.py +0 -0
  59. {ostruct_cli-0.7.1 → ostruct_cli-0.8.0}/src/ostruct/cli/security/case_manager.py +0 -0
  60. {ostruct_cli-0.7.1 → ostruct_cli-0.8.0}/src/ostruct/cli/security/errors.py +0 -0
  61. {ostruct_cli-0.7.1 → ostruct_cli-0.8.0}/src/ostruct/cli/security/normalization.py +0 -0
  62. {ostruct_cli-0.7.1 → ostruct_cli-0.8.0}/src/ostruct/cli/security/safe_joiner.py +0 -0
  63. {ostruct_cli-0.7.1 → ostruct_cli-0.8.0}/src/ostruct/cli/security/security_manager.py +0 -0
  64. {ostruct_cli-0.7.1 → ostruct_cli-0.8.0}/src/ostruct/cli/security/symlink_resolver.py +0 -0
  65. {ostruct_cli-0.7.1 → ostruct_cli-0.8.0}/src/ostruct/cli/security/types.py +0 -0
  66. {ostruct_cli-0.7.1 → ostruct_cli-0.8.0}/src/ostruct/cli/security/windows_paths.py +0 -0
  67. {ostruct_cli-0.7.1 → ostruct_cli-0.8.0}/src/ostruct/cli/serialization.py +0 -0
  68. {ostruct_cli-0.7.1 → ostruct_cli-0.8.0}/src/ostruct/cli/template_extensions.py +0 -0
  69. {ostruct_cli-0.7.1 → ostruct_cli-0.8.0}/src/ostruct/cli/template_io.py +0 -0
  70. {ostruct_cli-0.7.1 → ostruct_cli-0.8.0}/src/ostruct/cli/template_schema.py +0 -0
  71. {ostruct_cli-0.7.1 → ostruct_cli-0.8.0}/src/ostruct/cli/template_utils.py +0 -0
  72. {ostruct_cli-0.7.1 → ostruct_cli-0.8.0}/src/ostruct/cli/template_validation.py +0 -0
  73. {ostruct_cli-0.7.1 → ostruct_cli-0.8.0}/src/ostruct/cli/token_utils.py +0 -0
  74. {ostruct_cli-0.7.1 → ostruct_cli-0.8.0}/src/ostruct/cli/utils.py +0 -0
  75. {ostruct_cli-0.7.1 → ostruct_cli-0.8.0}/src/ostruct/py.typed +0 -0
@@ -1,5 +1,7 @@
1
1
  MIT License
2
2
 
3
+ SPDX-License-Identifier: MIT
4
+
3
5
  Copyright (c) 2024 Yaniv Golan
4
6
 
5
7
  Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -0,0 +1,633 @@
1
+ Metadata-Version: 2.3
2
+ Name: ostruct-cli
3
+ Version: 0.8.0
4
+ Summary: CLI for OpenAI Structured Output with Multi-Tool Integration
5
+ Author: Yaniv Golan
6
+ Author-email: yaniv@golan.name
7
+ Requires-Python: >=3.10,<4.0
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.10
10
+ Classifier: Programming Language :: Python :: 3.11
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
13
+ Provides-Extra: dev
14
+ Provides-Extra: docs
15
+ Provides-Extra: examples
16
+ Requires-Dist: anyio[trio] (==3.7.1) ; extra == "dev"
17
+ Requires-Dist: asyncio-throttle (>=1.0.2,<2.0) ; extra == "examples"
18
+ Requires-Dist: black (==24.8.0) ; extra == "dev"
19
+ Requires-Dist: build (>=1.2.2.post1,<2.0) ; extra == "dev"
20
+ Requires-Dist: cachetools (>=5.3.2,<6.0)
21
+ Requires-Dist: chardet (>=5.0.0,<6.0)
22
+ Requires-Dist: click (>=8.1.7,<9.0)
23
+ Requires-Dist: flake8 (>=6.0,<7.0) ; extra == "dev"
24
+ Requires-Dist: flake8-pyproject (>=1.2.3,<2.0) ; extra == "dev"
25
+ Requires-Dist: ijson (>=3.2.3,<4.0)
26
+ Requires-Dist: jinja2 (>=3.1.2,<4.0)
27
+ Requires-Dist: jsonschema (>=4.23.0,<5.0)
28
+ Requires-Dist: mypy (>=1.0,<2.0) ; extra == "dev"
29
+ Requires-Dist: myst-parser (>=2.0.0,<3.0) ; extra == "docs"
30
+ Requires-Dist: openai (==1.81.0)
31
+ Requires-Dist: openai-model-registry (>=0.7.0,<1.0)
32
+ Requires-Dist: pre-commit (>=4.1.0,<5.0) ; extra == "dev"
33
+ Requires-Dist: psutil (>=7.0.0,<8.0) ; extra == "dev"
34
+ Requires-Dist: pydantic (>=2.6.3,<3.0)
35
+ Requires-Dist: pyfakefs (>=5.7.4,<6.0) ; extra == "dev"
36
+ Requires-Dist: pygments (>=2.15.0,<3.0)
37
+ Requires-Dist: pytest (>=8.3.4,<9.0) ; extra == "dev"
38
+ Requires-Dist: pytest-asyncio (>=0.25.2,<1.0) ; extra == "dev"
39
+ Requires-Dist: pytest-mock (>=3.14.0,<4.0) ; extra == "dev"
40
+ Requires-Dist: python-dotenv (>=1.0.1,<2.0) ; extra == "dev"
41
+ Requires-Dist: pyyaml (>=6.0.2,<7.0)
42
+ Requires-Dist: sphinx (>=7.0,<8.0) ; extra == "dev"
43
+ Requires-Dist: sphinx (>=7.0,<8.0) ; extra == "docs"
44
+ Requires-Dist: sphinx-design (>=0.5.0,<1.0) ; extra == "docs"
45
+ Requires-Dist: sphinx-rtd-theme (>=1.0,<2.0) ; extra == "docs"
46
+ Requires-Dist: tenacity (>=8.2.3,<9.0) ; extra == "examples"
47
+ Requires-Dist: tiktoken (==0.9.0)
48
+ Requires-Dist: tomli (>=2.0.1,<3.0) ; (python_version < "3.11") and (extra == "docs")
49
+ Requires-Dist: tomli (>=2.0.1,<3.0) ; python_version < "3.11"
50
+ Requires-Dist: twine (>=6.0.1,<7.0) ; extra == "dev"
51
+ Requires-Dist: types-cachetools (>=5.5.0.20240820) ; extra == "dev"
52
+ Requires-Dist: types-chardet (>=5.0.4.6) ; extra == "dev"
53
+ Requires-Dist: types-click (>=7.1.8,<8.0) ; extra == "dev"
54
+ Requires-Dist: types-jsonschema (>=4.23.0.20241208) ; extra == "dev"
55
+ Requires-Dist: types-pygments (>=2.19.0.20250107) ; extra == "dev"
56
+ Requires-Dist: types-pyyaml (>=6.0.12.20241230) ; extra == "dev"
57
+ Requires-Dist: types-requests (>=2.32.0.20241016) ; extra == "dev"
58
+ Requires-Dist: typing-extensions (>=4.9.0,<5.0)
59
+ Requires-Dist: werkzeug (>=3.1.3,<4.0)
60
+ Description-Content-Type: text/markdown
61
+
62
+ ## 02:07 A.M. CI Failure
63
+
64
+ *"Build failed. Again. The third time this week our data extraction pipeline broke because someone changed the log format, and our regex-based parser couldn't handle the new structure. Sarah's on vacation, Mike's parsing code is unreadable, and the client wants their analytics dashboard working by morning.*
65
+
66
+ *There has to be a better way to turn messy data into structured JSON without writing custom parsers for every format change..."*
67
+
68
+ ---
69
+
70
+ ![ostruct](src/assets/ostruct-header.png)
71
+
72
+ <div align="center">
73
+
74
+ [![PyPI version](https://badge.fury.io/py/ostruct-cli.svg)](https://badge.fury.io/py/ostruct-cli)
75
+ [![Python Versions](https://img.shields.io/pypi/pyversions/ostruct-cli.svg)](https://pypi.org/project/ostruct-cli)
76
+ [![Documentation Status](https://readthedocs.org/projects/ostruct/badge/?version=latest)](https://ostruct.readthedocs.io/en/latest/?badge=latest)
77
+ [![CI](https://github.com/yaniv-golan/ostruct/actions/workflows/ci.yml/badge.svg)](https://github.com/yaniv-golan/ostruct/actions/workflows/ci.yml)
78
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
79
+ [![Downloads](https://pepy.tech/badge/ostruct-cli)](https://pepy.tech/project/ostruct-cli)
80
+ [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
81
+
82
+ **ostruct** transforms **unstructured** inputs into **structured**, usable **JSON** output using **OpenAI APIs** with **multi-tool integration**
83
+
84
+ *The better way you've been looking for.*
85
+
86
+ </div>
87
+
88
+ # ostruct-cli
89
+
90
+ ostruct processes unstructured data (text files, code, CSVs, etc.), input variables, and dynamic prompt templates to produce structured JSON output defined by a JSON schema. With enhanced multi-tool integration, ostruct now supports Code Interpreter for data analysis, File Search for document retrieval, and MCP (Model Context Protocol) servers for extended capabilities.
91
+
92
+ <div align="center">
93
+
94
+ ![How ostruct works](src/assets/ostrict-hl-diagram.png)
95
+
96
+ </div>
97
+
98
+ ## Why ostruct?
99
+
100
+ LLMs are powerful, but getting consistent, structured output from them can be challenging. ostruct solves this problem by providing a streamlined approach to transform unstructured data into reliable JSON structures. The motivation behind creating ostruct was to:
101
+
102
+ - **Bridge the gap** between freeform LLM capabilities and structured data needs in production systems
103
+ - **Simplify integration** of AI into existing workflows and applications that expect consistent data formats
104
+ - **Ensure reliability** and validate output against a defined schema to avoid unexpected formats or missing data
105
+ - **Reduce development time** by providing a standardized way to interact with OpenAI models for structured outputs
106
+ - **Enable non-developers** to leverage AI capabilities through a simple CLI interface with templates
107
+
108
+ ## Real-World Use Cases
109
+
110
+ ostruct can be used for various scenarios, including:
111
+
112
+ ### Automated Code Review with Multi-Tool Analysis
113
+
114
+ ```bash
115
+ # Traditional pattern matching
116
+ ostruct run prompts/task.j2 schemas/code_review.json -p source "examples/security/*.py"
117
+
118
+ # Enhanced with Code Interpreter for deeper analysis
119
+ ostruct run prompts/task.j2 schemas/code_review.json -fc examples/security/ -fs documentation/
120
+ ```
121
+
122
+ Analyze code for security vulnerabilities, style issues, and performance problems. The enhanced version uses Code Interpreter for execution analysis and File Search for documentation context.
123
+
124
+ ### Security Vulnerability Scanning
125
+
126
+ ```bash
127
+ # Budget-friendly static analysis (recommended for most projects)
128
+ ostruct run prompts/static_analysis.j2 schemas/scan_result.json \
129
+ -d code examples -R --sys-file prompts/system.txt
130
+
131
+ # Professional security analysis with Code Interpreter (best balance)
132
+ ostruct run prompts/code_interpreter.j2 schemas/scan_result.json \
133
+ -dc examples --sys-file prompts/system.txt
134
+
135
+ # Comprehensive hybrid analysis for critical applications
136
+ ostruct run prompts/hybrid_analysis.j2 schemas/scan_result.json \
137
+ -d code examples -R -dc examples --sys-file prompts/system.txt
138
+ ```
139
+
140
+ **Three optimized approaches** for automated security vulnerability scanning:
141
+
142
+ - **Static Analysis**: $0.18 cost, fast processing, comprehensive vulnerability detection
143
+ - **Code Interpreter**: $0.18 cost (same!), superior analysis quality with evidence-based findings
144
+ - **Hybrid Analysis**: $0.20 cost (+13%), maximum depth with cross-validation
145
+
146
+ Each approach finds the same core vulnerabilities but with different levels of detail and analysis quality. Directory-based analysis provides comprehensive project coverage in a single scan.
147
+
148
+ ### Data Analysis with Code Interpreter
149
+
150
+ ```bash
151
+ # Upload data for analysis and visualization
152
+ ostruct run analysis.j2 schemas/analysis_result.json \
153
+ -fc sales_data.csv -fc customer_data.json \
154
+ -fs reports/ -ft config.yaml
155
+ ```
156
+
157
+ Perform sophisticated data analysis using Python execution, generate visualizations, and create comprehensive reports with document context.
158
+
159
+ ### Configuration Validation & Analysis
160
+
161
+ ```bash
162
+ # Traditional file comparison
163
+ ostruct run prompts/task.j2 schemas/validation_result.json \
164
+ -f dev examples/basic/dev.yaml -f prod examples/basic/prod.yaml
165
+
166
+ # Enhanced with environment context
167
+ ostruct run prompts/task.j2 schemas/validation_result.json \
168
+ -ft dev.yaml -ft prod.yaml -fs infrastructure_docs/
169
+ ```
170
+
171
+ Validate configuration files across environments with documentation context for better analysis and recommendations.
172
+
173
+ Oh, and also, among endless other use cases:
174
+
175
+ ### Etymology Analysis
176
+
177
+ ```bash
178
+ ostruct run prompts/task.j2 schemas/etymology.json -ft examples/scientific.txt
179
+ ```
180
+
181
+ Break down words into their components, showing their origins, meanings, and hierarchical relationships. Useful for linguistics, educational tools, and understanding terminology in specialized fields.
182
+
183
+ ## Features
184
+
185
+ ### Core Capabilities
186
+
187
+ - Generate structured JSON output defined by dynamic prompts using OpenAI models and JSON schemas
188
+ - Rich template system for defining prompts (Jinja2-based)
189
+ - Automatic token counting and context window management
190
+ - Streaming support for real-time output
191
+ - Secure handling of sensitive data with comprehensive path validation
192
+ - Automatic prompt optimization and token management
193
+
194
+ ### Multi-Tool Integration
195
+
196
+ - **Code Interpreter**: Upload and analyze data files, execute Python code, generate visualizations
197
+ - **File Search**: Vector-based document search and retrieval from uploaded files
198
+ - **MCP Servers**: Connect to Model Context Protocol servers for extended functionality
199
+ - **Explicit File Routing**: Route different files to specific tools for optimized processing
200
+
201
+ ### Advanced Features
202
+
203
+ - **Configuration System**: YAML-based configuration with environment variable support
204
+ - **Unattended Operation**: Designed for CI/CD and automation scenarios
205
+ - **Progress Reporting**: Real-time progress updates with clear, user-friendly messaging
206
+ - **Model Registry**: Dynamic model management with support for latest OpenAI models
207
+
208
+ ## Requirements
209
+
210
+ - Python 3.10 or higher
211
+
212
+ ## Installation
213
+
214
+ ### For Users
215
+
216
+ To install the latest stable version from PyPI:
217
+
218
+ ```bash
219
+ pip install ostruct-cli
220
+ ```
221
+
222
+ ### For Developers
223
+
224
+ If you plan to contribute to the project, see the [Development Setup](#development-setup) section below for instructions on setting up the development environment with Poetry.
225
+
226
+ ## Environment Variables
227
+
228
+ ostruct-cli respects the following environment variables:
229
+
230
+ - `OPENAI_API_KEY`: Your OpenAI API key (required unless provided via command line)
231
+ - `OPENAI_API_BASE`: Custom API base URL (optional)
232
+ - `OPENAI_API_VERSION`: API version to use (optional)
233
+ - `OPENAI_API_TYPE`: API type (e.g., "azure") (optional)
234
+ - `OSTRUCT_DISABLE_REGISTRY_UPDATE_CHECKS`: Set to "1", "true", or "yes" to disable automatic registry update checks
235
+ - `MCP_<NAME>_URL`: Custom MCP server URLs (e.g., `MCP_STRIPE_URL=https://mcp.stripe.com`)
236
+
237
+ <details>
238
+ <summary><strong>Shell Completion Setup</strong> (Click to expand)</summary>
239
+
240
+ ostruct-cli supports shell completion for Bash, Zsh, and Fish shells. To enable it:
241
+
242
+ ### Bash
243
+
244
+ Add this to your `~/.bashrc`:
245
+
246
+ ```bash
247
+ eval "$(_OSTRUCT_COMPLETE=bash_source ostruct)"
248
+ ```
249
+
250
+ ### Zsh
251
+
252
+ Add this to your `~/.zshrc`:
253
+
254
+ ```bash
255
+ eval "$(_OSTRUCT_COMPLETE=zsh_source ostruct)"
256
+ ```
257
+
258
+ ### Fish
259
+
260
+ Add this to your `~/.config/fish/completions/ostruct.fish`:
261
+
262
+ ```fish
263
+ eval (env _OSTRUCT_COMPLETE=fish_source ostruct)
264
+ ```
265
+
266
+ After adding the appropriate line, restart your shell or source the configuration file.
267
+ Shell completion will help you with:
268
+
269
+ - Command options and their arguments
270
+ - File paths for template and schema files
271
+ - Directory paths for `-d` and `--base-dir` options
272
+ - And more!
273
+
274
+ </details>
275
+
276
+ ## Enhanced CLI with Multi-Tool Integration
277
+
278
+ ### Migration Notice
279
+
280
+ ostruct now includes powerful multi-tool integration while maintaining **full backward compatibility**. All existing commands continue to work exactly as before, but you can now take advantage of:
281
+
282
+ - **Code Interpreter** for data analysis and visualization
283
+ - **File Search** for document retrieval
284
+ - **MCP Servers** for extended functionality
285
+ - **Explicit File Routing** for optimized processing
286
+
287
+ <details>
288
+ <summary><strong>New File Routing Options</strong> (Click to expand)</summary>
289
+
290
+ #### Basic File Routing (Explicit Tool Assignment)
291
+
292
+ ```bash
293
+ # Template access only (config files, small data)
294
+ ostruct run template.j2 schema.json -ft config.yaml
295
+
296
+ # Code Interpreter (data analysis, code execution)
297
+ ostruct run analysis.j2 schema.json -fc data.csv
298
+
299
+ # File Search (document retrieval)
300
+ ostruct run search.j2 schema.json -fs documentation.pdf
301
+
302
+ # Multiple tools with one file
303
+ ostruct run template.j2 schema.json --file-for code-interpreter shared.json --file-for file-search shared.json
304
+ ```
305
+
306
+ #### Directory Routing
307
+
308
+ ostruct provides two directory routing patterns to match different use cases:
309
+
310
+ **Auto-Naming Pattern** (for known directory structures):
311
+
312
+ ```bash
313
+ # Variables are auto-generated from directory contents
314
+ ostruct run template.j2 schema.json -dt ./config -dc ./datasets -ds ./docs
315
+ # Creates variables like: config_yaml, datasets_csv, docs_pdf (based on actual files)
316
+ ```
317
+
318
+ **Alias Pattern** (for generic, reusable templates):
319
+
320
+ ```bash
321
+ # Create stable variable names regardless of directory contents
322
+ ostruct run template.j2 schema.json --dta app_config ./config --dca data ./datasets --dsa knowledge ./docs
323
+ # Creates stable variables: app_config, data, knowledge (always these names)
324
+ ```
325
+
326
+ **When to Use Each Pattern:**
327
+
328
+ - Use **auto-naming** (`-dt`, `-dc`, `-ds`) when your template knows the specific directory structure
329
+ - Use **alias syntax** (`--dta`, `--dca`, `--dsa`) when your template is generic and needs stable variable names
330
+
331
+ **Template Example:**
332
+
333
+ ```jinja
334
+ {# Works with alias pattern - variables are predictable #}
335
+ {% for file in app_config %}
336
+ Configuration: {{ file.name }} = {{ file.content }}
337
+ {% endfor %}
338
+
339
+ {# Analysis data from stable variable name #}
340
+ {% for file in data %}
341
+ Processing: {{ file.path }}
342
+ {% endfor %}
343
+ ```
344
+
345
+ This design pattern makes templates reusable across different projects while maintaining full backward compatibility.
346
+
347
+ #### MCP Server Integration
348
+
349
+ ```bash
350
+ # Connect to MCP servers for extended capabilities
351
+ ostruct run template.j2 schema.json --mcp-server deepwiki@https://mcp.deepwiki.com/sse
352
+ ```
353
+
354
+ </details>
355
+
356
+ ### Configuration System
357
+
358
+ Create an `ostruct.yaml` file for persistent settings:
359
+
360
+ ```yaml
361
+ models:
362
+ default: gpt-4o
363
+
364
+ tools:
365
+ code_interpreter:
366
+ auto_download: true
367
+ output_directory: "./output"
368
+
369
+ mcp:
370
+ custom_server: "https://my-mcp-server.com"
371
+
372
+ limits:
373
+ max_cost_per_run: 10.00
374
+ ```
375
+
376
+ Load custom configuration:
377
+
378
+ ```bash
379
+ ostruct --config my-config.yaml run template.j2 schema.json
380
+ ```
381
+
382
+ ## Get Started Quickly
383
+
384
+ 🚀 **New to ostruct?** Follow our [step-by-step quickstart guide](https://ostruct.readthedocs.io/en/latest/user-guide/quickstart.html) featuring Juno the beagle for a hands-on introduction.
385
+
386
+ 📖 **Full Documentation:** <https://ostruct.readthedocs.io/>
387
+
388
+ ### Quick Start
389
+
390
+ 1. Set your OpenAI API key:
391
+
392
+ ```bash
393
+ export OPENAI_API_KEY=your-api-key
394
+ ```
395
+
396
+ ### Example 1: Basic Text Extraction (Simplest)
397
+
398
+ 1. Create a template file `extract_person.j2`:
399
+
400
+ ```jinja
401
+ Extract information about the person from this text: {{ stdin }}
402
+ ```
403
+
404
+ 2. Create a schema file `schema.json`:
405
+
406
+ ```json
407
+ {
408
+ "type": "object",
409
+ "properties": {
410
+ "person": {
411
+ "type": "object",
412
+ "properties": {
413
+ "name": {"type": "string", "description": "The person's full name"},
414
+ "age": {"type": "integer", "description": "The person's age"},
415
+ "occupation": {"type": "string", "description": "The person's job"}
416
+ },
417
+ "required": ["name", "age", "occupation"],
418
+ "additionalProperties": false
419
+ }
420
+ },
421
+ "required": ["person"],
422
+ "additionalProperties": false
423
+ }
424
+ ```
425
+
426
+ 3. Run the CLI:
427
+
428
+ ```bash
429
+ # Basic usage
430
+ echo "John Smith is a 35-year-old software engineer" | ostruct run extract_person.j2 schema.json
431
+
432
+ # With enhanced options
433
+ echo "John Smith is a 35-year-old software engineer" | \
434
+ ostruct run extract_person.j2 schema.json \
435
+ --model gpt-4o \
436
+ --temperature 0.7
437
+ ```
438
+
439
+ ### Example 2: Multi-Tool Data Analysis
440
+
441
+ 1. Create an analysis template `analysis_template.j2`:
442
+
443
+ ```jinja
444
+ Analyze the following data sources:
445
+
446
+ {% if sales_data_csv is defined %}
447
+ Sales Data: {{ sales_data_csv.name }} ({{ sales_data_csv.size }} bytes)
448
+ {% endif %}
449
+
450
+ {% if customer_data_json is defined %}
451
+ Customer Data: {{ customer_data_json.name }} ({{ customer_data_json.size }} bytes)
452
+ {% endif %}
453
+
454
+ {% if market_reports_pdf is defined %}
455
+ Market Reports: {{ market_reports_pdf.name }} ({{ market_reports_pdf.size }} bytes)
456
+ {% endif %}
457
+
458
+ {% if config_yaml is defined %}
459
+ Configuration: {{ config_yaml.content }}
460
+ {% endif %}
461
+
462
+ Provide comprehensive analysis and actionable insights.
463
+ ```
464
+
465
+ 2. Create an analysis schema `analysis_schema.json`:
466
+
467
+ ```json
468
+ {
469
+ "type": "object",
470
+ "properties": {
471
+ "analysis": {
472
+ "type": "object",
473
+ "properties": {
474
+ "insights": {"type": "string", "description": "Key insights from the data"},
475
+ "recommendations": {
476
+ "type": "array",
477
+ "items": {"type": "string"},
478
+ "description": "Actionable recommendations"
479
+ },
480
+ "data_quality": {"type": "string", "description": "Assessment of data quality"}
481
+ },
482
+ "required": ["insights", "recommendations"],
483
+ "additionalProperties": false
484
+ }
485
+ },
486
+ "required": ["analysis"],
487
+ "additionalProperties": false
488
+ }
489
+ ```
490
+
491
+ 3. For more complex scenarios, use explicit file routing with flexible syntax options:
492
+
493
+ ```bash
494
+ # Auto-naming (fastest for one-off analysis)
495
+ ostruct run analysis_template.j2 analysis_schema.json \
496
+ -fc sales_data.csv \
497
+ -fc customer_data.json \
498
+ -fs market_reports.pdf \
499
+ -ft config.yaml
500
+
501
+ # Mixed syntax with custom variable names
502
+ ostruct run analysis_template.j2 analysis_schema.json \
503
+ -fc sales_data.csv \
504
+ -fc customers customer_data.json \
505
+ --fsa reports market_reports.pdf \
506
+ --fta app_config config.yaml
507
+
508
+ # Alias syntax for reusable templates (best tab completion)
509
+ ostruct run reusable_analysis.j2 analysis_schema.json \
510
+ --fca sales_data sales_data.csv \
511
+ --fca customer_data customer_data.json \
512
+ --fsa market_reports market_reports.pdf \
513
+ --fta config config.yaml
514
+
515
+ # Code review with stable variable names
516
+ ostruct run code_review.j2 review_schema.json \
517
+ --fca source_code source_code/ \
518
+ --fsa documentation docs/ \
519
+ --fta eslint_config .eslintrc.json
520
+ ```
521
+
522
+ ### Example 3: Legacy Compatibility
523
+
524
+ All existing commands continue to work unchanged:
525
+
526
+ ```bash
527
+ # Traditional usage (fully supported)
528
+ ostruct run extract_from_file.j2 schema.json -f text input.txt -d configs
529
+ ostruct run template.j2 schema.json -p "*.py" source -V env=prod
530
+ ```
531
+
532
+ <details>
533
+ <summary><strong>System Prompt Handling</strong> (Click to expand)</summary>
534
+
535
+ ostruct-cli provides three ways to specify a system prompt, with a clear precedence order:
536
+
537
+ 1. Command-line option (`--sys-prompt` or `--sys-file`):
538
+
539
+ ```bash
540
+ # Direct string
541
+ ostruct run template.j2 schema.json --sys-prompt "You are an expert analyst"
542
+
543
+ # From file
544
+ ostruct run template.j2 schema.json --sys-file system_prompt.txt
545
+ ```
546
+
547
+ 2. Template frontmatter:
548
+
549
+ ```jinja
550
+ ---
551
+ system_prompt: You are an expert analyst
552
+ ---
553
+ Extract information from: {{ text }}
554
+ ```
555
+
556
+ 3. Shared system prompts (with template frontmatter):
557
+
558
+ ```jinja
559
+ ---
560
+ include_system: shared/base_analyst.txt
561
+ system_prompt: Focus on financial metrics
562
+ ---
563
+ Extract information from: {{ text }}
564
+ ```
565
+
566
+ 4. Default system prompt (built into the CLI)
567
+
568
+ ### Precedence Rules
569
+
570
+ When multiple system prompts are provided, they are resolved in this order:
571
+
572
+ 1. Command-line options take highest precedence:
573
+ - If both `--sys-prompt` and `--sys-file` are provided, `--sys-prompt` wins
574
+ - Use `--ignore-task-sysprompt` to ignore template frontmatter
575
+
576
+ 2. Template frontmatter is used if:
577
+ - No command-line options are provided
578
+ - `--ignore-task-sysprompt` is not set
579
+
580
+ 3. Default system prompt is used only if no other prompts are provided
581
+
582
+ Example combining multiple sources:
583
+
584
+ ```bash
585
+ # Command-line prompt will override template frontmatter
586
+ ostruct run template.j2 schema.json --sys-prompt "Override prompt"
587
+
588
+ # Ignore template frontmatter and use default
589
+ ostruct run template.j2 schema.json --ignore-task-sysprompt
590
+ ```
591
+
592
+ </details>
593
+
594
+ ## Model Registry Management
595
+
596
+ ostruct-cli maintains a registry of OpenAI models and their capabilities, which includes:
597
+
598
+ - Context window sizes for each model
599
+ - Maximum output token limits
600
+ - Supported parameters and their constraints
601
+ - Model version information
602
+
603
+ To ensure you're using the latest models and features, you can update the registry:
604
+
605
+ ```bash
606
+ # Update from the official repository
607
+ ostruct update-registry
608
+
609
+ # Update from a custom URL
610
+ ostruct update-registry --url https://example.com/models.yml
611
+
612
+ # Force an update even if the registry is current
613
+ ostruct update-registry --force
614
+ ```
615
+
616
+ This is especially useful when:
617
+
618
+ - New OpenAI models are released
619
+ - Model capabilities or parameters change
620
+ - You need to work with custom model configurations
621
+
622
+ The registry file is stored at `~/.openai_structured/config/models.yml` and is automatically referenced when validating model parameters and token limits.
623
+
624
+ The update command uses HTTP conditional requests (If-Modified-Since headers) to check if the remote registry has changed before downloading, ensuring efficient updates.
625
+
626
+ <!--
627
+ MAINTAINER NOTE: After editing this README, please test GitHub rendering by:
628
+ 1. Creating a draft PR or pushing to a test branch
629
+ 2. Verifying all HTML <details> sections expand/collapse correctly
630
+ 3. Checking badge display and links work as expected
631
+ 4. Ensuring quickstart guide link is functional
632
+ -->
633
+