Class: Docforge::Config
- Inherits:
-
Object
- Object
- Docforge::Config
- Defined in:
- lib/docforge/config.rb
Overview
Layered configuration.
Precedence (highest wins):
1. ENV vars
2. Project config (./.docforge.yml, or --config PATH)
3. Global config (~/.docforge.yml)
4. Built-in defaults
Env vars:
ANTHROPIC_API_KEY — required, your Anthropic API key
ANTHROPIC_MODEL — model id (overrides yaml `model`)
DOCFORGE_OUTPUT_DIR — where briefs are written
DOCFORGE_AUTHOR — byline on the brief
YAML schema (all keys optional — see ‘docforge init` for a template):
model: claude-sonnet-4-5
output_dir: ~/Desktop/Portfolio/Features
author: Your Name
input_files:
prd: PRD.md
spec: SPEC.md
notes: notes.md
system_prompt: ./prompts/feature_brief.md # relative to this yaml
interview:
- "Who is the human user of this feature?"
- "..."
Constant Summary collapse
- DEFAULT_MODEL =
"claude-sonnet-4-5"- DEFAULT_OUTPUT_DIR =
File.("~/Desktop/Portfolio/Features")
- DEFAULT_AUTHOR =
"You"- DEFAULT_INPUT_FILES =
{ "prd" => "PRD.md", "spec" => "SPEC.md", "notes" => "notes.md" }.freeze
- DEFAULT_INTERVIEW =
[ "Who is the human user of this feature? Name them (e.g. 'Mira, a content designer at an EdTech client').", "What was the world like *before* this shipped — specifically?", "What was the single hardest design decision, and why?", "What's the one metric you'd brag about (or a design target if pre-production)?", "Is there a moment in the build that taught you something worth conveying?" ].freeze
- BUNDLED_SYSTEM_PROMPT_PATH =
File.("../../prompts/system_prompt.md", __dir__)
- GLOBAL_CONFIG_PATH =
File.("~/.docforge.yml")
- PROJECT_CONFIG_NAME =
".docforge.yml"
Instance Attribute Summary collapse
-
#api_key ⇒ Object
readonly
Returns the value of attribute api_key.
-
#author ⇒ Object
readonly
Returns the value of attribute author.
-
#input_filenames ⇒ Object
readonly
Returns the value of attribute input_filenames.
-
#interview_questions ⇒ Object
readonly
Returns the value of attribute interview_questions.
-
#loaded_config_files ⇒ Object
readonly
Returns the value of attribute loaded_config_files.
-
#model ⇒ Object
readonly
Returns the value of attribute model.
-
#output_dir ⇒ Object
readonly
Returns the value of attribute output_dir.
-
#system_prompt_path ⇒ Object
readonly
Returns the value of attribute system_prompt_path.
Instance Method Summary collapse
-
#initialize(env: ENV, explicit_config_path: nil, cwd: Dir.pwd) ⇒ Config
constructor
A new instance of Config.
- #system_prompt_content ⇒ Object
- #to_h ⇒ Object
- #validate! ⇒ Object
Constructor Details
#initialize(env: ENV, explicit_config_path: nil, cwd: Dir.pwd) ⇒ Config
Returns a new instance of Config.
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/docforge/config.rb', line 54 def initialize(env: ENV, explicit_config_path: nil, cwd: Dir.pwd) @loaded_config_files = [] global = load_yaml(GLOBAL_CONFIG_PATH) project = load_yaml(explicit_config_path || File.join(cwd, PROJECT_CONFIG_NAME)) merged = global.merge(project) @api_key = env["ANTHROPIC_API_KEY"] @model = env["ANTHROPIC_MODEL"] || merged["model"] || DEFAULT_MODEL @output_dir = env["DOCFORGE_OUTPUT_DIR"] || merged["output_dir"] || DEFAULT_OUTPUT_DIR @author = env["DOCFORGE_AUTHOR"] || merged["author"] || DEFAULT_AUTHOR @output_dir = File.(@output_dir) @input_filenames = DEFAULT_INPUT_FILES.merge(merged["input_files"] || {}) @interview_questions = Array(merged["interview"]).then { |a| a.empty? ? DEFAULT_INTERVIEW : a } @system_prompt_path = resolve_system_prompt_path(merged["system_prompt"], merged["_loaded_from"]) end |
Instance Attribute Details
#api_key ⇒ Object (readonly)
Returns the value of attribute api_key.
50 51 52 |
# File 'lib/docforge/config.rb', line 50 def api_key @api_key end |
#author ⇒ Object (readonly)
Returns the value of attribute author.
50 51 52 |
# File 'lib/docforge/config.rb', line 50 def @author end |
#input_filenames ⇒ Object (readonly)
Returns the value of attribute input_filenames.
50 51 52 |
# File 'lib/docforge/config.rb', line 50 def input_filenames @input_filenames end |
#interview_questions ⇒ Object (readonly)
Returns the value of attribute interview_questions.
50 51 52 |
# File 'lib/docforge/config.rb', line 50 def interview_questions @interview_questions end |
#loaded_config_files ⇒ Object (readonly)
Returns the value of attribute loaded_config_files.
50 51 52 |
# File 'lib/docforge/config.rb', line 50 def loaded_config_files @loaded_config_files end |
#model ⇒ Object (readonly)
Returns the value of attribute model.
50 51 52 |
# File 'lib/docforge/config.rb', line 50 def model @model end |
#output_dir ⇒ Object (readonly)
Returns the value of attribute output_dir.
50 51 52 |
# File 'lib/docforge/config.rb', line 50 def output_dir @output_dir end |
#system_prompt_path ⇒ Object (readonly)
Returns the value of attribute system_prompt_path.
50 51 52 |
# File 'lib/docforge/config.rb', line 50 def system_prompt_path @system_prompt_path end |
Instance Method Details
#system_prompt_content ⇒ Object
72 73 74 |
# File 'lib/docforge/config.rb', line 72 def system_prompt_content @system_prompt_content ||= File.read(@system_prompt_path) end |
#to_h ⇒ Object
90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/docforge/config.rb', line 90 def to_h { api_key_set: !api_key.nil? && !api_key.empty?, model: model, output_dir: output_dir, author: , input_filenames: input_filenames, system_prompt_path: system_prompt_path, interview_question_count: interview_questions.size, loaded_config_files: loaded_config_files } end |
#validate! ⇒ Object
76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/docforge/config.rb', line 76 def validate! if api_key.nil? || api_key.strip.empty? raise ConfigError, <<~MSG ANTHROPIC_API_KEY is not set. Get one at https://console.anthropic.com/settings/keys and export it: export ANTHROPIC_API_KEY=sk-ant-... MSG end unless File.exist?(@system_prompt_path) raise ConfigError, "System prompt file not found: #{@system_prompt_path}" end true end |