PromptManager
Caution
⚠️ Breaking Changes are Coming ⚠️
See Roadmap for details about upcoming changes.
![]() [Comprehensive Documentation Website](https://madbomber.github.io/prompt_manager/) |
Like an enchanted librarian organizing floating books of knowledge, PromptManager helps you masterfully orchestrate and organize your AI prompts through wisdom and experience. Each prompt becomes a living entity that can be categorized, parameterized, and interconnected with golden threads of relationships.
Key Features
|
Table of Contents
- Installation
- Quick Start
- Core Features
- Parameterized Prompts
- Keyword Syntax
- Custom Patterns
- Working with Parameters
- Directive Processing
- Built-in Directives
- Directive Syntax
- Custom Directive Processors
- ERB and Shell Integration
- ERB Templates
- Environment Variables
- Comments and Documentation
- Line Comments
- Block Comments
- Blank Lines
- Parameter History
- Error Handling
- Parameterized Prompts
- Storage Adapters
- FileSystemAdapter
- Configuration
- File Structure
- Custom Search
- Extra Methods
- ActiveRecordAdapter
- Configuration
- Database Setup
- Custom Adapters
- FileSystemAdapter
- Configuration
- Initialization Options
- Global Configuration
- Advanced Usage
- Custom Keyword Patterns
- Dynamic Directives
- Search Capabilities
- Examples
- Basic Usage
- With Search
- Custom Storage
- Extensible Architecture
- Extension Points
- Potential Extensions
- Roadmap
- v0.9.0 - Modern Prompt Format (Breaking Changes)
- v1.0.0 - Stability Release
- Future Enhancements
- Development
- Contributing
- License
Installation
Install the gem and add to the application's Gemfile by executing:
bundle add prompt_manager
If bundler is not being used to manage dependencies, install the gem by executing:
gem install prompt_manager
Quick Start
require 'prompt_manager'
# Configure storage adapter
PromptManager::Prompt.storage_adapter =
PromptManager::Storage::FileSystemAdapter.config do |config|
config.prompts_dir = '~/.prompts'
end.new
# Load and use a prompt
prompt = PromptManager::Prompt.new(id: 'greeting')
prompt.parameters = {
"[NAME]" => "Alice",
"[LANGUAGE]" => "English"
}
# Get the processed prompt text
result = prompt.to_s
Core Features
Parameterized Prompts
The heart of PromptManager is its ability to manage parameterized prompts - text templates with embedded keywords that can be replaced with dynamic values.
Keyword Syntax
By default, keywords are enclosed in square brackets: [KEYWORD]
, [MULTIPLE WORDS]
, or [WITH_UNDERSCORES]
.
prompt_text = "Hello [NAME], please translate this to [LANGUAGE]"
Custom Patterns
You can customize the keyword pattern to match your preferences:
# Use {{mustache}} style
PromptManager::Prompt.parameter_regex = /(\{\{[A-Za-z_]+\}\})/
# Use :colon style
PromptManager::Prompt.parameter_regex = /(:[a-z_]+)/
The regex must include capturing parentheses ()
to extract the keyword.
Working with Parameters
prompt = PromptManager::Prompt.new(id: 'example')
# Get all keywords found in the prompt
keywords = prompt.keywords #=> ["[NAME]", "[LANGUAGE]"]
# Set parameter values
prompt.parameters = {
"[NAME]" => "Alice",
"[LANGUAGE]" => "French"
}
# Get processed text with substitutions
final_text = prompt.to_s
# Save changes
prompt.save
Directive Processing
Directives are special line oriented instructions in your prompts that begin with //
starting in column 1. They're inspired by IBM JCL and provide powerful prompt composition capabilities. A character string that begins with //
but is not at the very beginning of the line will NOT be processed as a directive.
Built-in Directives
//include
(alias: //import
) - Include content from other files:
//include common/header.txt
//import [TEMPLATE_NAME].txt
Main prompt content here...
Features:
- Loop protection prevents circular includes
- Supports keyword substitution in file paths
- Processes included files recursively
Directive Syntax
//directive_name [PARAM1] [PARAM2] options
# Dynamic directives using keywords
//[COMMAND] [OPTIONS]
Custom Directive Processors
You can create custom directive processors:
class MyDirectiveProcessor < PromptManager::DirectiveProcessor
def process_directive(directive, prompt)
case directive
when /^\/\/model (.+)$/
set_model($1)
when /^\/\/temperature (.+)$/
set_temperature($1.to_f)
else
super
end
end
end
prompt = PromptManager::Prompt.new(
id: 'example',
directives_processor: MyDirectiveProcessor.new
)
ERB and Shell Integration
ERB Templates
Enable ERB processing for dynamic content generation:
prompt = PromptManager::Prompt.new(
id: 'dynamic',
erb_flag: true
)
Example prompt with ERB:
Today's date is <%= Date.today %>
<% 5.times do |i| %>
Item <%= i + 1 %>
<% end %>
Environment Variables
Enable automatic environment variable substitution:
prompt = PromptManager::Prompt.new(
id: 'with_env',
envar_flag: true
)
Environment variables are automatically replaced in the prompt text.
Comments and Documentation
PromptManager supports comprehensive inline documentation:
Line Comments
Lines beginning with #
are treated as comments:
# This is a comment
# Description: This prompt does something useful
Actual prompt text here...
Block Comments
Everything after __END__
is ignored:
Main prompt content...
__END__
Development notes:
- This section is completely ignored
- Great for documentation
- TODO items
Blank Lines
Blank lines are automatically removed from the final output.
Parameter History
PromptManager maintains a history of parameter values (since v0.3.0):
# Parameters are stored as arrays
prompt.parameters = {
"[NAME]" => ["Alice", "Bob", "Charlie"] # Charlie is most recent
}
# The last value is always the most recent
current_name = prompt.parameters["[NAME]"].last
# Useful for:
# - Implementing value history in UIs
# - Providing dropdown selections
# - Tracking parameter usage over time
Error Handling
PromptManager provides specific error classes for better debugging:
begin
prompt = PromptManager::Prompt.new(id: 'missing')
rescue PromptManager::StorageError => e
# Handle storage-related errors
puts "Storage error: #{e.message}"
rescue PromptManager::ParameterError => e
# Handle parameter substitution errors
puts "Parameter error: #{e.message}"
rescue PromptManager::ConfigurationError => e
# Handle configuration errors
puts "Configuration error: #{e.message}"
end
Storage Adapters
Storage adapters provide the persistence layer for prompts. PromptManager includes two built-in adapters and supports custom implementations.
FileSystemAdapter
Stores prompts as text files in a directory structure.
Configuration
PromptManager::Storage::FileSystemAdapter.config do |config|
config.prompts_dir = "~/.prompts" # Required
config.search_proc = nil # Optional custom search
config.prompt_extension = '.txt' # Default
config.params_extension = '.json' # Default
end
File Structure
~/.prompts/
├── greeting.txt # Prompt text
├── greeting.json # Parameters
├── email/
│ ├── welcome.txt
│ └── welcome.json
Custom Search
Integrate with external search tools:
config.search_proc = ->(query) {
# Use ripgrep for fast searching
`rg -l "#{query}" #{config.prompts_dir}`.split("\n")
}
Extra Methods
-
list
- Returns array of all prompt IDs -
path(id)
- Returns Pathname to prompt file
ActiveRecordAdapter
Stores prompts in a database using ActiveRecord.
Configuration
PromptManager::Storage::ActiveRecordAdapter.config do |config|
config.model = PromptModel # Your AR model
config.id_column = :prompt_id # Column for ID
config.text_column = :content # Column for text
config.parameters_column = :params # Column for parameters
end
Database Setup
class CreatePrompts < ActiveRecord::Migration[7.0]
def change
create_table :prompts do |t|
t.string :prompt_id, null: false, index: { unique: true }
t.text :content
t.json :params
t.timestamps
end
end
end
Custom Adapters
Create your own storage adapter:
class RedisAdapter
def initialize(redis_client)
@redis = redis_client
end
def get(id)
prompt_text = @redis.get("prompt:#{id}:text")
parameters = JSON.parse(@redis.get("prompt:#{id}:params") || '{}')
[prompt_text, parameters]
end
def save(id, text, parameters)
@redis.set("prompt:#{id}:text", text)
@redis.set("prompt:#{id}:params", parameters.to_json)
end
def delete(id)
@redis.del("prompt:#{id}:text", "prompt:#{id}:params")
end
def list
@redis.keys("prompt:*:text").map { |k| k.split(':')[1] }
end
end
Configuration
Initialization Options
When creating a prompt instance:
prompt = PromptManager::Prompt.new(
id: 'example',
context: ['additional', 'context'],
directives_processor: CustomProcessor.new,
external_binding: binding,
erb_flag: true,
envar_flag: true
)
Options:
-
id
- Unique identifier for the prompt -
context
- Additional context array -
directives_processor
- Custom directive processor -
external_binding
- Ruby binding for ERB -
erb_flag
- Enable ERB processing -
envar_flag
- Enable environment variable substitution
Global Configuration
Set the storage adapter globally:
PromptManager::Prompt.storage_adapter = adapter_instance
Advanced Usage
Custom Keyword Patterns
Examples of different keyword patterns:
# Handlebars style: {{name}}
PromptManager::Prompt.parameter_regex = /(\{\{[a-z_]+\}\})/
# Colon prefix: :name
PromptManager::Prompt.parameter_regex = /(:[a-z_]+)/
# Dollar sign: $NAME
PromptManager::Prompt.parameter_regex = /(\$[A-Z_]+)/
# Percentage: %name%
PromptManager::Prompt.parameter_regex = /(%[a-z_]+%)/
Dynamic Directives
Create directives that change based on parameters:
# Set directive name via parameter
//[DIRECTIVE_TYPE] [OPTIONS]
# Conditional directives
//include templates/[TEMPLATE_TYPE].txt
Search Capabilities
Implement powerful search across prompts:
# With FileSystemAdapter
adapter.search_proc = ->(query) {
# Custom search implementation
results = []
Dir.glob("#{prompts_dir}/**/*.txt").each do |file|
content = File.read(file)
if content.include?(query)
results << File.basename(file, '.txt')
end
end
results
}
# With ActiveRecordAdapter
PromptModel.where("content LIKE ?", "%#{query}%").pluck(:prompt_id)
Examples
Basic Usage
# examples/simple.rb
require 'prompt_manager'
# Setup
PromptManager::Prompt.storage_adapter =
PromptManager::Storage::FileSystemAdapter.config do |c|
c.prompts_dir = '~/.prompts'
end.new
# Create and use a prompt
prompt = PromptManager::Prompt.new(id: 'story')
prompt.parameters = {
"[GENRE]" => "fantasy",
"[CHARACTER]" => "wizard"
}
puts prompt.to_s
Advanced Integration with LLM and Streaming
See examples/advanced_integrations.rb for a complete example that demonstrates:
- ERB templating for dynamic content generation
- Shell integration for environment variable substitution
- OpenAI API integration with streaming responses
-
Professional UI with spinner feedback using
tty-spinner
This example shows how to create sophisticated AI prompts that adapt to your system environment and stream responses in real-time.
With Search
See examples/using_search_proc.rb for advanced search integration.
Custom Storage
# examples/redis_storage.rb
class RedisStorage
# ... implementation
end
PromptManager::Prompt.storage_adapter = RedisStorage.new(Redis.new)
Extensible Architecture
PromptManager is designed to be extended:
Extension Points
- Storage Adapters - Implement your own persistence layer
- Directive Processors - Add custom directives
- Search Processors - Integrate external search tools
- Serializers - Support different parameter formats
Potential Extensions
- CloudStorageAdapter - S3, Google Cloud Storage
- RedisAdapter - For caching and fast access
- ApiAdapter - REST API backend
- GraphQLAdapter - GraphQL endpoint storage
- GitAdapter - Version controlled prompts
Roadmap
v0.9.0 - Modern Prompt Format (Breaking Changes)
-
Markdown Support: Full
.md
file support with YAML front matter -
Modern Parameter Syntax: Support for
{{keyword}}
format -
Enhanced API: New
set_parameter()
andget_parameter()
methods - Parameter Validation: Built-in validation based on specifications
-
HTML Comments: Support for
<!-- comments -->
- Migration Tools: Automated conversion utilities
v1.0.0 - Stability Release
- Performance optimizations
- Complete documentation
- Production hardening
Future Enhancements
- Additional storage adapters
- Enhanced directive system with plugins
- Prompt versioning and inheritance
- Performance optimizations for large collections
Development
Looking for feedback and contributors to enhance the capability of prompt_manager.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/MadBomber/prompt_manager.
License
The gem is available as open source under the terms of the MIT License.