Module: Lyman::CLI::Registry
- Defined in:
- lib/lyman/cli/registry.rb
Overview
What lyman installs. Everything the generator plants into a client project is declared here — this list, not directory layout, is the boundary between what lyman does (lib/lyman/cli) and what lyman installs (everything named below).
Constant Summary collapse
- GEM_ROOT =
File.("../../..", __dir__)
- ARTIFACTS =
{ "lyman_entry" => { source: "templates/lib_lyman.rb", dest: "lib/lyman.rb", role: :managed, description: "Library entry point; requires shifty and every planted module" }, "conversation" => { source: "lib/lyman/conversation.rb", dest: "lib/lyman/conversation.rb", role: :managed, description: "The item that flows through pipelines" }, "chat_completion" => { source: "lib/lyman/workers/chat_completion.rb", dest: "lib/lyman/workers/chat_completion.rb", role: :managed, description: "Relay worker: OpenAI-compatible chat completions (streaming + blocking)" }, "tool_execution" => { source: "lib/lyman/workers/tool_execution.rb", dest: "lib/lyman/workers/tool_execution.rb", role: :managed, description: "Relay worker: executes pending tool calls" }, "harness" => { source: "harness/chat.rb", dest: "harness/chat.rb", role: :owned, description: "The wiring script — yours from day one; lyman never updates it" }, "claude_md" => { source: "templates/CLAUDE.md", dest: "CLAUDE.md", role: :owned, alternative: "claude_skill", description: "Guidance for coding agents working in this project" }, # The same guidance as claude_md, packaged as a Claude Code skill — # for projects that already have a CLAUDE.md lyman shouldn't clobber. # `optional:` keeps `new` from planting it (a fresh scaffold gets # claude_md instead); `alternative:` on claude_md points here when # `add` refuses to overwrite an existing CLAUDE.md. "claude_skill" => { source: "templates/SKILL.md", dest: ".claude/skills/lyman/SKILL.md", role: :owned, optional: true, description: "Claude Code skill variant of the CLAUDE.md guidance — for projects with their own CLAUDE.md" }, "gemfile" => { source: "templates/Gemfile", dest: "Gemfile", role: :owned, description: "Client dependencies: shifty (and ostruct for ruby >= 4)" }, "gitignore" => { source: "templates/gitignore", dest: ".gitignore", role: :owned, description: "A minimal starter .gitignore (.lyman/ stays tracked on purpose)" } }.freeze
Class Method Summary collapse
-
.default ⇒ Object
What
newplants: everything except opt-in artifacts (those exist for situations a fresh scaffold can't be in, like a pre-existing CLAUDE.md — reach them withlyman add). - .fetch(name) ⇒ Object
- .managed ⇒ Object
-
.resolve(token, manifest: nil) ⇒ Object
Commands accept an artifact name or a project-relative path — you shouldn't have to remember the token while looking at the file.
- .source_path(spec, source_root: GEM_ROOT) ⇒ Object
Class Method Details
.default ⇒ Object
What new plants: everything except opt-in artifacts (those exist
for situations a fresh scaffold can't be in, like a pre-existing
CLAUDE.md — reach them with lyman add).
109 110 111 |
# File 'lib/lyman/cli/registry.rb', line 109 def self.default ARTIFACTS.reject { |_, spec| spec[:optional] } end |
.fetch(name) ⇒ Object
74 75 76 77 78 79 |
# File 'lib/lyman/cli/registry.rb', line 74 def self.fetch(name) ARTIFACTS.fetch(name) do valid = ARTIFACTS.keys.join(", ") raise Thor::Error, "Unknown artifact #{name.inspect}. Valid artifacts: #{valid}" end end |
.managed ⇒ Object
102 103 104 |
# File 'lib/lyman/cli/registry.rb', line 102 def self.managed ARTIFACTS.select { |_, spec| spec[:role] == :managed } end |
.resolve(token, manifest: nil) ⇒ Object
Commands accept an artifact name or a project-relative path — you shouldn't have to remember the token while looking at the file. Resolution order: registry name, then the path recorded in this project's manifest (authoritative for where the file actually is), then the registry's dest (for artifacts not yet planted).
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/lyman/cli/registry.rb', line 86 def self.resolve(token, manifest: nil) return token if ARTIFACTS.key?(token) path = token.delete_prefix("./") if manifest name, _entry = manifest.artifacts.find { |_, entry| entry["path"] == path } return name if name end name, _spec = ARTIFACTS.find { |_, spec| spec[:dest] == path } return name if name valid = ARTIFACTS.keys.join(", ") raise Thor::Error, "Unknown artifact #{token.inspect}. " \ "Give an artifact name (#{valid}) or a planted path (e.g. lib/lyman/conversation.rb)." end |
.source_path(spec, source_root: GEM_ROOT) ⇒ Object
113 114 115 |
# File 'lib/lyman/cli/registry.rb', line 113 def self.source_path(spec, source_root: GEM_ROOT) File.join(source_root, spec[:source]) end |