ostruct-cli 0.7.2__tar.gz → 0.8.1__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.2 → ostruct_cli-0.8.1}/LICENSE +2 -0
  2. ostruct_cli-0.8.1/PKG-INFO +638 -0
  3. ostruct_cli-0.8.1/README.md +576 -0
  4. ostruct_cli-0.8.1/pyproject.toml +141 -0
  5. {ostruct_cli-0.7.2 → ostruct_cli-0.8.1}/src/ostruct/cli/__init__.py +21 -3
  6. {ostruct_cli-0.7.2 → ostruct_cli-0.8.1}/src/ostruct/cli/base_errors.py +1 -1
  7. ostruct_cli-0.8.1/src/ostruct/cli/cli.py +141 -0
  8. ostruct_cli-0.8.1/src/ostruct/cli/click_options.py +807 -0
  9. ostruct_cli-0.8.1/src/ostruct/cli/code_interpreter.py +238 -0
  10. ostruct_cli-0.8.1/src/ostruct/cli/commands/__init__.py +32 -0
  11. ostruct_cli-0.8.1/src/ostruct/cli/commands/list_models.py +128 -0
  12. ostruct_cli-0.8.1/src/ostruct/cli/commands/quick_ref.py +54 -0
  13. ostruct_cli-0.8.1/src/ostruct/cli/commands/run.py +137 -0
  14. ostruct_cli-0.8.1/src/ostruct/cli/commands/update_registry.py +71 -0
  15. ostruct_cli-0.8.1/src/ostruct/cli/config.py +277 -0
  16. ostruct_cli-0.8.1/src/ostruct/cli/cost_estimation.py +134 -0
  17. {ostruct_cli-0.7.2 → ostruct_cli-0.8.1}/src/ostruct/cli/errors.py +310 -6
  18. {ostruct_cli-0.7.2 → ostruct_cli-0.8.1}/src/ostruct/cli/exit_codes.py +1 -0
  19. ostruct_cli-0.8.1/src/ostruct/cli/explicit_file_processor.py +548 -0
  20. ostruct_cli-0.8.1/src/ostruct/cli/field_utils.py +69 -0
  21. {ostruct_cli-0.7.2 → ostruct_cli-0.8.1}/src/ostruct/cli/file_info.py +42 -9
  22. ostruct_cli-0.8.1/src/ostruct/cli/file_list.py +525 -0
  23. ostruct_cli-0.8.1/src/ostruct/cli/file_search.py +455 -0
  24. {ostruct_cli-0.7.2 → ostruct_cli-0.8.1}/src/ostruct/cli/file_utils.py +47 -13
  25. ostruct_cli-0.8.1/src/ostruct/cli/mcp_integration.py +541 -0
  26. {ostruct_cli-0.7.2 → ostruct_cli-0.8.1}/src/ostruct/cli/model_creation.py +150 -1
  27. ostruct_cli-0.8.1/src/ostruct/cli/model_validation.py +204 -0
  28. ostruct_cli-0.8.1/src/ostruct/cli/progress_reporting.py +398 -0
  29. {ostruct_cli-0.7.2 → ostruct_cli-0.8.1}/src/ostruct/cli/registry_updates.py +14 -9
  30. ostruct_cli-0.8.1/src/ostruct/cli/runner.py +1418 -0
  31. ostruct_cli-0.8.1/src/ostruct/cli/schema_utils.py +113 -0
  32. ostruct_cli-0.8.1/src/ostruct/cli/services.py +626 -0
  33. ostruct_cli-0.8.1/src/ostruct/cli/template_debug.py +748 -0
  34. ostruct_cli-0.8.1/src/ostruct/cli/template_debug_help.py +162 -0
  35. {ostruct_cli-0.7.2 → ostruct_cli-0.8.1}/src/ostruct/cli/template_env.py +15 -6
  36. {ostruct_cli-0.7.2 → ostruct_cli-0.8.1}/src/ostruct/cli/template_filters.py +55 -3
  37. ostruct_cli-0.8.1/src/ostruct/cli/template_optimizer.py +474 -0
  38. ostruct_cli-0.8.1/src/ostruct/cli/template_processor.py +1080 -0
  39. {ostruct_cli-0.7.2 → ostruct_cli-0.8.1}/src/ostruct/cli/template_rendering.py +69 -34
  40. ostruct_cli-0.8.1/src/ostruct/cli/token_validation.py +286 -0
  41. ostruct_cli-0.8.1/src/ostruct/cli/types.py +78 -0
  42. ostruct_cli-0.8.1/src/ostruct/cli/unattended_operation.py +269 -0
  43. ostruct_cli-0.8.1/src/ostruct/cli/validators.py +496 -0
  44. ostruct_cli-0.7.2/PKG-INFO +0 -370
  45. ostruct_cli-0.7.2/README.md +0 -340
  46. ostruct_cli-0.7.2/pyproject.toml +0 -127
  47. ostruct_cli-0.7.2/src/ostruct/cli/cli.py +0 -2058
  48. ostruct_cli-0.7.2/src/ostruct/cli/click_options.py +0 -375
  49. ostruct_cli-0.7.2/src/ostruct/cli/file_list.py +0 -326
  50. ostruct_cli-0.7.2/src/ostruct/cli/validators.py +0 -113
  51. {ostruct_cli-0.7.2 → ostruct_cli-0.8.1}/src/ostruct/__init__.py +0 -0
  52. {ostruct_cli-0.7.2 → ostruct_cli-0.8.1}/src/ostruct/cli/cache_manager.py +0 -0
  53. {ostruct_cli-0.7.2 → ostruct_cli-0.8.1}/src/ostruct/cli/path_utils.py +0 -0
  54. {ostruct_cli-0.7.2 → ostruct_cli-0.8.1}/src/ostruct/cli/progress.py +0 -0
  55. {ostruct_cli-0.7.2 → ostruct_cli-0.8.1}/src/ostruct/cli/schema_validation.py +0 -0
  56. {ostruct_cli-0.7.2 → ostruct_cli-0.8.1}/src/ostruct/cli/security/__init__.py +0 -0
  57. {ostruct_cli-0.7.2 → ostruct_cli-0.8.1}/src/ostruct/cli/security/allowed_checker.py +0 -0
  58. {ostruct_cli-0.7.2 → ostruct_cli-0.8.1}/src/ostruct/cli/security/base.py +0 -0
  59. {ostruct_cli-0.7.2 → ostruct_cli-0.8.1}/src/ostruct/cli/security/case_manager.py +0 -0
  60. {ostruct_cli-0.7.2 → ostruct_cli-0.8.1}/src/ostruct/cli/security/errors.py +0 -0
  61. {ostruct_cli-0.7.2 → ostruct_cli-0.8.1}/src/ostruct/cli/security/normalization.py +0 -0
  62. {ostruct_cli-0.7.2 → ostruct_cli-0.8.1}/src/ostruct/cli/security/safe_joiner.py +0 -0
  63. {ostruct_cli-0.7.2 → ostruct_cli-0.8.1}/src/ostruct/cli/security/security_manager.py +0 -0
  64. {ostruct_cli-0.7.2 → ostruct_cli-0.8.1}/src/ostruct/cli/security/symlink_resolver.py +0 -0
  65. {ostruct_cli-0.7.2 → ostruct_cli-0.8.1}/src/ostruct/cli/security/types.py +0 -0
  66. {ostruct_cli-0.7.2 → ostruct_cli-0.8.1}/src/ostruct/cli/security/windows_paths.py +0 -0
  67. {ostruct_cli-0.7.2 → ostruct_cli-0.8.1}/src/ostruct/cli/serialization.py +0 -0
  68. {ostruct_cli-0.7.2 → ostruct_cli-0.8.1}/src/ostruct/cli/template_extensions.py +0 -0
  69. {ostruct_cli-0.7.2 → ostruct_cli-0.8.1}/src/ostruct/cli/template_io.py +0 -0
  70. {ostruct_cli-0.7.2 → ostruct_cli-0.8.1}/src/ostruct/cli/template_schema.py +0 -0
  71. {ostruct_cli-0.7.2 → ostruct_cli-0.8.1}/src/ostruct/cli/template_utils.py +0 -0
  72. {ostruct_cli-0.7.2 → ostruct_cli-0.8.1}/src/ostruct/cli/template_validation.py +0 -0
  73. {ostruct_cli-0.7.2 → ostruct_cli-0.8.1}/src/ostruct/cli/token_utils.py +0 -0
  74. {ostruct_cli-0.7.2 → ostruct_cli-0.8.1}/src/ostruct/cli/utils.py +0 -0
  75. {ostruct_cli-0.7.2 → ostruct_cli-0.8.1}/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,638 @@
1
+ Metadata-Version: 2.3
2
+ Name: ostruct-cli
3
+ Version: 0.8.1
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, Web Search for real-time information access, 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
+ - **Web Search**: Real-time information retrieval and current data access via OpenAI's web search tool
199
+ - **MCP Servers**: Connect to Model Context Protocol servers for extended functionality
200
+ - **Explicit File Routing**: Route different files to specific tools for optimized processing
201
+
202
+ ### Advanced Features
203
+
204
+ - **Configuration System**: YAML-based configuration with environment variable support
205
+ - **Unattended Operation**: Designed for CI/CD and automation scenarios
206
+ - **Progress Reporting**: Real-time progress updates with clear, user-friendly messaging
207
+ - **Model Registry**: Dynamic model management with support for latest OpenAI models
208
+
209
+ ## Requirements
210
+
211
+ - Python 3.10 or higher
212
+
213
+ ## Installation
214
+
215
+ ### For Users
216
+
217
+ To install the latest stable version from PyPI:
218
+
219
+ ```bash
220
+ pip install ostruct-cli
221
+ ```
222
+
223
+ ### For Developers
224
+
225
+ 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.
226
+
227
+ ## Environment Variables
228
+
229
+ ostruct-cli respects the following environment variables:
230
+
231
+ - `OPENAI_API_KEY`: Your OpenAI API key (required unless provided via command line)
232
+ - `OPENAI_API_BASE`: Custom API base URL (optional)
233
+ - `OPENAI_API_VERSION`: API version to use (optional)
234
+ - `OPENAI_API_TYPE`: API type (e.g., "azure") (optional)
235
+ - `OSTRUCT_DISABLE_REGISTRY_UPDATE_CHECKS`: Set to "1", "true", or "yes" to disable automatic registry update checks
236
+ - `MCP_<NAME>_URL`: Custom MCP server URLs (e.g., `MCP_STRIPE_URL=https://mcp.stripe.com`)
237
+
238
+ <details>
239
+ <summary><strong>Shell Completion Setup</strong> (Click to expand)</summary>
240
+
241
+ ostruct-cli supports shell completion for Bash, Zsh, and Fish shells. To enable it:
242
+
243
+ ### Bash
244
+
245
+ Add this to your `~/.bashrc`:
246
+
247
+ ```bash
248
+ eval "$(_OSTRUCT_COMPLETE=bash_source ostruct)"
249
+ ```
250
+
251
+ ### Zsh
252
+
253
+ Add this to your `~/.zshrc`:
254
+
255
+ ```bash
256
+ eval "$(_OSTRUCT_COMPLETE=zsh_source ostruct)"
257
+ ```
258
+
259
+ ### Fish
260
+
261
+ Add this to your `~/.config/fish/completions/ostruct.fish`:
262
+
263
+ ```fish
264
+ eval (env _OSTRUCT_COMPLETE=fish_source ostruct)
265
+ ```
266
+
267
+ After adding the appropriate line, restart your shell or source the configuration file.
268
+ Shell completion will help you with:
269
+
270
+ - Command options and their arguments
271
+ - File paths for template and schema files
272
+ - Directory paths for `-d` and `--base-dir` options
273
+ - And more!
274
+
275
+ </details>
276
+
277
+ ## Enhanced CLI with Multi-Tool Integration
278
+
279
+ ### Migration Notice
280
+
281
+ 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:
282
+
283
+ - **Code Interpreter** for data analysis and visualization
284
+ - **File Search** for document retrieval
285
+ - **Web Search** for real-time information access
286
+ - **MCP Servers** for extended functionality
287
+ - **Explicit File Routing** for optimized processing
288
+
289
+ <details>
290
+ <summary><strong>New File Routing Options</strong> (Click to expand)</summary>
291
+
292
+ #### Basic File Routing (Explicit Tool Assignment)
293
+
294
+ ```bash
295
+ # Template access only (config files, small data)
296
+ ostruct run template.j2 schema.json -ft config.yaml
297
+
298
+ # Code Interpreter (data analysis, code execution)
299
+ ostruct run analysis.j2 schema.json -fc data.csv
300
+
301
+ # File Search (document retrieval)
302
+ ostruct run search.j2 schema.json -fs documentation.pdf
303
+
304
+ # Web Search (real-time information)
305
+ ostruct run research.j2 schema.json --web-search -V topic="latest AI developments"
306
+
307
+ # Multiple tools with one file
308
+ ostruct run template.j2 schema.json --file-for code-interpreter shared.json --file-for file-search shared.json
309
+ ```
310
+
311
+ #### Directory Routing
312
+
313
+ ostruct provides two directory routing patterns to match different use cases:
314
+
315
+ **Auto-Naming Pattern** (for known directory structures):
316
+
317
+ ```bash
318
+ # Variables are auto-generated from directory contents
319
+ ostruct run template.j2 schema.json -dt ./config -dc ./datasets -ds ./docs
320
+ # Creates variables like: config_yaml, datasets_csv, docs_pdf (based on actual files)
321
+ ```
322
+
323
+ **Alias Pattern** (for generic, reusable templates):
324
+
325
+ ```bash
326
+ # Create stable variable names regardless of directory contents
327
+ ostruct run template.j2 schema.json --dta app_config ./config --dca data ./datasets --dsa knowledge ./docs
328
+ # Creates stable variables: app_config, data, knowledge (always these names)
329
+ ```
330
+
331
+ **When to Use Each Pattern:**
332
+
333
+ - Use **auto-naming** (`-dt`, `-dc`, `-ds`) when your template knows the specific directory structure
334
+ - Use **alias syntax** (`--dta`, `--dca`, `--dsa`) when your template is generic and needs stable variable names
335
+
336
+ **Template Example:**
337
+
338
+ ```jinja
339
+ {# Works with alias pattern - variables are predictable #}
340
+ {% for file in app_config %}
341
+ Configuration: {{ file.name }} = {{ file.content }}
342
+ {% endfor %}
343
+
344
+ {# Analysis data from stable variable name #}
345
+ {% for file in data %}
346
+ Processing: {{ file.path }}
347
+ {% endfor %}
348
+ ```
349
+
350
+ This design pattern makes templates reusable across different projects while maintaining full backward compatibility.
351
+
352
+ #### MCP Server Integration
353
+
354
+ ```bash
355
+ # Connect to MCP servers for extended capabilities
356
+ ostruct run template.j2 schema.json --mcp-server deepwiki@https://mcp.deepwiki.com/sse
357
+ ```
358
+
359
+ </details>
360
+
361
+ ### Configuration System
362
+
363
+ Create an `ostruct.yaml` file for persistent settings:
364
+
365
+ ```yaml
366
+ models:
367
+ default: gpt-4o
368
+
369
+ tools:
370
+ code_interpreter:
371
+ auto_download: true
372
+ output_directory: "./output"
373
+
374
+ mcp:
375
+ custom_server: "https://my-mcp-server.com"
376
+
377
+ limits:
378
+ max_cost_per_run: 10.00
379
+ ```
380
+
381
+ Load custom configuration:
382
+
383
+ ```bash
384
+ ostruct --config my-config.yaml run template.j2 schema.json
385
+ ```
386
+
387
+ ## Get Started Quickly
388
+
389
+ 🚀 **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.
390
+
391
+ 📖 **Full Documentation:** <https://ostruct.readthedocs.io/>
392
+
393
+ ### Quick Start
394
+
395
+ 1. Set your OpenAI API key:
396
+
397
+ ```bash
398
+ export OPENAI_API_KEY=your-api-key
399
+ ```
400
+
401
+ ### Example 1: Basic Text Extraction (Simplest)
402
+
403
+ 1. Create a template file `extract_person.j2`:
404
+
405
+ ```jinja
406
+ Extract information about the person from this text: {{ stdin }}
407
+ ```
408
+
409
+ 2. Create a schema file `schema.json`:
410
+
411
+ ```json
412
+ {
413
+ "type": "object",
414
+ "properties": {
415
+ "person": {
416
+ "type": "object",
417
+ "properties": {
418
+ "name": {"type": "string", "description": "The person's full name"},
419
+ "age": {"type": "integer", "description": "The person's age"},
420
+ "occupation": {"type": "string", "description": "The person's job"}
421
+ },
422
+ "required": ["name", "age", "occupation"],
423
+ "additionalProperties": false
424
+ }
425
+ },
426
+ "required": ["person"],
427
+ "additionalProperties": false
428
+ }
429
+ ```
430
+
431
+ 3. Run the CLI:
432
+
433
+ ```bash
434
+ # Basic usage
435
+ echo "John Smith is a 35-year-old software engineer" | ostruct run extract_person.j2 schema.json
436
+
437
+ # With enhanced options
438
+ echo "John Smith is a 35-year-old software engineer" | \
439
+ ostruct run extract_person.j2 schema.json \
440
+ --model gpt-4o \
441
+ --temperature 0.7
442
+ ```
443
+
444
+ ### Example 2: Multi-Tool Data Analysis
445
+
446
+ 1. Create an analysis template `analysis_template.j2`:
447
+
448
+ ```jinja
449
+ Analyze the following data sources:
450
+
451
+ {% if sales_data_csv is defined %}
452
+ Sales Data: {{ sales_data_csv.name }} ({{ sales_data_csv.size }} bytes)
453
+ {% endif %}
454
+
455
+ {% if customer_data_json is defined %}
456
+ Customer Data: {{ customer_data_json.name }} ({{ customer_data_json.size }} bytes)
457
+ {% endif %}
458
+
459
+ {% if market_reports_pdf is defined %}
460
+ Market Reports: {{ market_reports_pdf.name }} ({{ market_reports_pdf.size }} bytes)
461
+ {% endif %}
462
+
463
+ {% if config_yaml is defined %}
464
+ Configuration: {{ config_yaml.content }}
465
+ {% endif %}
466
+
467
+ Provide comprehensive analysis and actionable insights.
468
+ ```
469
+
470
+ 2. Create an analysis schema `analysis_schema.json`:
471
+
472
+ ```json
473
+ {
474
+ "type": "object",
475
+ "properties": {
476
+ "analysis": {
477
+ "type": "object",
478
+ "properties": {
479
+ "insights": {"type": "string", "description": "Key insights from the data"},
480
+ "recommendations": {
481
+ "type": "array",
482
+ "items": {"type": "string"},
483
+ "description": "Actionable recommendations"
484
+ },
485
+ "data_quality": {"type": "string", "description": "Assessment of data quality"}
486
+ },
487
+ "required": ["insights", "recommendations"],
488
+ "additionalProperties": false
489
+ }
490
+ },
491
+ "required": ["analysis"],
492
+ "additionalProperties": false
493
+ }
494
+ ```
495
+
496
+ 3. For more complex scenarios, use explicit file routing with flexible syntax options:
497
+
498
+ ```bash
499
+ # Auto-naming (fastest for one-off analysis)
500
+ ostruct run analysis_template.j2 analysis_schema.json \
501
+ -fc sales_data.csv \
502
+ -fc customer_data.json \
503
+ -fs market_reports.pdf \
504
+ -ft config.yaml
505
+
506
+ # Mixed syntax with custom variable names
507
+ ostruct run analysis_template.j2 analysis_schema.json \
508
+ -fc sales_data.csv \
509
+ -fc customers customer_data.json \
510
+ --fsa reports market_reports.pdf \
511
+ --fta app_config config.yaml
512
+
513
+ # Alias syntax for reusable templates (best tab completion)
514
+ ostruct run reusable_analysis.j2 analysis_schema.json \
515
+ --fca sales_data sales_data.csv \
516
+ --fca customer_data customer_data.json \
517
+ --fsa market_reports market_reports.pdf \
518
+ --fta config config.yaml
519
+
520
+ # Code review with stable variable names
521
+ ostruct run code_review.j2 review_schema.json \
522
+ --fca source_code source_code/ \
523
+ --fsa documentation docs/ \
524
+ --fta eslint_config .eslintrc.json
525
+ ```
526
+
527
+ ### Example 3: Legacy Compatibility
528
+
529
+ All existing commands continue to work unchanged:
530
+
531
+ ```bash
532
+ # Traditional usage (fully supported)
533
+ ostruct run extract_from_file.j2 schema.json -f text input.txt -d configs
534
+ ostruct run template.j2 schema.json -p "*.py" source -V env=prod
535
+ ```
536
+
537
+ <details>
538
+ <summary><strong>System Prompt Handling</strong> (Click to expand)</summary>
539
+
540
+ ostruct-cli provides three ways to specify a system prompt, with a clear precedence order:
541
+
542
+ 1. Command-line option (`--sys-prompt` or `--sys-file`):
543
+
544
+ ```bash
545
+ # Direct string
546
+ ostruct run template.j2 schema.json --sys-prompt "You are an expert analyst"
547
+
548
+ # From file
549
+ ostruct run template.j2 schema.json --sys-file system_prompt.txt
550
+ ```
551
+
552
+ 2. Template frontmatter:
553
+
554
+ ```jinja
555
+ ---
556
+ system_prompt: You are an expert analyst
557
+ ---
558
+ Extract information from: {{ text }}
559
+ ```
560
+
561
+ 3. Shared system prompts (with template frontmatter):
562
+
563
+ ```jinja
564
+ ---
565
+ include_system: shared/base_analyst.txt
566
+ system_prompt: Focus on financial metrics
567
+ ---
568
+ Extract information from: {{ text }}
569
+ ```
570
+
571
+ 4. Default system prompt (built into the CLI)
572
+
573
+ ### Precedence Rules
574
+
575
+ When multiple system prompts are provided, they are resolved in this order:
576
+
577
+ 1. Command-line options take highest precedence:
578
+ - If both `--sys-prompt` and `--sys-file` are provided, `--sys-prompt` wins
579
+ - Use `--ignore-task-sysprompt` to ignore template frontmatter
580
+
581
+ 2. Template frontmatter is used if:
582
+ - No command-line options are provided
583
+ - `--ignore-task-sysprompt` is not set
584
+
585
+ 3. Default system prompt is used only if no other prompts are provided
586
+
587
+ Example combining multiple sources:
588
+
589
+ ```bash
590
+ # Command-line prompt will override template frontmatter
591
+ ostruct run template.j2 schema.json --sys-prompt "Override prompt"
592
+
593
+ # Ignore template frontmatter and use default
594
+ ostruct run template.j2 schema.json --ignore-task-sysprompt
595
+ ```
596
+
597
+ </details>
598
+
599
+ ## Model Registry Management
600
+
601
+ ostruct-cli maintains a registry of OpenAI models and their capabilities, which includes:
602
+
603
+ - Context window sizes for each model
604
+ - Maximum output token limits
605
+ - Supported parameters and their constraints
606
+ - Model version information
607
+
608
+ To ensure you're using the latest models and features, you can update the registry:
609
+
610
+ ```bash
611
+ # Update from the official repository
612
+ ostruct update-registry
613
+
614
+ # Update from a custom URL
615
+ ostruct update-registry --url https://example.com/models.yml
616
+
617
+ # Force an update even if the registry is current
618
+ ostruct update-registry --force
619
+ ```
620
+
621
+ This is especially useful when:
622
+
623
+ - New OpenAI models are released
624
+ - Model capabilities or parameters change
625
+ - You need to work with custom model configurations
626
+
627
+ The registry file is stored at `~/.openai_structured/config/models.yml` and is automatically referenced when validating model parameters and token limits.
628
+
629
+ The update command uses HTTP conditional requests (If-Modified-Since headers) to check if the remote registry has changed before downloading, ensuring efficient updates.
630
+
631
+ <!--
632
+ MAINTAINER NOTE: After editing this README, please test GitHub rendering by:
633
+ 1. Creating a draft PR or pushing to a test branch
634
+ 2. Verifying all HTML <details> sections expand/collapse correctly
635
+ 3. Checking badge display and links work as expected
636
+ 4. Ensuring quickstart guide link is functional
637
+ -->
638
+