the_local 0.1.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 +7 -0
- data/CHANGELOG.md +15 -0
- data/LICENSE.txt +21 -0
- data/PROVIDERS.md +135 -0
- data/README.md +72 -0
- data/Rakefile +15 -0
- data/exe/the_local +6 -0
- data/lib/generators/the_local/install_generator.rb +21 -0
- data/lib/generators/the_local/provider_generator.rb +144 -0
- data/lib/generators/the_local/templates/guide.md.tt +25 -0
- data/lib/generators/the_local/templates/reference.rb.tt +17 -0
- data/lib/generators/the_local/templates/the_local.rb.tt +46 -0
- data/lib/the_local/agent.rb +41 -0
- data/lib/the_local/builder.rb +30 -0
- data/lib/the_local/cli.rb +34 -0
- data/lib/the_local/disk_providers.rb +32 -0
- data/lib/the_local/installer.rb +41 -0
- data/lib/the_local/process_doc_writer.rb +48 -0
- data/lib/the_local/process_rules/develop_process_rules.md +97 -0
- data/lib/the_local/process_rules.rb +17 -0
- data/lib/the_local/railtie.rb +15 -0
- data/lib/the_local/rake.rb +23 -0
- data/lib/the_local/reference/guide.md +103 -0
- data/lib/the_local/reference.rb +16 -0
- data/lib/the_local/refresh.rb +28 -0
- data/lib/the_local/registry.rb +59 -0
- data/lib/the_local/scope.rb +15 -0
- data/lib/the_local/sync.rb +28 -0
- data/lib/the_local/tasks/the_local.rake +9 -0
- data/lib/the_local/the_local/agents/the_local-develop.md +111 -0
- data/lib/the_local/the_local/agents/the_local-info.md +111 -0
- data/lib/the_local/the_local/agents/the_local-install.md +111 -0
- data/lib/the_local/the_local.rb +59 -0
- data/lib/the_local/trigger_writer.rb +64 -0
- data/lib/the_local/version.rb +5 -0
- data/lib/the_local.rb +51 -0
- data/sig/the_local.rbs +4 -0
- metadata +95 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: the_local-info
|
|
3
|
+
description: Use to learn how the_local works — providers, the build/install model, the delegation trigger, and the direct-dependency scope rule.
|
|
4
|
+
tools: Read
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
You explain how the_local works, answering only from the reference: providers register locals, the_local:build renders committed .md, install/refresh copy them verbatim into a host, the CLAUDE.md delegation trigger makes the host delegate, and only direct dependencies contribute. You make no changes.
|
|
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 the gem to the host's `Gemfile` (until it is on RubyGems, use a git
|
|
49
|
+
source: `gem "the_local", github: "DYB-Development/the_local"`), then
|
|
50
|
+
`bundle install`.
|
|
51
|
+
2. Run `bundle exec the_local install`. This syncs every direct provider's
|
|
52
|
+
committed locals into `.claude/agents/` and writes the delegation trigger
|
|
53
|
+
into `CLAUDE.md`/`AGENTS.md`. It needs no Rails — a plain gem installs the
|
|
54
|
+
same way an app does.
|
|
55
|
+
3. Re-run `bundle exec the_local install` after any bundle change (a provider
|
|
56
|
+
added, removed, or upgraded) to bring the host's locals back in sync. The
|
|
57
|
+
shell can automate this; the gem only exposes the command.
|
|
58
|
+
|
|
59
|
+
Rails apps can equivalently run `bin/rails g the_local:install` and
|
|
60
|
+
`the_local:refresh`; a gem that already wires `require "the_local/rake"` into
|
|
61
|
+
its Rakefile also gets `rake the_local:install`. All three share one engine.
|
|
62
|
+
|
|
63
|
+
### Author a provider (turn a gem into a provider)
|
|
64
|
+
|
|
65
|
+
1. Run `bin/rails g the_local:provider <gem_name>` (pass `--scope`,
|
|
66
|
+
`--prefix`, `--worker` as needed). It scaffolds `lib/<gem>/reference.rb`, a
|
|
67
|
+
`lib/<gem>/reference/guide.md`, and a `lib/<gem>/the_local.rb` companion that
|
|
68
|
+
registers the standard interface; hooks `the_local:build` into the `Rakefile`;
|
|
69
|
+
requires the companion from the gem entrypoint; and builds the committed
|
|
70
|
+
`.md` for review.
|
|
71
|
+
2. Write `guide.md` in this format — it is the single source of truth and is
|
|
72
|
+
embedded verbatim into every local. Document *your own* gem only: what it
|
|
73
|
+
does, how to install it, the conventions to enforce. Name companion gems but
|
|
74
|
+
do not explain their internals.
|
|
75
|
+
3. Tailor the register block bodies and `scope` to your gem; the standard
|
|
76
|
+
interface is `info` (read-only explainer), `install` (sets the gem up in a
|
|
77
|
+
host), and a domain worker (`develop` for libraries, `operate` for CLIs).
|
|
78
|
+
4. Run `rake the_local:build`, then **commit and ship**
|
|
79
|
+
`lib/<gem>/the_local/agents/*.md` (they must be in the gemspec's `files`).
|
|
80
|
+
This is the whole contract: a host discovers your locals by reading these
|
|
81
|
+
committed files from your gem on disk — it never loads your gem or runs your
|
|
82
|
+
register block — so if they aren't committed and shipped, you contribute
|
|
83
|
+
nothing, and if they are, you contribute everything. A drift test asserting
|
|
84
|
+
each committed file equals its `agent.to_markdown` keeps the artifact honest.
|
|
85
|
+
|
|
86
|
+
### TheLocal.register
|
|
87
|
+
|
|
88
|
+
```ruby
|
|
89
|
+
TheLocal.register("my_gem", prefix: "my_gem", scope: "one-line domain phrase",
|
|
90
|
+
agents_dir: File.expand_path("the_local/agents", __dir__)) do |c|
|
|
91
|
+
c.agent "info",
|
|
92
|
+
description: "Use to learn what my_gem offers.",
|
|
93
|
+
tools: "Read",
|
|
94
|
+
body: "You explain my_gem, answering only from the reference. You make no changes.",
|
|
95
|
+
knowledge: MyGem::Reference.content
|
|
96
|
+
end
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
- `gem_name` (first arg) filters to a host's direct dependencies.
|
|
100
|
+
- `prefix` is the agent filename namespace; defaults to the gem name.
|
|
101
|
+
- `scope` is a one-line domain phrase used to generate the delegation trigger.
|
|
102
|
+
- `agents_dir` is the absolute path to the committed `.md` files; each agent
|
|
103
|
+
records its `source_path` there so the installer can copy it verbatim.
|
|
104
|
+
|
|
105
|
+
### Conventions
|
|
106
|
+
|
|
107
|
+
- The register block lives behind `begin require "the_local" … rescue LoadError`
|
|
108
|
+
so the gem still works when the_local is absent.
|
|
109
|
+
- `guide.md` documents the providing gem only and stays the single source of
|
|
110
|
+
truth; never let a rendered `.md` drift from `agent.to_markdown`.
|
|
111
|
+
- Commit the rendered `.md`; never render in the host at install time.
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: the_local-install
|
|
3
|
+
description: Use to add the_local to a host app and set it up correctly.
|
|
4
|
+
tools: Bash, Read, Edit
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
You set the_local up in a host gem or app, following the reference's install section exactly: add the gem (git source until it is on RubyGems), bundle, run `bundle exec the_local install` to sync locals into .claude/agents/ and write the delegation trigger, and re-run it after bundle changes. You do not invent steps the reference does not list.
|
|
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 the gem to the host's `Gemfile` (until it is on RubyGems, use a git
|
|
49
|
+
source: `gem "the_local", github: "DYB-Development/the_local"`), then
|
|
50
|
+
`bundle install`.
|
|
51
|
+
2. Run `bundle exec the_local install`. This syncs every direct provider's
|
|
52
|
+
committed locals into `.claude/agents/` and writes the delegation trigger
|
|
53
|
+
into `CLAUDE.md`/`AGENTS.md`. It needs no Rails — a plain gem installs the
|
|
54
|
+
same way an app does.
|
|
55
|
+
3. Re-run `bundle exec the_local install` after any bundle change (a provider
|
|
56
|
+
added, removed, or upgraded) to bring the host's locals back in sync. The
|
|
57
|
+
shell can automate this; the gem only exposes the command.
|
|
58
|
+
|
|
59
|
+
Rails apps can equivalently run `bin/rails g the_local:install` and
|
|
60
|
+
`the_local:refresh`; a gem that already wires `require "the_local/rake"` into
|
|
61
|
+
its Rakefile also gets `rake the_local:install`. All three share one engine.
|
|
62
|
+
|
|
63
|
+
### Author a provider (turn a gem into a provider)
|
|
64
|
+
|
|
65
|
+
1. Run `bin/rails g the_local:provider <gem_name>` (pass `--scope`,
|
|
66
|
+
`--prefix`, `--worker` as needed). It scaffolds `lib/<gem>/reference.rb`, a
|
|
67
|
+
`lib/<gem>/reference/guide.md`, and a `lib/<gem>/the_local.rb` companion that
|
|
68
|
+
registers the standard interface; hooks `the_local:build` into the `Rakefile`;
|
|
69
|
+
requires the companion from the gem entrypoint; and builds the committed
|
|
70
|
+
`.md` for review.
|
|
71
|
+
2. Write `guide.md` in this format — it is the single source of truth and is
|
|
72
|
+
embedded verbatim into every local. Document *your own* gem only: what it
|
|
73
|
+
does, how to install it, the conventions to enforce. Name companion gems but
|
|
74
|
+
do not explain their internals.
|
|
75
|
+
3. Tailor the register block bodies and `scope` to your gem; the standard
|
|
76
|
+
interface is `info` (read-only explainer), `install` (sets the gem up in a
|
|
77
|
+
host), and a domain worker (`develop` for libraries, `operate` for CLIs).
|
|
78
|
+
4. Run `rake the_local:build`, then **commit and ship**
|
|
79
|
+
`lib/<gem>/the_local/agents/*.md` (they must be in the gemspec's `files`).
|
|
80
|
+
This is the whole contract: a host discovers your locals by reading these
|
|
81
|
+
committed files from your gem on disk — it never loads your gem or runs your
|
|
82
|
+
register block — so if they aren't committed and shipped, you contribute
|
|
83
|
+
nothing, and if they are, you contribute everything. A drift test asserting
|
|
84
|
+
each committed file equals its `agent.to_markdown` keeps the artifact honest.
|
|
85
|
+
|
|
86
|
+
### TheLocal.register
|
|
87
|
+
|
|
88
|
+
```ruby
|
|
89
|
+
TheLocal.register("my_gem", prefix: "my_gem", scope: "one-line domain phrase",
|
|
90
|
+
agents_dir: File.expand_path("the_local/agents", __dir__)) do |c|
|
|
91
|
+
c.agent "info",
|
|
92
|
+
description: "Use to learn what my_gem offers.",
|
|
93
|
+
tools: "Read",
|
|
94
|
+
body: "You explain my_gem, answering only from the reference. You make no changes.",
|
|
95
|
+
knowledge: MyGem::Reference.content
|
|
96
|
+
end
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
- `gem_name` (first arg) filters to a host's direct dependencies.
|
|
100
|
+
- `prefix` is the agent filename namespace; defaults to the gem name.
|
|
101
|
+
- `scope` is a one-line domain phrase used to generate the delegation trigger.
|
|
102
|
+
- `agents_dir` is the absolute path to the committed `.md` files; each agent
|
|
103
|
+
records its `source_path` there so the installer can copy it verbatim.
|
|
104
|
+
|
|
105
|
+
### Conventions
|
|
106
|
+
|
|
107
|
+
- The register block lives behind `begin require "the_local" … rescue LoadError`
|
|
108
|
+
so the gem still works when the_local is absent.
|
|
109
|
+
- `guide.md` documents the providing gem only and stays the single source of
|
|
110
|
+
truth; never let a rendered `.md` drift from `agent.to_markdown`.
|
|
111
|
+
- Commit the rendered `.md`; never render in the host at install time.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "reference"
|
|
4
|
+
|
|
5
|
+
module TheLocal
|
|
6
|
+
# Registers the_local's own locals (info / install / develop) with the_local,
|
|
7
|
+
# so the engine dogfoods the same provider model every other gem uses.
|
|
8
|
+
module Companion
|
|
9
|
+
SCOPE = "Claude Code locals: gems register subagents, the_local builds " \
|
|
10
|
+
"committed .md and installs them into a host app"
|
|
11
|
+
|
|
12
|
+
# rubocop:disable Metrics/MethodLength, Metrics/BlockLength
|
|
13
|
+
def self.register!
|
|
14
|
+
TheLocal.register(
|
|
15
|
+
"the_local",
|
|
16
|
+
scope: SCOPE,
|
|
17
|
+
agents_dir: File.expand_path("the_local/agents", __dir__)
|
|
18
|
+
) do |c|
|
|
19
|
+
c.agent "info",
|
|
20
|
+
description: "Use to learn how the_local works — providers, the build/install " \
|
|
21
|
+
"model, the delegation trigger, and the direct-dependency scope rule.",
|
|
22
|
+
tools: "Read",
|
|
23
|
+
body: "You explain how the_local works, answering only from the reference: providers " \
|
|
24
|
+
"register locals, the_local:build renders committed .md, install/refresh copy " \
|
|
25
|
+
"them verbatim into a host, the CLAUDE.md delegation trigger makes the host " \
|
|
26
|
+
"delegate, and only direct dependencies contribute. You make no changes.",
|
|
27
|
+
knowledge: TheLocal::Reference.content
|
|
28
|
+
|
|
29
|
+
c.agent "install",
|
|
30
|
+
description: "Use to add the_local to a host app and set it up correctly.",
|
|
31
|
+
tools: "Bash, Read, Edit",
|
|
32
|
+
body: "You set the_local up in a host gem or app, following the reference's install " \
|
|
33
|
+
"section exactly: add the gem (git source until it is on RubyGems), bundle, run " \
|
|
34
|
+
"`bundle exec the_local install` to sync locals into .claude/agents/ and write " \
|
|
35
|
+
"the delegation trigger, and re-run it after bundle changes. You do not invent " \
|
|
36
|
+
"steps the reference does not list.",
|
|
37
|
+
knowledge: TheLocal::Reference.content
|
|
38
|
+
|
|
39
|
+
c.agent "develop",
|
|
40
|
+
description: "Use PROACTIVELY to turn a gem into a the_local provider — scaffolding " \
|
|
41
|
+
"the companion, authoring the guide, and committing the rendered locals. " \
|
|
42
|
+
"MUST BE USED instead of wiring a provider by hand.",
|
|
43
|
+
tools: "Read, Write, Edit, Grep",
|
|
44
|
+
body: "You turn a gem into a the_local provider following the reference's " \
|
|
45
|
+
"provider-author workflow: run `the_local:provider`, write guide.md as the " \
|
|
46
|
+
"single source of truth (your own gem only), tailor the register block, and " \
|
|
47
|
+
"hook the_local:build into the Rakefile. The deliverable is the committed, " \
|
|
48
|
+
"shipped lib/<gem>/the_local/agents/*.md — that is the whole contract a host " \
|
|
49
|
+
"reads from disk; a host never loads the gem, so unless those files are built, " \
|
|
50
|
+
"committed, and in the gemspec, the gem contributes nothing. You keep them in " \
|
|
51
|
+
"sync with agent.to_markdown.",
|
|
52
|
+
knowledge: TheLocal::Reference.content
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
# rubocop:enable Metrics/MethodLength, Metrics/BlockLength
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
TheLocal::Companion.register!
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module TheLocal
|
|
4
|
+
# Writes the mandatory delegation trigger — the standing rule, read at the
|
|
5
|
+
# start of every session, that tells the host agent to delegate to its locals
|
|
6
|
+
# rather than work from memory. Generated from the registry's providers,
|
|
7
|
+
# filtered to the host's allowed gems. Plain Ruby; the Rails generator wraps it.
|
|
8
|
+
class TriggerWriter
|
|
9
|
+
BEGIN_MARKER = "<!-- the_local:begin -->"
|
|
10
|
+
END_MARKER = "<!-- the_local:end -->"
|
|
11
|
+
|
|
12
|
+
def initialize(registry:, destination:, allowed_gems:, filename: "CLAUDE.md")
|
|
13
|
+
@registry = registry
|
|
14
|
+
@destination = destination
|
|
15
|
+
@allowed_gems = allowed_gems
|
|
16
|
+
@filename = filename
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def call
|
|
20
|
+
path = File.join(@destination, @filename)
|
|
21
|
+
existing = File.exist?(path) ? File.read(path) : ""
|
|
22
|
+
File.write(path, "#{merge(existing)}\n")
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def rule
|
|
26
|
+
<<~MARKDOWN.chomp
|
|
27
|
+
#{BEGIN_MARKER}
|
|
28
|
+
## Delegate to your locals
|
|
29
|
+
|
|
30
|
+
This project has installed expert subagents. Before doing work yourself,
|
|
31
|
+
check whether a local owns it and delegate — never work from memory on
|
|
32
|
+
something a local covers:
|
|
33
|
+
|
|
34
|
+
#{bullets.join("\n")}
|
|
35
|
+
|
|
36
|
+
See each agent's description for specifics.
|
|
37
|
+
#{END_MARKER}
|
|
38
|
+
MARKDOWN
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
# Replaces an existing marked section in place, or appends one, so re-running
|
|
44
|
+
# re-syncs the rule without duplicating or clobbering the host's own content.
|
|
45
|
+
def merge(existing)
|
|
46
|
+
section = /#{Regexp.escape(BEGIN_MARKER)}.*?#{Regexp.escape(END_MARKER)}/m
|
|
47
|
+
return existing.sub(section, rule) if existing.match?(section)
|
|
48
|
+
return rule if existing.strip.empty?
|
|
49
|
+
|
|
50
|
+
"#{existing.chomp}\n\n#{rule}"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def bullets
|
|
54
|
+
allowed_providers.map do |provider|
|
|
55
|
+
target = "#{provider.prefix}-* agents"
|
|
56
|
+
"- #{[provider.scope, target].compact.join(" → ")}"
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def allowed_providers
|
|
61
|
+
@registry.providers.select { |provider| @allowed_gems.include?(provider.gem_name) }
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
data/lib/the_local.rb
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "the_local/version"
|
|
4
|
+
require_relative "the_local/agent"
|
|
5
|
+
require_relative "the_local/registry"
|
|
6
|
+
require_relative "the_local/installer"
|
|
7
|
+
require_relative "the_local/trigger_writer"
|
|
8
|
+
require_relative "the_local/process_doc_writer"
|
|
9
|
+
require_relative "the_local/scope"
|
|
10
|
+
require_relative "the_local/sync"
|
|
11
|
+
require_relative "the_local/refresh"
|
|
12
|
+
require_relative "the_local/disk_providers"
|
|
13
|
+
|
|
14
|
+
# Resident Claude Code expert subagents ("locals"), contributed by the gems and
|
|
15
|
+
# app that register with it and installed into a consuming app's .claude/agents/.
|
|
16
|
+
module TheLocal
|
|
17
|
+
class Error < StandardError; end
|
|
18
|
+
|
|
19
|
+
class << self
|
|
20
|
+
def registry
|
|
21
|
+
@registry ||= Registry.new
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Providers (gems or the app) call this at load time to contribute their
|
|
25
|
+
# agents. The first argument is the providing gem's name (used to filter to a
|
|
26
|
+
# host's direct dependencies); +prefix+ is the agent filename namespace and
|
|
27
|
+
# defaults to the gem name; +scope+ is a one-line phrase describing the
|
|
28
|
+
# provider's domain, used to generate the delegation trigger. +agents_dir+
|
|
29
|
+
# is the absolute path to the provider's committed, pre-rendered .md files
|
|
30
|
+
# (e.g. File.expand_path("the_local/agents", __dir__)); when given, each
|
|
31
|
+
# agent records its source_path there for the host installer to copy:
|
|
32
|
+
#
|
|
33
|
+
# TheLocal.register("keystone_ui", prefix: "keystone", scope: "UI work") do |c|
|
|
34
|
+
# c.agent "scaffold", description: "…", tools: "…", body: "…", knowledge: "…"
|
|
35
|
+
# end
|
|
36
|
+
def register(gem_name, prefix: gem_name, scope: nil, agents_dir: nil)
|
|
37
|
+
registry.add_provider(Provider.new(gem_name: gem_name, prefix: prefix, scope: scope))
|
|
38
|
+
yield Collector.new(gem_name, prefix, registry, agents_dir: agents_dir)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def reset!
|
|
42
|
+
registry.clear
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# In a Rails host, expose the the_local:refresh rake task. Skipped outside Rails
|
|
48
|
+
# so the gem core stays Rails-free.
|
|
49
|
+
require_relative "the_local/railtie" if defined?(Rails::Railtie)
|
|
50
|
+
|
|
51
|
+
require_relative "the_local/the_local"
|
data/sig/the_local.rbs
ADDED
metadata
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: the_local
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- tylercschneider
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-06-11 00:00:00.000000000 Z
|
|
12
|
+
dependencies: []
|
|
13
|
+
description: the_local lets any gem or app declare Claude Code subagents ("locals")
|
|
14
|
+
that know its conventions, and installs the aggregated set from every installed
|
|
15
|
+
provider into a consuming app's .claude/agents/ — plus a delegation rule so the
|
|
16
|
+
app's agent actually uses them.
|
|
17
|
+
email:
|
|
18
|
+
- tylercschneider@gmail.com
|
|
19
|
+
executables:
|
|
20
|
+
- the_local
|
|
21
|
+
extensions: []
|
|
22
|
+
extra_rdoc_files: []
|
|
23
|
+
files:
|
|
24
|
+
- CHANGELOG.md
|
|
25
|
+
- LICENSE.txt
|
|
26
|
+
- PROVIDERS.md
|
|
27
|
+
- README.md
|
|
28
|
+
- Rakefile
|
|
29
|
+
- exe/the_local
|
|
30
|
+
- lib/generators/the_local/install_generator.rb
|
|
31
|
+
- lib/generators/the_local/provider_generator.rb
|
|
32
|
+
- lib/generators/the_local/templates/guide.md.tt
|
|
33
|
+
- lib/generators/the_local/templates/reference.rb.tt
|
|
34
|
+
- lib/generators/the_local/templates/the_local.rb.tt
|
|
35
|
+
- lib/the_local.rb
|
|
36
|
+
- lib/the_local/agent.rb
|
|
37
|
+
- lib/the_local/builder.rb
|
|
38
|
+
- lib/the_local/cli.rb
|
|
39
|
+
- lib/the_local/disk_providers.rb
|
|
40
|
+
- lib/the_local/installer.rb
|
|
41
|
+
- lib/the_local/process_doc_writer.rb
|
|
42
|
+
- lib/the_local/process_rules.rb
|
|
43
|
+
- lib/the_local/process_rules/develop_process_rules.md
|
|
44
|
+
- lib/the_local/railtie.rb
|
|
45
|
+
- lib/the_local/rake.rb
|
|
46
|
+
- lib/the_local/reference.rb
|
|
47
|
+
- lib/the_local/reference/guide.md
|
|
48
|
+
- lib/the_local/refresh.rb
|
|
49
|
+
- lib/the_local/registry.rb
|
|
50
|
+
- lib/the_local/scope.rb
|
|
51
|
+
- lib/the_local/sync.rb
|
|
52
|
+
- lib/the_local/tasks/the_local.rake
|
|
53
|
+
- lib/the_local/the_local.rb
|
|
54
|
+
- lib/the_local/the_local/agents/the_local-develop.md
|
|
55
|
+
- lib/the_local/the_local/agents/the_local-info.md
|
|
56
|
+
- lib/the_local/the_local/agents/the_local-install.md
|
|
57
|
+
- lib/the_local/trigger_writer.rb
|
|
58
|
+
- lib/the_local/version.rb
|
|
59
|
+
- sig/the_local.rbs
|
|
60
|
+
homepage: https://github.com/DYB-Development/the_local
|
|
61
|
+
licenses:
|
|
62
|
+
- MIT
|
|
63
|
+
metadata:
|
|
64
|
+
allowed_push_host: https://rubygems.org
|
|
65
|
+
homepage_uri: https://github.com/DYB-Development/the_local
|
|
66
|
+
source_code_uri: https://github.com/DYB-Development/the_local/tree/main
|
|
67
|
+
bug_tracker_uri: https://github.com/DYB-Development/the_local/issues
|
|
68
|
+
changelog_uri: https://github.com/DYB-Development/the_local/blob/main/CHANGELOG.md
|
|
69
|
+
rubygems_mfa_required: 'true'
|
|
70
|
+
post_install_message: |
|
|
71
|
+
the_local is installed. To copy its Claude Code agents into this project, run:
|
|
72
|
+
|
|
73
|
+
bundle exec the_local install
|
|
74
|
+
|
|
75
|
+
That installs the locals contributed by your direct dependencies into
|
|
76
|
+
.claude/agents/ and writes the delegation trigger. Re-run it after bundle changes.
|
|
77
|
+
rdoc_options: []
|
|
78
|
+
require_paths:
|
|
79
|
+
- lib
|
|
80
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
81
|
+
requirements:
|
|
82
|
+
- - ">="
|
|
83
|
+
- !ruby/object:Gem::Version
|
|
84
|
+
version: 3.2.0
|
|
85
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - ">="
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '0'
|
|
90
|
+
requirements: []
|
|
91
|
+
rubygems_version: 3.5.16
|
|
92
|
+
signing_key:
|
|
93
|
+
specification_version: 4
|
|
94
|
+
summary: Resident Claude Code expert subagents, contributed by the gems an app uses.
|
|
95
|
+
test_files: []
|