the_local 0.3.0 → 0.4.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +29 -1
- data/CLAUDE.md +117 -0
- data/MIGRATING.md +478 -0
- data/PROVIDERS.md +62 -123
- data/README.md +20 -14
- data/lib/generators/the_local/provider_generator.rb +15 -90
- data/lib/the_local/agent.rb +3 -2
- data/lib/the_local/author.rb +43 -0
- data/lib/the_local/creators/develop.md +81 -0
- data/lib/the_local/creators/info.md +67 -0
- data/lib/the_local/creators/install.md +79 -0
- data/lib/the_local/disk_providers.rb +18 -10
- data/lib/the_local/format.rb +27 -0
- data/lib/the_local/front_matter.rb +26 -0
- data/lib/the_local/installer.rb +2 -2
- data/lib/the_local/interface.rb +26 -0
- data/lib/the_local/provider_check.rb +92 -0
- data/lib/the_local/rake.rb +14 -9
- data/lib/the_local/registry.rb +2 -30
- data/lib/the_local/version.rb +1 -1
- data/lib/the_local.rb +1 -20
- data/the_local/agents/the_local-develop.md +48 -0
- data/the_local/agents/the_local-info.md +40 -0
- data/the_local/agents/the_local-install.md +49 -0
- data/the_local/interface.yml +21 -0
- metadata +16 -12
- data/lib/generators/the_local/templates/guide.md.tt +0 -41
- data/lib/generators/the_local/templates/reference.rb.tt +0 -17
- data/lib/generators/the_local/templates/the_local.rb.tt +0 -49
- data/lib/the_local/builder.rb +0 -57
- data/lib/the_local/reference/guide.md +0 -179
- data/lib/the_local/reference.rb +0 -16
- data/lib/the_local/the_local/agents/the_local-develop.md +0 -187
- data/lib/the_local/the_local/agents/the_local-info.md +0 -187
- data/lib/the_local/the_local/agents/the_local-install.md +0 -187
- data/lib/the_local/the_local.rb +0 -59
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
## <%= module_name %>
|
|
2
|
-
|
|
3
|
-
> **DO NOT** explore the <%= gem_name %> gem source code. This reference is the
|
|
4
|
-
> complete user-facing API, embedded verbatim into every <%= gem_name %> local so
|
|
5
|
-
> their guidance never drifts. Keep it the single source of truth.
|
|
6
|
-
>
|
|
7
|
-
> The bar for everything below: a host agent must be able to do <%= gem_name %>
|
|
8
|
-
> work from this guide alone — exact signatures and a complete, copy-paste
|
|
9
|
-
> recipe — without ever opening <%= gem_name %>'s source. If a signature or step
|
|
10
|
-
> is missing, the agent will dig into source, which is the cost the_local exists
|
|
11
|
-
> to remove. Replace every TODO; `rake the_local:build` refuses a guide that
|
|
12
|
-
> still has one.
|
|
13
|
-
|
|
14
|
-
TODO: One paragraph — what <%= gem_name %> is and the problem it solves.
|
|
15
|
-
|
|
16
|
-
### Interface
|
|
17
|
-
|
|
18
|
-
TODO: The literal public API a host calls — every method/class/DSL entry with
|
|
19
|
-
its exact signature: arguments, which are required vs optional, and what it
|
|
20
|
-
returns. Give the signatures themselves, each with a one-line example, not prose
|
|
21
|
-
about them. This is what the `info` and `<%= worker %>` locals answer from, so an
|
|
22
|
-
agent never has to read source to recall how a call is shaped.
|
|
23
|
-
|
|
24
|
-
### Recipe
|
|
25
|
-
|
|
26
|
-
TODO: A complete, copy-paste implementation of the most common <%= gem_name %>
|
|
27
|
-
task — the whole thing, not a fragment — so the `<%= worker %>` local reproduces
|
|
28
|
-
it identically every time instead of re-deriving it from source.
|
|
29
|
-
|
|
30
|
-
### Install
|
|
31
|
-
|
|
32
|
-
TODO: The exact, correct steps to add <%= gem_name %> to a host and set it up —
|
|
33
|
-
this is what the `install` local follows. Be specific to how <%= gem_name %> is
|
|
34
|
-
actually installed (e.g. for a Rails engine: add the gem, `bundle install`,
|
|
35
|
-
install + run migrations, wire any concerns/initializers). Don't leave it
|
|
36
|
-
generic.
|
|
37
|
-
|
|
38
|
-
### Conventions
|
|
39
|
-
|
|
40
|
-
TODO: The conventions the `<%= worker %>` local must enforce when doing
|
|
41
|
-
<%= gem_name %> work, so usage stays consistent across the host.
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
<%= open_module %>
|
|
4
|
-
# Single source of truth for <%= gem_name %>'s user-facing API, read by the
|
|
5
|
-
# the_local companion subagents so their guidance never drifts from the docs.
|
|
6
|
-
module Reference
|
|
7
|
-
DIR = File.expand_path("reference", __dir__)
|
|
8
|
-
|
|
9
|
-
def self.content
|
|
10
|
-
read("guide.md")
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def self.read(name)
|
|
14
|
-
File.read(File.join(DIR, name)).chomp
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
<%= close_module %>
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative "reference"
|
|
4
|
-
|
|
5
|
-
<%= open_module %>
|
|
6
|
-
# Registers <%= gem_name %>'s locals (Claude Code subagents) with the_local.
|
|
7
|
-
# These are the common command interface every provider exposes to apps:
|
|
8
|
-
# `info` (read-only, explains the gem), `install` (sets it up in a host), and
|
|
9
|
-
# `<%= worker %>` (the proactive domain worker). Soft dependency: registration
|
|
10
|
-
# is a no-op when the_local is absent.
|
|
11
|
-
module Companion
|
|
12
|
-
def self.register!
|
|
13
|
-
TheLocal.register("<%= gem_name %>"<%= ", prefix: \"#{prefix}\"" unless prefix == gem_name %>, scope: "<%= scope %>",
|
|
14
|
-
agents_dir: File.expand_path("the_local/agents", __dir__)) do |c|
|
|
15
|
-
c.agent "info",
|
|
16
|
-
description: "Use to learn what <%= gem_name %> offers — its API and conventions.",
|
|
17
|
-
tools: "Read",
|
|
18
|
-
body: "You explain what <%= gem_name %> does and how to use it, answering only from " \
|
|
19
|
-
"your reference. You make no changes, and you never read <%= gem_name %>'s " \
|
|
20
|
-
"source — the reference is the complete interface.",
|
|
21
|
-
knowledge: <%= module_name %>::Reference.content
|
|
22
|
-
|
|
23
|
-
c.agent "install",
|
|
24
|
-
description: "Use to add <%= gem_name %> to a project and set it up correctly.",
|
|
25
|
-
tools: "Bash, Read, Edit",
|
|
26
|
-
body: "You add <%= gem_name %> to the project and complete its setup by following your " \
|
|
27
|
-
"reference's Install section exactly, step by step. You do not invent steps it " \
|
|
28
|
-
"does not list, and you never read <%= gem_name %>'s source.",
|
|
29
|
-
knowledge: <%= module_name %>::Reference.content
|
|
30
|
-
|
|
31
|
-
c.agent "<%= worker %>",
|
|
32
|
-
description: "Use PROACTIVELY for any <%= gem_name %> work. MUST BE USED instead of " \
|
|
33
|
-
"hand-rolling it. TODO: name the concrete tasks this local owns.",
|
|
34
|
-
tools: "Read, Write, Edit, Grep",
|
|
35
|
-
body: "You do <%= gem_name %> work by following the Interface, Recipe, and Conventions " \
|
|
36
|
-
"in your reference exactly, so usage stays consistent across the host. You " \
|
|
37
|
-
"implement from the reference, never from <%= gem_name %>'s source.",
|
|
38
|
-
knowledge: <%= module_name %>::Reference.content
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
<%= close_module %>
|
|
43
|
-
|
|
44
|
-
begin
|
|
45
|
-
require "the_local"
|
|
46
|
-
<%= module_name %>::Companion.register!
|
|
47
|
-
rescue LoadError
|
|
48
|
-
# the_local not installed — <%= gem_name %> works standalone.
|
|
49
|
-
end
|
data/lib/the_local/builder.rb
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "fileutils"
|
|
4
|
-
|
|
5
|
-
module TheLocal
|
|
6
|
-
# Renders each registered agent's markdown to its committed source_path, so a
|
|
7
|
-
# provider gem can commit the files and the host installer later copies them
|
|
8
|
-
# verbatim (rather than rendering at install time). Plain Ruby — driven by the
|
|
9
|
-
# the_local:build rake task a provider runs. Agents that declared no agents_dir
|
|
10
|
-
# (and so have no source_path) are skipped: there is nowhere to write them.
|
|
11
|
-
class Builder
|
|
12
|
-
# A real placeholder is a line-leading "TODO:"; an inline mention of the
|
|
13
|
-
# marker (a guide documenting the convention) is left alone.
|
|
14
|
-
PLACEHOLDER = /^\s*TODO:/
|
|
15
|
-
|
|
16
|
-
# The canonical sections every guide must carry, so a consuming agent meets
|
|
17
|
-
# the same shape in every gem's local. Matched as header prefixes.
|
|
18
|
-
REQUIRED_SECTIONS = ["### Interface", "### Recipe", "### Install", "### Conventions"].freeze
|
|
19
|
-
|
|
20
|
-
def initialize(registry:, validate: false)
|
|
21
|
-
@registry = registry
|
|
22
|
-
@validate = validate
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def call
|
|
26
|
-
validate! if @validate
|
|
27
|
-
|
|
28
|
-
buildable_agents.map do |agent|
|
|
29
|
-
FileUtils.mkdir_p(File.dirname(agent.source_path))
|
|
30
|
-
File.write(agent.source_path, agent.to_markdown)
|
|
31
|
-
agent.source_path
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
private
|
|
36
|
-
|
|
37
|
-
def validate!
|
|
38
|
-
problems = buildable_agents.flat_map { |agent| problems_for(agent) }
|
|
39
|
-
return if problems.empty?
|
|
40
|
-
|
|
41
|
-
raise Error, "the_local: incomplete guide(s):\n- #{problems.join("\n- ")}"
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def problems_for(agent)
|
|
45
|
-
markdown = agent.to_markdown
|
|
46
|
-
problems = []
|
|
47
|
-
problems << "#{agent.qualified_name}: TODO: placeholders remain" if markdown.match?(PLACEHOLDER)
|
|
48
|
-
missing = REQUIRED_SECTIONS.reject { |section| markdown.include?(section) }
|
|
49
|
-
problems << "#{agent.qualified_name}: missing #{missing.join(", ")}" if missing.any?
|
|
50
|
-
problems
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
def buildable_agents
|
|
54
|
-
@registry.agents.select(&:source_path)
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
end
|
|
@@ -1,179 +0,0 @@
|
|
|
1
|
-
## TheLocal
|
|
2
|
-
|
|
3
|
-
> **DO NOT** explore the the_local gem source code. This reference is the
|
|
4
|
-
> complete user-facing API, embedded verbatim into every the_local local so
|
|
5
|
-
> their guidance never drifts. Keep it the single source of truth.
|
|
6
|
-
|
|
7
|
-
the_local is the engine that lets any gem or app ship resident Claude Code
|
|
8
|
-
expert subagents ("locals") that know its conventions. A provider gem registers
|
|
9
|
-
its locals once; the_local renders them to committed `.md` files and installs
|
|
10
|
-
the aggregated set from every directly-depended provider into a consuming app's
|
|
11
|
-
`.claude/agents/`, plus a delegation rule so the host's agent actually uses them.
|
|
12
|
-
|
|
13
|
-
### The model
|
|
14
|
-
|
|
15
|
-
- **Providers define locals.** A gem (or the app) calls `TheLocal.register` to
|
|
16
|
-
declare its locals; each `c.agent` becomes one local. The register block runs
|
|
17
|
-
only at build time, behind a soft `require "the_local"` guard so the gem still
|
|
18
|
-
works standalone.
|
|
19
|
-
- **`the_local:build` renders committed `.md`.** The provider runs
|
|
20
|
-
`rake the_local:build`; `TheLocal::Builder` writes each agent to its
|
|
21
|
-
`source_path` under `lib/<gem>/the_local/agents/<prefix>-<name>.md`. The
|
|
22
|
-
rendered files are committed to the provider's repo. **These committed files
|
|
23
|
-
are the contract** — they are what a host reads. The register block + `guide.md`
|
|
24
|
-
are the source of truth they're built from.
|
|
25
|
-
- **Install discovers committed `.md` on disk.** In a host, install reads each
|
|
26
|
-
direct dependency's committed `lib/**/the_local/agents/*.md` straight from its
|
|
27
|
-
gem path and copies them into `.claude/agents/` byte-for-byte — no provider
|
|
28
|
-
code is loaded and no register block runs in the host. Output depends only on
|
|
29
|
-
the provider gem version (a true carbon copy across every app), a provider needs
|
|
30
|
-
no install-time wiring to be found, and a fragile gem can't crash the install.
|
|
31
|
-
- **The delegation trigger.** Install also writes a registry-generated block into
|
|
32
|
-
the host's `CLAUDE.md`/`AGENTS.md` telling the host agent to delegate to these
|
|
33
|
-
locals. This is what makes delegation actually happen.
|
|
34
|
-
- **Direct-dependency scope.** Only the host's *direct* dependencies contribute
|
|
35
|
-
locals; transitive provider gems are filtered out, so a host gets exactly the
|
|
36
|
-
experts for the gems it chose.
|
|
37
|
-
|
|
38
|
-
### Install (in any gem or app)
|
|
39
|
-
|
|
40
|
-
1. Add `gem "the_local"` to the host's `Gemfile`, then `bundle install`.
|
|
41
|
-
2. Run `bundle exec the_local install`. This syncs every direct provider's
|
|
42
|
-
committed locals into `.claude/agents/` and writes the delegation trigger
|
|
43
|
-
into `CLAUDE.md`/`AGENTS.md`. It needs no Rails — a plain gem installs the
|
|
44
|
-
same way an app does.
|
|
45
|
-
3. Re-run `bundle exec the_local install` after any bundle change (a provider
|
|
46
|
-
added, removed, or upgraded) to bring the host's locals back in sync. The
|
|
47
|
-
shell can automate this; the gem only exposes the command.
|
|
48
|
-
|
|
49
|
-
Rails apps can equivalently run `bin/rails g the_local:install` and
|
|
50
|
-
`the_local:refresh`; a gem that already wires `require "the_local/rake"` into
|
|
51
|
-
its Rakefile also gets `rake the_local:install`. All three share one engine.
|
|
52
|
-
|
|
53
|
-
### Author a provider (turn a gem into a provider)
|
|
54
|
-
|
|
55
|
-
1. Run `bin/rails g the_local:provider <gem_name>` (pass `--scope`,
|
|
56
|
-
`--prefix`, `--worker` as needed). It scaffolds `lib/<gem>/reference.rb`, a
|
|
57
|
-
`lib/<gem>/reference/guide.md`, and a `lib/<gem>/the_local.rb` companion that
|
|
58
|
-
registers the standard interface; hooks `the_local:build` into the `Rakefile`;
|
|
59
|
-
requires the companion from the gem entrypoint; and builds the committed
|
|
60
|
-
`.md` for review.
|
|
61
|
-
2. Write `guide.md` to the canonical shape — the same sections in every
|
|
62
|
-
provider, so the consuming agent meets one structure everywhere and
|
|
63
|
-
`rake the_local:build` rejects a guide missing one:
|
|
64
|
-
- **Interface** — every public call's *exact signature* (arguments, required
|
|
65
|
-
vs optional, return) as real signatures in a code block, not prose.
|
|
66
|
-
- **Recipe** — a complete copy-paste implementation of the common task.
|
|
67
|
-
- **Install** — the exact setup steps for *this* gem.
|
|
68
|
-
- **Conventions** — what the worker enforces to keep usage consistent.
|
|
69
|
-
|
|
70
|
-
The bar: a host agent does your gem's work from the guide alone, without ever
|
|
71
|
-
opening your source. Document your own gem only; name companion gems but do
|
|
72
|
-
not explain their internals.
|
|
73
|
-
3. Tailor the register block bodies and `scope` to your gem; the standard
|
|
74
|
-
interface is `info` (read-only explainer), `install` (sets the gem up in a
|
|
75
|
-
host), and a domain worker (`develop` for libraries, `operate` for CLIs).
|
|
76
|
-
4. Run `rake the_local:build`, then **commit and ship**
|
|
77
|
-
`lib/<gem>/the_local/agents/*.md` (they must be in the gemspec's `files`).
|
|
78
|
-
This is the whole contract: a host discovers your locals by reading these
|
|
79
|
-
committed files from your gem on disk — it never loads your gem or runs your
|
|
80
|
-
register block — so if they aren't committed and shipped, you contribute
|
|
81
|
-
nothing, and if they are, you contribute everything. A drift test asserting
|
|
82
|
-
each committed file equals its `agent.to_markdown` keeps the artifact honest.
|
|
83
|
-
|
|
84
|
-
### Interface
|
|
85
|
-
|
|
86
|
-
The complete public surface — every entry point with its exact signature, so a
|
|
87
|
-
local answers from here instead of reading source.
|
|
88
|
-
|
|
89
|
-
**Register locals (provider Ruby, behind a soft `require "the_local"` guard):**
|
|
90
|
-
|
|
91
|
-
```ruby
|
|
92
|
-
TheLocal.register(gem_name, prefix: gem_name, scope: nil, agents_dir: nil) { |c| … }
|
|
93
|
-
# Registers a provider and yields a Collector. gem_name is positional and
|
|
94
|
-
# filters to a host's direct dependencies; prefix is the filename namespace
|
|
95
|
-
# (defaults to gem_name); scope is the one-line delegation phrase; agents_dir
|
|
96
|
-
# is the absolute path to the committed .md files (each agent records its
|
|
97
|
-
# source_path there for the installer to copy verbatim).
|
|
98
|
-
|
|
99
|
-
c.agent(name, description:, tools:, body:, knowledge: nil)
|
|
100
|
-
# Declares one local. name is positional; description, tools, body are
|
|
101
|
-
# required; knowledge — a String or Array of Strings, usually
|
|
102
|
-
# MyGem::Reference.content — is optional and appended below the body.
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
```ruby
|
|
106
|
-
TheLocal.register("my_gem", prefix: "my_gem", scope: "one-line domain phrase",
|
|
107
|
-
agents_dir: File.expand_path("the_local/agents", __dir__)) do |c|
|
|
108
|
-
c.agent "info",
|
|
109
|
-
description: "Use to learn what my_gem offers.",
|
|
110
|
-
tools: "Read",
|
|
111
|
-
body: "You explain my_gem, answering only from the reference. You make no changes.",
|
|
112
|
-
knowledge: MyGem::Reference.content
|
|
113
|
-
end
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
**Build (provider Rakefile, after `require "the_local/rake"`):**
|
|
117
|
-
|
|
118
|
-
- `rake the_local:build` — renders each registered agent to its committed
|
|
119
|
-
`lib/<gem>/the_local/agents/<prefix>-<name>.md`. Refuses to render a guide that
|
|
120
|
-
still holds a `TODO:` placeholder or is missing a canonical section.
|
|
121
|
-
- `rake the_local:install` — installs/refreshes this project's own locals.
|
|
122
|
-
|
|
123
|
-
**Host (consuming app or gem):**
|
|
124
|
-
|
|
125
|
-
- `bundle exec the_local install` — CLI; syncs direct providers' locals into
|
|
126
|
-
`.claude/agents/` and writes the delegation trigger. No Rails required.
|
|
127
|
-
- `bin/rails g the_local:install` and `rake the_local:refresh` — Rails equivalents.
|
|
128
|
-
- `bin/rails g the_local:provider <gem_name> [--prefix P] [--scope "…"] [--worker develop|operate]`
|
|
129
|
-
— scaffolds the provider wiring (Reference loader, guide, companion).
|
|
130
|
-
|
|
131
|
-
### Recipe
|
|
132
|
-
|
|
133
|
-
Turn a gem into a provider — the complete companion, copy-paste and rename:
|
|
134
|
-
|
|
135
|
-
```ruby
|
|
136
|
-
# lib/my_gem/the_local.rb
|
|
137
|
-
require_relative "reference"
|
|
138
|
-
|
|
139
|
-
module MyGem
|
|
140
|
-
module Companion
|
|
141
|
-
def self.register!
|
|
142
|
-
TheLocal.register("my_gem", scope: "one-line domain phrase",
|
|
143
|
-
agents_dir: File.expand_path("the_local/agents", __dir__)) do |c|
|
|
144
|
-
c.agent "info",
|
|
145
|
-
description: "Use to learn what my_gem offers.",
|
|
146
|
-
tools: "Read",
|
|
147
|
-
body: "You explain what my_gem does, answering only from your reference. " \
|
|
148
|
-
"You make no changes and never read my_gem's source.",
|
|
149
|
-
knowledge: MyGem::Reference.content
|
|
150
|
-
|
|
151
|
-
c.agent "develop",
|
|
152
|
-
description: "Use PROACTIVELY for any my_gem work.",
|
|
153
|
-
tools: "Read, Write, Edit, Grep",
|
|
154
|
-
body: "You do my_gem work by following your reference's Interface, Recipe, " \
|
|
155
|
-
"and Conventions exactly. You implement from the reference, never source.",
|
|
156
|
-
knowledge: MyGem::Reference.content
|
|
157
|
-
end
|
|
158
|
-
end
|
|
159
|
-
end
|
|
160
|
-
end
|
|
161
|
-
|
|
162
|
-
begin
|
|
163
|
-
require "the_local"
|
|
164
|
-
MyGem::Companion.register!
|
|
165
|
-
rescue LoadError
|
|
166
|
-
# the_local not installed — my_gem works standalone.
|
|
167
|
-
end
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
Then write `reference/guide.md` to the canonical shape, `rake the_local:build`,
|
|
171
|
-
and commit `lib/my_gem/the_local/agents/*.md`.
|
|
172
|
-
|
|
173
|
-
### Conventions
|
|
174
|
-
|
|
175
|
-
- The register block lives behind `begin require "the_local" … rescue LoadError`
|
|
176
|
-
so the gem still works when the_local is absent.
|
|
177
|
-
- `guide.md` documents the providing gem only and stays the single source of
|
|
178
|
-
truth; never let a rendered `.md` drift from `agent.to_markdown`.
|
|
179
|
-
- Commit the rendered `.md`; never render in the host at install time.
|
data/lib/the_local/reference.rb
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module TheLocal
|
|
4
|
-
# Loads the_local's own knowledge guide, embedded verbatim into its locals.
|
|
5
|
-
module Reference
|
|
6
|
-
DIR = File.expand_path("reference", __dir__)
|
|
7
|
-
|
|
8
|
-
def self.content
|
|
9
|
-
read("guide.md")
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def self.read(name)
|
|
13
|
-
File.read(File.join(DIR, name)).chomp
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
end
|
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: the_local-develop
|
|
3
|
-
description: Use PROACTIVELY to turn a gem into a the_local provider — scaffolding the companion, authoring the guide, and committing the rendered locals. MUST BE USED instead of wiring a provider by hand.
|
|
4
|
-
tools: Read, Write, Edit, Grep
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
You turn a gem into a the_local provider following the reference's provider-author workflow: run `the_local:provider`, write guide.md as the single source of truth (your own gem only), tailor the register block, and hook the_local:build into the Rakefile. The deliverable is the committed, shipped lib/<gem>/the_local/agents/*.md — that is the whole contract a host reads from disk; a host never loads the gem, so unless those files are built, committed, and in the gemspec, the gem contributes nothing. You keep them in sync with agent.to_markdown.
|
|
8
|
-
|
|
9
|
-
## TheLocal
|
|
10
|
-
|
|
11
|
-
> **DO NOT** explore the the_local gem source code. This reference is the
|
|
12
|
-
> complete user-facing API, embedded verbatim into every the_local local so
|
|
13
|
-
> their guidance never drifts. Keep it the single source of truth.
|
|
14
|
-
|
|
15
|
-
the_local is the engine that lets any gem or app ship resident Claude Code
|
|
16
|
-
expert subagents ("locals") that know its conventions. A provider gem registers
|
|
17
|
-
its locals once; the_local renders them to committed `.md` files and installs
|
|
18
|
-
the aggregated set from every directly-depended provider into a consuming app's
|
|
19
|
-
`.claude/agents/`, plus a delegation rule so the host's agent actually uses them.
|
|
20
|
-
|
|
21
|
-
### The model
|
|
22
|
-
|
|
23
|
-
- **Providers define locals.** A gem (or the app) calls `TheLocal.register` to
|
|
24
|
-
declare its locals; each `c.agent` becomes one local. The register block runs
|
|
25
|
-
only at build time, behind a soft `require "the_local"` guard so the gem still
|
|
26
|
-
works standalone.
|
|
27
|
-
- **`the_local:build` renders committed `.md`.** The provider runs
|
|
28
|
-
`rake the_local:build`; `TheLocal::Builder` writes each agent to its
|
|
29
|
-
`source_path` under `lib/<gem>/the_local/agents/<prefix>-<name>.md`. The
|
|
30
|
-
rendered files are committed to the provider's repo. **These committed files
|
|
31
|
-
are the contract** — they are what a host reads. The register block + `guide.md`
|
|
32
|
-
are the source of truth they're built from.
|
|
33
|
-
- **Install discovers committed `.md` on disk.** In a host, install reads each
|
|
34
|
-
direct dependency's committed `lib/**/the_local/agents/*.md` straight from its
|
|
35
|
-
gem path and copies them into `.claude/agents/` byte-for-byte — no provider
|
|
36
|
-
code is loaded and no register block runs in the host. Output depends only on
|
|
37
|
-
the provider gem version (a true carbon copy across every app), a provider needs
|
|
38
|
-
no install-time wiring to be found, and a fragile gem can't crash the install.
|
|
39
|
-
- **The delegation trigger.** Install also writes a registry-generated block into
|
|
40
|
-
the host's `CLAUDE.md`/`AGENTS.md` telling the host agent to delegate to these
|
|
41
|
-
locals. This is what makes delegation actually happen.
|
|
42
|
-
- **Direct-dependency scope.** Only the host's *direct* dependencies contribute
|
|
43
|
-
locals; transitive provider gems are filtered out, so a host gets exactly the
|
|
44
|
-
experts for the gems it chose.
|
|
45
|
-
|
|
46
|
-
### Install (in any gem or app)
|
|
47
|
-
|
|
48
|
-
1. Add `gem "the_local"` to the host's `Gemfile`, then `bundle install`.
|
|
49
|
-
2. Run `bundle exec the_local install`. This syncs every direct provider's
|
|
50
|
-
committed locals into `.claude/agents/` and writes the delegation trigger
|
|
51
|
-
into `CLAUDE.md`/`AGENTS.md`. It needs no Rails — a plain gem installs the
|
|
52
|
-
same way an app does.
|
|
53
|
-
3. Re-run `bundle exec the_local install` after any bundle change (a provider
|
|
54
|
-
added, removed, or upgraded) to bring the host's locals back in sync. The
|
|
55
|
-
shell can automate this; the gem only exposes the command.
|
|
56
|
-
|
|
57
|
-
Rails apps can equivalently run `bin/rails g the_local:install` and
|
|
58
|
-
`the_local:refresh`; a gem that already wires `require "the_local/rake"` into
|
|
59
|
-
its Rakefile also gets `rake the_local:install`. All three share one engine.
|
|
60
|
-
|
|
61
|
-
### Author a provider (turn a gem into a provider)
|
|
62
|
-
|
|
63
|
-
1. Run `bin/rails g the_local:provider <gem_name>` (pass `--scope`,
|
|
64
|
-
`--prefix`, `--worker` as needed). It scaffolds `lib/<gem>/reference.rb`, a
|
|
65
|
-
`lib/<gem>/reference/guide.md`, and a `lib/<gem>/the_local.rb` companion that
|
|
66
|
-
registers the standard interface; hooks `the_local:build` into the `Rakefile`;
|
|
67
|
-
requires the companion from the gem entrypoint; and builds the committed
|
|
68
|
-
`.md` for review.
|
|
69
|
-
2. Write `guide.md` to the canonical shape — the same sections in every
|
|
70
|
-
provider, so the consuming agent meets one structure everywhere and
|
|
71
|
-
`rake the_local:build` rejects a guide missing one:
|
|
72
|
-
- **Interface** — every public call's *exact signature* (arguments, required
|
|
73
|
-
vs optional, return) as real signatures in a code block, not prose.
|
|
74
|
-
- **Recipe** — a complete copy-paste implementation of the common task.
|
|
75
|
-
- **Install** — the exact setup steps for *this* gem.
|
|
76
|
-
- **Conventions** — what the worker enforces to keep usage consistent.
|
|
77
|
-
|
|
78
|
-
The bar: a host agent does your gem's work from the guide alone, without ever
|
|
79
|
-
opening your source. Document your own gem only; name companion gems but do
|
|
80
|
-
not explain their internals.
|
|
81
|
-
3. Tailor the register block bodies and `scope` to your gem; the standard
|
|
82
|
-
interface is `info` (read-only explainer), `install` (sets the gem up in a
|
|
83
|
-
host), and a domain worker (`develop` for libraries, `operate` for CLIs).
|
|
84
|
-
4. Run `rake the_local:build`, then **commit and ship**
|
|
85
|
-
`lib/<gem>/the_local/agents/*.md` (they must be in the gemspec's `files`).
|
|
86
|
-
This is the whole contract: a host discovers your locals by reading these
|
|
87
|
-
committed files from your gem on disk — it never loads your gem or runs your
|
|
88
|
-
register block — so if they aren't committed and shipped, you contribute
|
|
89
|
-
nothing, and if they are, you contribute everything. A drift test asserting
|
|
90
|
-
each committed file equals its `agent.to_markdown` keeps the artifact honest.
|
|
91
|
-
|
|
92
|
-
### Interface
|
|
93
|
-
|
|
94
|
-
The complete public surface — every entry point with its exact signature, so a
|
|
95
|
-
local answers from here instead of reading source.
|
|
96
|
-
|
|
97
|
-
**Register locals (provider Ruby, behind a soft `require "the_local"` guard):**
|
|
98
|
-
|
|
99
|
-
```ruby
|
|
100
|
-
TheLocal.register(gem_name, prefix: gem_name, scope: nil, agents_dir: nil) { |c| … }
|
|
101
|
-
# Registers a provider and yields a Collector. gem_name is positional and
|
|
102
|
-
# filters to a host's direct dependencies; prefix is the filename namespace
|
|
103
|
-
# (defaults to gem_name); scope is the one-line delegation phrase; agents_dir
|
|
104
|
-
# is the absolute path to the committed .md files (each agent records its
|
|
105
|
-
# source_path there for the installer to copy verbatim).
|
|
106
|
-
|
|
107
|
-
c.agent(name, description:, tools:, body:, knowledge: nil)
|
|
108
|
-
# Declares one local. name is positional; description, tools, body are
|
|
109
|
-
# required; knowledge — a String or Array of Strings, usually
|
|
110
|
-
# MyGem::Reference.content — is optional and appended below the body.
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
```ruby
|
|
114
|
-
TheLocal.register("my_gem", prefix: "my_gem", scope: "one-line domain phrase",
|
|
115
|
-
agents_dir: File.expand_path("the_local/agents", __dir__)) do |c|
|
|
116
|
-
c.agent "info",
|
|
117
|
-
description: "Use to learn what my_gem offers.",
|
|
118
|
-
tools: "Read",
|
|
119
|
-
body: "You explain my_gem, answering only from the reference. You make no changes.",
|
|
120
|
-
knowledge: MyGem::Reference.content
|
|
121
|
-
end
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
**Build (provider Rakefile, after `require "the_local/rake"`):**
|
|
125
|
-
|
|
126
|
-
- `rake the_local:build` — renders each registered agent to its committed
|
|
127
|
-
`lib/<gem>/the_local/agents/<prefix>-<name>.md`. Refuses to render a guide that
|
|
128
|
-
still holds a `TODO:` placeholder or is missing a canonical section.
|
|
129
|
-
- `rake the_local:install` — installs/refreshes this project's own locals.
|
|
130
|
-
|
|
131
|
-
**Host (consuming app or gem):**
|
|
132
|
-
|
|
133
|
-
- `bundle exec the_local install` — CLI; syncs direct providers' locals into
|
|
134
|
-
`.claude/agents/` and writes the delegation trigger. No Rails required.
|
|
135
|
-
- `bin/rails g the_local:install` and `rake the_local:refresh` — Rails equivalents.
|
|
136
|
-
- `bin/rails g the_local:provider <gem_name> [--prefix P] [--scope "…"] [--worker develop|operate]`
|
|
137
|
-
— scaffolds the provider wiring (Reference loader, guide, companion).
|
|
138
|
-
|
|
139
|
-
### Recipe
|
|
140
|
-
|
|
141
|
-
Turn a gem into a provider — the complete companion, copy-paste and rename:
|
|
142
|
-
|
|
143
|
-
```ruby
|
|
144
|
-
# lib/my_gem/the_local.rb
|
|
145
|
-
require_relative "reference"
|
|
146
|
-
|
|
147
|
-
module MyGem
|
|
148
|
-
module Companion
|
|
149
|
-
def self.register!
|
|
150
|
-
TheLocal.register("my_gem", scope: "one-line domain phrase",
|
|
151
|
-
agents_dir: File.expand_path("the_local/agents", __dir__)) do |c|
|
|
152
|
-
c.agent "info",
|
|
153
|
-
description: "Use to learn what my_gem offers.",
|
|
154
|
-
tools: "Read",
|
|
155
|
-
body: "You explain what my_gem does, answering only from your reference. " \
|
|
156
|
-
"You make no changes and never read my_gem's source.",
|
|
157
|
-
knowledge: MyGem::Reference.content
|
|
158
|
-
|
|
159
|
-
c.agent "develop",
|
|
160
|
-
description: "Use PROACTIVELY for any my_gem work.",
|
|
161
|
-
tools: "Read, Write, Edit, Grep",
|
|
162
|
-
body: "You do my_gem work by following your reference's Interface, Recipe, " \
|
|
163
|
-
"and Conventions exactly. You implement from the reference, never source.",
|
|
164
|
-
knowledge: MyGem::Reference.content
|
|
165
|
-
end
|
|
166
|
-
end
|
|
167
|
-
end
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
begin
|
|
171
|
-
require "the_local"
|
|
172
|
-
MyGem::Companion.register!
|
|
173
|
-
rescue LoadError
|
|
174
|
-
# the_local not installed — my_gem works standalone.
|
|
175
|
-
end
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
Then write `reference/guide.md` to the canonical shape, `rake the_local:build`,
|
|
179
|
-
and commit `lib/my_gem/the_local/agents/*.md`.
|
|
180
|
-
|
|
181
|
-
### Conventions
|
|
182
|
-
|
|
183
|
-
- The register block lives behind `begin require "the_local" … rescue LoadError`
|
|
184
|
-
so the gem still works when the_local is absent.
|
|
185
|
-
- `guide.md` documents the providing gem only and stays the single source of
|
|
186
|
-
truth; never let a rendered `.md` drift from `agent.to_markdown`.
|
|
187
|
-
- Commit the rendered `.md`; never render in the host at install time.
|