the_local 0.1.0 → 0.2.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 +19 -0
- data/PROVIDERS.md +10 -6
- data/lib/generators/the_local/provider_generator.rb +1 -1
- data/lib/generators/the_local/templates/guide.md.tt +20 -4
- data/lib/generators/the_local/templates/the_local.rb.tt +9 -6
- data/lib/the_local/builder.rb +28 -1
- data/lib/the_local/rake.rb +1 -1
- data/lib/the_local/reference/guide.md +89 -13
- data/lib/the_local/the_local/agents/the_local-develop.md +89 -13
- data/lib/the_local/the_local/agents/the_local-info.md +89 -13
- data/lib/the_local/the_local/agents/the_local-install.md +89 -13
- data/lib/the_local/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 46515a04fbebe5b7f0b5bbd09fb5ac194b013e7cb08a10445849b0a3954b593a
|
|
4
|
+
data.tar.gz: 1840cb121e1d6c8cd0e458d945396d29c620db62f391c15836e1130a686fa682
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ff8308ecbcc6adab431e1148f0a87a082de8e0a7441b390f4766886facda382fa0416f01a0b248340d8fb4eff4dd55aa2b794b82e249d49d52ea3b137f91dd98
|
|
7
|
+
data.tar.gz: a1e570c7f1a4341e61dfbf35805762bf6d7a1bdb1ad0175bce502603e3e35404b901ec3ef320acefa1a0765ba8aa20e917e36ddee93d880cd0f9bcfc1cbd06b7
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [0.2.0] - 2026-06-20
|
|
4
|
+
|
|
5
|
+
- `rake the_local:build` now refuses a guide that still holds line-leading
|
|
6
|
+
`TODO:` placeholders or is missing a canonical section, so a provider can't
|
|
7
|
+
ship a local that hasn't surfaced its gem's real interface (and would send
|
|
8
|
+
host agents digging into source).
|
|
9
|
+
- Guides follow one canonical shape across every provider — **Interface**
|
|
10
|
+
(exact signatures), **Recipe** (copy-paste common task), **Install**,
|
|
11
|
+
**Conventions** — enforced at build and enumerated in the develop local's
|
|
12
|
+
authoring spec, so the consuming agent meets the same structure everywhere.
|
|
13
|
+
the_local's own guide models it with the `register` / `c.agent` signatures.
|
|
14
|
+
- Scaffolded facet bodies (`info` / `install` / worker) are now a standard role
|
|
15
|
+
that defers to the guide and forbids reading source, identical across gems —
|
|
16
|
+
so the consuming agent gets consistent behavior, with gem-specifics in the
|
|
17
|
+
guide rather than hand-written per-provider bodies.
|
|
18
|
+
- Install instructions and the provider generator now use the published
|
|
19
|
+
`gem "the_local"` instead of a `github:` git source, since the gem is on
|
|
20
|
+
RubyGems.
|
|
21
|
+
|
|
3
22
|
## [0.1.0] - 2026-06-02
|
|
4
23
|
|
|
5
24
|
- Initial release.
|
data/PROVIDERS.md
CHANGED
|
@@ -74,10 +74,14 @@ them after filling in the real content (below).
|
|
|
74
74
|
|
|
75
75
|
Then **fill in the scaffold** — this is the real work the generator can't do:
|
|
76
76
|
|
|
77
|
-
1. Write `reference/guide.md` as the complete user-facing API.
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
77
|
+
1. Write `reference/guide.md` as the complete user-facing API. The bar is that
|
|
78
|
+
a host agent can do your gem's work *from the guide alone, without opening
|
|
79
|
+
your source*: surface the literal interface (exact signatures — arguments,
|
|
80
|
+
required vs optional, return) and a complete copy-paste recipe for the common
|
|
81
|
+
task, not prose about them. Its **Install** section must be the exact, correct
|
|
82
|
+
steps for *this* gem (for an engine: add the gem → `bundle install` → install
|
|
83
|
+
+ run migrations → wire concerns / initializers), not a generic placeholder.
|
|
84
|
+
Replace every `TODO:` — `rake the_local:build` refuses a guide that keeps one.
|
|
81
85
|
2. Tailor the three agent `body:` strings in `the_local.rb` to the gem.
|
|
82
86
|
3. **Rebuild and commit the locals.** The scaffold built `.md` from the TODO
|
|
83
87
|
placeholders, so regenerate them from your real definition and commit them:
|
|
@@ -126,8 +130,8 @@ itself a non-Rails provider built this way — mirror its own wiring
|
|
|
126
130
|
```
|
|
127
131
|
4. `require_relative "<gem>/the_local"` from the gem's entrypoint (so your own
|
|
128
132
|
`the_local:build` and standalone use load the register block — a host never
|
|
129
|
-
needs it), and add `gem "the_local"
|
|
130
|
-
|
|
133
|
+
needs it), and add `gem "the_local"` to the Gemfile (dev/test — an optional
|
|
134
|
+
companion, not a hard dependency).
|
|
131
135
|
5. Add `require "the_local/rake"` to the `Rakefile`, then build, commit, and
|
|
132
136
|
**ship** the rendered locals — `rake the_local:build && git add
|
|
133
137
|
lib/<gem>/the_local/agents`, and make sure they're in the gemspec's `files`.
|
|
@@ -15,7 +15,7 @@ module TheLocal
|
|
|
15
15
|
class ProviderGenerator < Rails::Generators::Base
|
|
16
16
|
source_root File.expand_path("templates", __dir__)
|
|
17
17
|
|
|
18
|
-
GEMFILE_LINE = %(gem "the_local"
|
|
18
|
+
GEMFILE_LINE = %(gem "the_local")
|
|
19
19
|
RAKEFILE_REQUIRE = %(require "the_local/rake")
|
|
20
20
|
|
|
21
21
|
desc "Scaffold the_local provider wiring (info/install/worker locals) into this gem"
|
|
@@ -3,13 +3,29 @@
|
|
|
3
3
|
> **DO NOT** explore the <%= gem_name %> gem source code. This reference is the
|
|
4
4
|
> complete user-facing API, embedded verbatim into every <%= gem_name %> local so
|
|
5
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.
|
|
6
13
|
|
|
7
14
|
TODO: One paragraph — what <%= gem_name %> is and the problem it solves.
|
|
8
15
|
|
|
9
|
-
###
|
|
16
|
+
### Interface
|
|
10
17
|
|
|
11
|
-
TODO: The public API —
|
|
12
|
-
|
|
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.
|
|
13
29
|
|
|
14
30
|
### Install
|
|
15
31
|
|
|
@@ -19,7 +35,7 @@ actually installed (e.g. for a Rails engine: add the gem, `bundle install`,
|
|
|
19
35
|
install + run migrations, wire any concerns/initializers). Don't leave it
|
|
20
36
|
generic.
|
|
21
37
|
|
|
22
|
-
###
|
|
38
|
+
### Conventions
|
|
23
39
|
|
|
24
40
|
TODO: The conventions the `<%= worker %>` local must enforce when doing
|
|
25
41
|
<%= gem_name %> work, so usage stays consistent across the host.
|
|
@@ -15,23 +15,26 @@ require_relative "reference"
|
|
|
15
15
|
c.agent "info",
|
|
16
16
|
description: "Use to learn what <%= gem_name %> offers — its API and conventions.",
|
|
17
17
|
tools: "Read",
|
|
18
|
-
body: "You explain what <%= gem_name %> does and how to use it, answering from
|
|
19
|
-
"reference. You make no changes
|
|
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.",
|
|
20
21
|
knowledge: <%= module_name %>::Reference.content
|
|
21
22
|
|
|
22
23
|
c.agent "install",
|
|
23
24
|
description: "Use to add <%= gem_name %> to a project and set it up correctly.",
|
|
24
25
|
tools: "Bash, Read, Edit",
|
|
25
|
-
body: "You add <%= gem_name %> to the project and complete its setup
|
|
26
|
-
"reference's
|
|
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.",
|
|
27
29
|
knowledge: <%= module_name %>::Reference.content
|
|
28
30
|
|
|
29
31
|
c.agent "<%= worker %>",
|
|
30
32
|
description: "Use PROACTIVELY for any <%= gem_name %> work. MUST BE USED instead of " \
|
|
31
33
|
"hand-rolling it. TODO: name the concrete tasks this local owns.",
|
|
32
34
|
tools: "Read, Write, Edit, Grep",
|
|
33
|
-
body: "You do <%= gem_name %> work following the
|
|
34
|
-
"
|
|
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.",
|
|
35
38
|
knowledge: <%= module_name %>::Reference.content
|
|
36
39
|
end
|
|
37
40
|
end
|
data/lib/the_local/builder.rb
CHANGED
|
@@ -9,11 +9,22 @@ module TheLocal
|
|
|
9
9
|
# the_local:build rake task a provider runs. Agents that declared no agents_dir
|
|
10
10
|
# (and so have no source_path) are skipped: there is nowhere to write them.
|
|
11
11
|
class Builder
|
|
12
|
-
|
|
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)
|
|
13
21
|
@registry = registry
|
|
22
|
+
@validate = validate
|
|
14
23
|
end
|
|
15
24
|
|
|
16
25
|
def call
|
|
26
|
+
validate! if @validate
|
|
27
|
+
|
|
17
28
|
buildable_agents.map do |agent|
|
|
18
29
|
FileUtils.mkdir_p(File.dirname(agent.source_path))
|
|
19
30
|
File.write(agent.source_path, agent.to_markdown)
|
|
@@ -23,6 +34,22 @@ module TheLocal
|
|
|
23
34
|
|
|
24
35
|
private
|
|
25
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
|
+
|
|
26
53
|
def buildable_agents
|
|
27
54
|
@registry.agents.select(&:source_path)
|
|
28
55
|
end
|
data/lib/the_local/rake.rb
CHANGED
|
@@ -11,7 +11,7 @@ require "the_local/builder"
|
|
|
11
11
|
namespace :the_local do
|
|
12
12
|
desc "Render this provider's committed agent files from its registered definitions"
|
|
13
13
|
task :build do
|
|
14
|
-
written = TheLocal::Builder.new(registry: TheLocal.registry).call
|
|
14
|
+
written = TheLocal::Builder.new(registry: TheLocal.registry, validate: true).call
|
|
15
15
|
puts "the_local: built #{written.length} agent file(s)"
|
|
16
16
|
end
|
|
17
17
|
|
|
@@ -37,9 +37,7 @@ the aggregated set from every directly-depended provider into a consuming app's
|
|
|
37
37
|
|
|
38
38
|
### Install (in any gem or app)
|
|
39
39
|
|
|
40
|
-
1. Add
|
|
41
|
-
source: `gem "the_local", github: "DYB-Development/the_local"`), then
|
|
42
|
-
`bundle install`.
|
|
40
|
+
1. Add `gem "the_local"` to the host's `Gemfile`, then `bundle install`.
|
|
43
41
|
2. Run `bundle exec the_local install`. This syncs every direct provider's
|
|
44
42
|
committed locals into `.claude/agents/` and writes the delegation trigger
|
|
45
43
|
into `CLAUDE.md`/`AGENTS.md`. It needs no Rails — a plain gem installs the
|
|
@@ -60,10 +58,18 @@ its Rakefile also gets `rake the_local:install`. All three share one engine.
|
|
|
60
58
|
registers the standard interface; hooks `the_local:build` into the `Rakefile`;
|
|
61
59
|
requires the companion from the gem entrypoint; and builds the committed
|
|
62
60
|
`.md` for review.
|
|
63
|
-
2. Write `guide.md`
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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.
|
|
67
73
|
3. Tailor the register block bodies and `scope` to your gem; the standard
|
|
68
74
|
interface is `info` (read-only explainer), `install` (sets the gem up in a
|
|
69
75
|
host), and a domain worker (`develop` for libraries, `operate` for CLIs).
|
|
@@ -75,7 +81,26 @@ its Rakefile also gets `rake the_local:install`. All three share one engine.
|
|
|
75
81
|
nothing, and if they are, you contribute everything. A drift test asserting
|
|
76
82
|
each committed file equals its `agent.to_markdown` keeps the artifact honest.
|
|
77
83
|
|
|
78
|
-
###
|
|
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
|
+
```
|
|
79
104
|
|
|
80
105
|
```ruby
|
|
81
106
|
TheLocal.register("my_gem", prefix: "my_gem", scope: "one-line domain phrase",
|
|
@@ -88,11 +113,62 @@ TheLocal.register("my_gem", prefix: "my_gem", scope: "one-line domain phrase",
|
|
|
88
113
|
end
|
|
89
114
|
```
|
|
90
115
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
- `
|
|
94
|
-
|
|
95
|
-
|
|
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`.
|
|
96
172
|
|
|
97
173
|
### Conventions
|
|
98
174
|
|
|
@@ -45,9 +45,7 @@ the aggregated set from every directly-depended provider into a consuming app's
|
|
|
45
45
|
|
|
46
46
|
### Install (in any gem or app)
|
|
47
47
|
|
|
48
|
-
1. Add
|
|
49
|
-
source: `gem "the_local", github: "DYB-Development/the_local"`), then
|
|
50
|
-
`bundle install`.
|
|
48
|
+
1. Add `gem "the_local"` to the host's `Gemfile`, then `bundle install`.
|
|
51
49
|
2. Run `bundle exec the_local install`. This syncs every direct provider's
|
|
52
50
|
committed locals into `.claude/agents/` and writes the delegation trigger
|
|
53
51
|
into `CLAUDE.md`/`AGENTS.md`. It needs no Rails — a plain gem installs the
|
|
@@ -68,10 +66,18 @@ its Rakefile also gets `rake the_local:install`. All three share one engine.
|
|
|
68
66
|
registers the standard interface; hooks `the_local:build` into the `Rakefile`;
|
|
69
67
|
requires the companion from the gem entrypoint; and builds the committed
|
|
70
68
|
`.md` for review.
|
|
71
|
-
2. Write `guide.md`
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
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.
|
|
75
81
|
3. Tailor the register block bodies and `scope` to your gem; the standard
|
|
76
82
|
interface is `info` (read-only explainer), `install` (sets the gem up in a
|
|
77
83
|
host), and a domain worker (`develop` for libraries, `operate` for CLIs).
|
|
@@ -83,7 +89,26 @@ its Rakefile also gets `rake the_local:install`. All three share one engine.
|
|
|
83
89
|
nothing, and if they are, you contribute everything. A drift test asserting
|
|
84
90
|
each committed file equals its `agent.to_markdown` keeps the artifact honest.
|
|
85
91
|
|
|
86
|
-
###
|
|
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
|
+
```
|
|
87
112
|
|
|
88
113
|
```ruby
|
|
89
114
|
TheLocal.register("my_gem", prefix: "my_gem", scope: "one-line domain phrase",
|
|
@@ -96,11 +121,62 @@ TheLocal.register("my_gem", prefix: "my_gem", scope: "one-line domain phrase",
|
|
|
96
121
|
end
|
|
97
122
|
```
|
|
98
123
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
- `
|
|
102
|
-
|
|
103
|
-
|
|
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`.
|
|
104
180
|
|
|
105
181
|
### Conventions
|
|
106
182
|
|
|
@@ -45,9 +45,7 @@ the aggregated set from every directly-depended provider into a consuming app's
|
|
|
45
45
|
|
|
46
46
|
### Install (in any gem or app)
|
|
47
47
|
|
|
48
|
-
1. Add
|
|
49
|
-
source: `gem "the_local", github: "DYB-Development/the_local"`), then
|
|
50
|
-
`bundle install`.
|
|
48
|
+
1. Add `gem "the_local"` to the host's `Gemfile`, then `bundle install`.
|
|
51
49
|
2. Run `bundle exec the_local install`. This syncs every direct provider's
|
|
52
50
|
committed locals into `.claude/agents/` and writes the delegation trigger
|
|
53
51
|
into `CLAUDE.md`/`AGENTS.md`. It needs no Rails — a plain gem installs the
|
|
@@ -68,10 +66,18 @@ its Rakefile also gets `rake the_local:install`. All three share one engine.
|
|
|
68
66
|
registers the standard interface; hooks `the_local:build` into the `Rakefile`;
|
|
69
67
|
requires the companion from the gem entrypoint; and builds the committed
|
|
70
68
|
`.md` for review.
|
|
71
|
-
2. Write `guide.md`
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
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.
|
|
75
81
|
3. Tailor the register block bodies and `scope` to your gem; the standard
|
|
76
82
|
interface is `info` (read-only explainer), `install` (sets the gem up in a
|
|
77
83
|
host), and a domain worker (`develop` for libraries, `operate` for CLIs).
|
|
@@ -83,7 +89,26 @@ its Rakefile also gets `rake the_local:install`. All three share one engine.
|
|
|
83
89
|
nothing, and if they are, you contribute everything. A drift test asserting
|
|
84
90
|
each committed file equals its `agent.to_markdown` keeps the artifact honest.
|
|
85
91
|
|
|
86
|
-
###
|
|
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
|
+
```
|
|
87
112
|
|
|
88
113
|
```ruby
|
|
89
114
|
TheLocal.register("my_gem", prefix: "my_gem", scope: "one-line domain phrase",
|
|
@@ -96,11 +121,62 @@ TheLocal.register("my_gem", prefix: "my_gem", scope: "one-line domain phrase",
|
|
|
96
121
|
end
|
|
97
122
|
```
|
|
98
123
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
- `
|
|
102
|
-
|
|
103
|
-
|
|
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`.
|
|
104
180
|
|
|
105
181
|
### Conventions
|
|
106
182
|
|
|
@@ -45,9 +45,7 @@ the aggregated set from every directly-depended provider into a consuming app's
|
|
|
45
45
|
|
|
46
46
|
### Install (in any gem or app)
|
|
47
47
|
|
|
48
|
-
1. Add
|
|
49
|
-
source: `gem "the_local", github: "DYB-Development/the_local"`), then
|
|
50
|
-
`bundle install`.
|
|
48
|
+
1. Add `gem "the_local"` to the host's `Gemfile`, then `bundle install`.
|
|
51
49
|
2. Run `bundle exec the_local install`. This syncs every direct provider's
|
|
52
50
|
committed locals into `.claude/agents/` and writes the delegation trigger
|
|
53
51
|
into `CLAUDE.md`/`AGENTS.md`. It needs no Rails — a plain gem installs the
|
|
@@ -68,10 +66,18 @@ its Rakefile also gets `rake the_local:install`. All three share one engine.
|
|
|
68
66
|
registers the standard interface; hooks `the_local:build` into the `Rakefile`;
|
|
69
67
|
requires the companion from the gem entrypoint; and builds the committed
|
|
70
68
|
`.md` for review.
|
|
71
|
-
2. Write `guide.md`
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
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.
|
|
75
81
|
3. Tailor the register block bodies and `scope` to your gem; the standard
|
|
76
82
|
interface is `info` (read-only explainer), `install` (sets the gem up in a
|
|
77
83
|
host), and a domain worker (`develop` for libraries, `operate` for CLIs).
|
|
@@ -83,7 +89,26 @@ its Rakefile also gets `rake the_local:install`. All three share one engine.
|
|
|
83
89
|
nothing, and if they are, you contribute everything. A drift test asserting
|
|
84
90
|
each committed file equals its `agent.to_markdown` keeps the artifact honest.
|
|
85
91
|
|
|
86
|
-
###
|
|
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
|
+
```
|
|
87
112
|
|
|
88
113
|
```ruby
|
|
89
114
|
TheLocal.register("my_gem", prefix: "my_gem", scope: "one-line domain phrase",
|
|
@@ -96,11 +121,62 @@ TheLocal.register("my_gem", prefix: "my_gem", scope: "one-line domain phrase",
|
|
|
96
121
|
end
|
|
97
122
|
```
|
|
98
123
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
- `
|
|
102
|
-
|
|
103
|
-
|
|
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`.
|
|
104
180
|
|
|
105
181
|
### Conventions
|
|
106
182
|
|
data/lib/the_local/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: the_local
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- tylercschneider
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-06-
|
|
11
|
+
date: 2026-06-22 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: the_local lets any gem or app declare Claude Code subagents ("locals")
|
|
14
14
|
that know its conventions, and installs the aggregated set from every installed
|