rubyn-code 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/LICENSE +21 -0
- data/README.md +620 -0
- data/db/migrations/000_create_schema_migrations.sql +4 -0
- data/db/migrations/001_create_sessions.sql +16 -0
- data/db/migrations/002_create_messages.sql +16 -0
- data/db/migrations/003_create_tasks.sql +17 -0
- data/db/migrations/004_create_task_dependencies.sql +8 -0
- data/db/migrations/005_create_memories.sql +44 -0
- data/db/migrations/006_create_cost_records.sql +16 -0
- data/db/migrations/007_create_hooks.sql +12 -0
- data/db/migrations/008_create_skills_cache.sql +8 -0
- data/db/migrations/009_create_teams.sql +27 -0
- data/db/migrations/010_create_instincts.sql +15 -0
- data/exe/rubyn-code +6 -0
- data/lib/rubyn_code/agent/conversation.rb +193 -0
- data/lib/rubyn_code/agent/loop.rb +517 -0
- data/lib/rubyn_code/agent/loop_detector.rb +78 -0
- data/lib/rubyn_code/auth/oauth.rb +174 -0
- data/lib/rubyn_code/auth/server.rb +126 -0
- data/lib/rubyn_code/auth/token_store.rb +153 -0
- data/lib/rubyn_code/autonomous/daemon.rb +233 -0
- data/lib/rubyn_code/autonomous/idle_poller.rb +111 -0
- data/lib/rubyn_code/autonomous/task_claimer.rb +100 -0
- data/lib/rubyn_code/background/job.rb +19 -0
- data/lib/rubyn_code/background/notifier.rb +44 -0
- data/lib/rubyn_code/background/worker.rb +146 -0
- data/lib/rubyn_code/cli/app.rb +118 -0
- data/lib/rubyn_code/cli/input_handler.rb +79 -0
- data/lib/rubyn_code/cli/renderer.rb +205 -0
- data/lib/rubyn_code/cli/repl.rb +519 -0
- data/lib/rubyn_code/cli/spinner.rb +100 -0
- data/lib/rubyn_code/cli/stream_formatter.rb +149 -0
- data/lib/rubyn_code/config/defaults.rb +43 -0
- data/lib/rubyn_code/config/project_config.rb +120 -0
- data/lib/rubyn_code/config/settings.rb +127 -0
- data/lib/rubyn_code/context/auto_compact.rb +81 -0
- data/lib/rubyn_code/context/compactor.rb +89 -0
- data/lib/rubyn_code/context/manager.rb +91 -0
- data/lib/rubyn_code/context/manual_compact.rb +87 -0
- data/lib/rubyn_code/context/micro_compact.rb +135 -0
- data/lib/rubyn_code/db/connection.rb +176 -0
- data/lib/rubyn_code/db/migrator.rb +146 -0
- data/lib/rubyn_code/db/schema.rb +106 -0
- data/lib/rubyn_code/hooks/built_in.rb +124 -0
- data/lib/rubyn_code/hooks/registry.rb +99 -0
- data/lib/rubyn_code/hooks/runner.rb +88 -0
- data/lib/rubyn_code/hooks/user_hooks.rb +90 -0
- data/lib/rubyn_code/learning/extractor.rb +191 -0
- data/lib/rubyn_code/learning/injector.rb +138 -0
- data/lib/rubyn_code/learning/instinct.rb +172 -0
- data/lib/rubyn_code/llm/client.rb +218 -0
- data/lib/rubyn_code/llm/message_builder.rb +116 -0
- data/lib/rubyn_code/llm/streaming.rb +203 -0
- data/lib/rubyn_code/mcp/client.rb +139 -0
- data/lib/rubyn_code/mcp/config.rb +83 -0
- data/lib/rubyn_code/mcp/sse_transport.rb +225 -0
- data/lib/rubyn_code/mcp/stdio_transport.rb +196 -0
- data/lib/rubyn_code/mcp/tool_bridge.rb +164 -0
- data/lib/rubyn_code/memory/models.rb +62 -0
- data/lib/rubyn_code/memory/search.rb +181 -0
- data/lib/rubyn_code/memory/session_persistence.rb +194 -0
- data/lib/rubyn_code/memory/store.rb +199 -0
- data/lib/rubyn_code/observability/budget_enforcer.rb +159 -0
- data/lib/rubyn_code/observability/cost_calculator.rb +61 -0
- data/lib/rubyn_code/observability/models.rb +29 -0
- data/lib/rubyn_code/observability/token_counter.rb +42 -0
- data/lib/rubyn_code/observability/usage_reporter.rb +140 -0
- data/lib/rubyn_code/output/diff_renderer.rb +212 -0
- data/lib/rubyn_code/output/formatter.rb +120 -0
- data/lib/rubyn_code/permissions/deny_list.rb +49 -0
- data/lib/rubyn_code/permissions/policy.rb +59 -0
- data/lib/rubyn_code/permissions/prompter.rb +80 -0
- data/lib/rubyn_code/permissions/tier.rb +22 -0
- data/lib/rubyn_code/protocols/interrupt_handler.rb +95 -0
- data/lib/rubyn_code/protocols/plan_approval.rb +67 -0
- data/lib/rubyn_code/protocols/shutdown_handshake.rb +109 -0
- data/lib/rubyn_code/skills/catalog.rb +70 -0
- data/lib/rubyn_code/skills/document.rb +80 -0
- data/lib/rubyn_code/skills/loader.rb +57 -0
- data/lib/rubyn_code/sub_agents/runner.rb +168 -0
- data/lib/rubyn_code/sub_agents/summarizer.rb +57 -0
- data/lib/rubyn_code/tasks/dag.rb +208 -0
- data/lib/rubyn_code/tasks/manager.rb +212 -0
- data/lib/rubyn_code/tasks/models.rb +31 -0
- data/lib/rubyn_code/teams/mailbox.rb +128 -0
- data/lib/rubyn_code/teams/manager.rb +175 -0
- data/lib/rubyn_code/teams/teammate.rb +38 -0
- data/lib/rubyn_code/tools/background_run.rb +41 -0
- data/lib/rubyn_code/tools/base.rb +84 -0
- data/lib/rubyn_code/tools/bash.rb +81 -0
- data/lib/rubyn_code/tools/bundle_add.rb +53 -0
- data/lib/rubyn_code/tools/bundle_install.rb +41 -0
- data/lib/rubyn_code/tools/compact.rb +57 -0
- data/lib/rubyn_code/tools/db_migrate.rb +52 -0
- data/lib/rubyn_code/tools/edit_file.rb +49 -0
- data/lib/rubyn_code/tools/executor.rb +62 -0
- data/lib/rubyn_code/tools/git_commit.rb +97 -0
- data/lib/rubyn_code/tools/git_diff.rb +61 -0
- data/lib/rubyn_code/tools/git_log.rb +59 -0
- data/lib/rubyn_code/tools/git_status.rb +59 -0
- data/lib/rubyn_code/tools/glob.rb +44 -0
- data/lib/rubyn_code/tools/grep.rb +81 -0
- data/lib/rubyn_code/tools/load_skill.rb +41 -0
- data/lib/rubyn_code/tools/memory_search.rb +77 -0
- data/lib/rubyn_code/tools/memory_write.rb +52 -0
- data/lib/rubyn_code/tools/rails_generate.rb +54 -0
- data/lib/rubyn_code/tools/read_file.rb +38 -0
- data/lib/rubyn_code/tools/read_inbox.rb +64 -0
- data/lib/rubyn_code/tools/registry.rb +48 -0
- data/lib/rubyn_code/tools/review_pr.rb +145 -0
- data/lib/rubyn_code/tools/run_specs.rb +75 -0
- data/lib/rubyn_code/tools/schema.rb +59 -0
- data/lib/rubyn_code/tools/send_message.rb +53 -0
- data/lib/rubyn_code/tools/spawn_agent.rb +154 -0
- data/lib/rubyn_code/tools/spawn_teammate.rb +168 -0
- data/lib/rubyn_code/tools/task.rb +148 -0
- data/lib/rubyn_code/tools/web_fetch.rb +108 -0
- data/lib/rubyn_code/tools/web_search.rb +196 -0
- data/lib/rubyn_code/tools/write_file.rb +30 -0
- data/lib/rubyn_code/version.rb +5 -0
- data/lib/rubyn_code.rb +203 -0
- data/skills/code_quality/fits_in_your_head.md +189 -0
- data/skills/code_quality/naming_conventions.md +213 -0
- data/skills/code_quality/null_object.md +205 -0
- data/skills/code_quality/technical_debt.md +135 -0
- data/skills/code_quality/value_objects.md +216 -0
- data/skills/code_quality/yagni.md +176 -0
- data/skills/design_patterns/adapter.md +191 -0
- data/skills/design_patterns/bridge_memento_visitor.md +254 -0
- data/skills/design_patterns/builder.md +158 -0
- data/skills/design_patterns/command.md +126 -0
- data/skills/design_patterns/composite.md +147 -0
- data/skills/design_patterns/decorator.md +204 -0
- data/skills/design_patterns/facade.md +133 -0
- data/skills/design_patterns/factory_method.md +169 -0
- data/skills/design_patterns/iterator.md +116 -0
- data/skills/design_patterns/mediator.md +133 -0
- data/skills/design_patterns/observer.md +177 -0
- data/skills/design_patterns/proxy.md +140 -0
- data/skills/design_patterns/singleton.md +124 -0
- data/skills/design_patterns/state.md +207 -0
- data/skills/design_patterns/strategy.md +127 -0
- data/skills/design_patterns/template_method.md +173 -0
- data/skills/gems/devise.md +365 -0
- data/skills/gems/dry_rb.md +186 -0
- data/skills/gems/factory_bot.md +268 -0
- data/skills/gems/faraday.md +263 -0
- data/skills/gems/graphql_ruby.md +514 -0
- data/skills/gems/pundit.md +446 -0
- data/skills/gems/redis.md +219 -0
- data/skills/gems/rubocop.md +257 -0
- data/skills/gems/sidekiq.md +360 -0
- data/skills/gems/stripe.md +224 -0
- data/skills/minitest/assertions.md +185 -0
- data/skills/minitest/fixtures.md +238 -0
- data/skills/minitest/integration_tests.md +210 -0
- data/skills/minitest/mailers_and_jobs.md +218 -0
- data/skills/minitest/mocking_stubbing.md +202 -0
- data/skills/minitest/service_tests_and_performance.md +246 -0
- data/skills/minitest/structure_and_conventions.md +169 -0
- data/skills/minitest/system_tests.md +237 -0
- data/skills/rails/action_cable.md +160 -0
- data/skills/rails/active_record_basics.md +174 -0
- data/skills/rails/active_storage.md +242 -0
- data/skills/rails/api_design.md +212 -0
- data/skills/rails/associations.md +182 -0
- data/skills/rails/background_jobs.md +212 -0
- data/skills/rails/caching.md +158 -0
- data/skills/rails/callbacks.md +135 -0
- data/skills/rails/concerns_controllers.md +218 -0
- data/skills/rails/concerns_models.md +280 -0
- data/skills/rails/controllers.md +190 -0
- data/skills/rails/engines.md +201 -0
- data/skills/rails/form_objects.md +168 -0
- data/skills/rails/hotwire.md +229 -0
- data/skills/rails/internationalization.md +192 -0
- data/skills/rails/logging.md +198 -0
- data/skills/rails/mailers.md +180 -0
- data/skills/rails/migrations.md +200 -0
- data/skills/rails/multitenancy.md +207 -0
- data/skills/rails/n_plus_one.md +151 -0
- data/skills/rails/presenters.md +244 -0
- data/skills/rails/query_objects.md +177 -0
- data/skills/rails/routing.md +194 -0
- data/skills/rails/scopes.md +187 -0
- data/skills/rails/security.md +233 -0
- data/skills/rails/serializers.md +243 -0
- data/skills/rails/service_objects.md +184 -0
- data/skills/rails/testing_strategy.md +258 -0
- data/skills/rails/validations.md +206 -0
- data/skills/refactoring/code_smells.md +251 -0
- data/skills/refactoring/command_query_separation.md +166 -0
- data/skills/refactoring/encapsulate_collection.md +125 -0
- data/skills/refactoring/extract_class.md +138 -0
- data/skills/refactoring/extract_method.md +185 -0
- data/skills/refactoring/replace_conditional.md +211 -0
- data/skills/refactoring/value_objects.md +246 -0
- data/skills/rspec/build_stubbed.md +199 -0
- data/skills/rspec/factory_design.md +206 -0
- data/skills/rspec/let_vs_let_bang.md +161 -0
- data/skills/rspec/mocking_stubbing.md +209 -0
- data/skills/rspec/request_specs.md +212 -0
- data/skills/rspec/service_specs.md +262 -0
- data/skills/rspec/shared_examples.md +244 -0
- data/skills/rspec/system_specs.md +286 -0
- data/skills/rspec/test_performance.md +215 -0
- data/skills/ruby/blocks_procs_lambdas.md +204 -0
- data/skills/ruby/classes.md +155 -0
- data/skills/ruby/concurrency.md +194 -0
- data/skills/ruby/data_struct_openstruct.md +158 -0
- data/skills/ruby/debugging_profiling.md +204 -0
- data/skills/ruby/enumerable_patterns.md +168 -0
- data/skills/ruby/exception_handling.md +199 -0
- data/skills/ruby/file_io.md +217 -0
- data/skills/ruby/hashes.md +195 -0
- data/skills/ruby/metaprogramming.md +170 -0
- data/skills/ruby/modules.md +210 -0
- data/skills/ruby/pattern_matching.md +177 -0
- data/skills/ruby/regular_expressions.md +166 -0
- data/skills/ruby/result_objects.md +200 -0
- data/skills/ruby/strings.md +177 -0
- data/skills/ruby_project/bundler_dependencies.md +181 -0
- data/skills/ruby_project/cli_tools.md +224 -0
- data/skills/ruby_project/rake_tasks.md +146 -0
- data/skills/ruby_project/structure.md +261 -0
- data/skills/sinatra/application_structure.md +241 -0
- data/skills/sinatra/middleware_and_deployment.md +221 -0
- data/skills/sinatra/testing.md +233 -0
- data/skills/solid/dependency_inversion.md +195 -0
- data/skills/solid/interface_segregation.md +237 -0
- data/skills/solid/liskov_substitution.md +263 -0
- data/skills/solid/open_closed.md +212 -0
- data/skills/solid/single_responsibility.md +183 -0
- metadata +397 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 145ce97f1dd515f20c3fed6dbe8d84526f37d8d9c20c44ecc2fd69de60257caf
|
|
4
|
+
data.tar.gz: 1506876211d73ea5f6aef672fc501b9e924771bf7498e75f34384d98c6afe78f
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 11f8a71b925fa02fc60a97dfae217498df7d17cb4cd95ba82aa2a6c94524f7a95182488ce209242069791ad5bd46c0e32b0e03b1170643cda6492dd683fa0ed5
|
|
7
|
+
data.tar.gz: 741916a0fb8085b4baef4a0514e387f54c0a38720435e2cda50fa92dcd4d00d004866986e1d148dadbf0e120105d24f14c509e5df48c367c72d12f3c52490e96
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 fadedmaturity
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,620 @@
|
|
|
1
|
+
# Rubyn Code
|
|
2
|
+
|
|
3
|
+
An AI-powered CLI coding assistant built in Ruby, specialized for Ruby and Rails development. Powered by Claude Opus 4.6, authenticating via your existing Claude subscription (OAuth) — no API keys required.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Install the gem
|
|
9
|
+
gem install rubyn-code
|
|
10
|
+
|
|
11
|
+
# Start the interactive REPL
|
|
12
|
+
rubyn-code
|
|
13
|
+
|
|
14
|
+
# YOLO mode — no tool approval prompts
|
|
15
|
+
rubyn-code --yolo
|
|
16
|
+
|
|
17
|
+
# Run a single prompt and exit
|
|
18
|
+
rubyn-code -p "Add authentication to the users controller"
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
**Authentication:** Rubyn Code automatically reads your Claude Code OAuth token from the macOS Keychain. Just make sure you've logged into Claude Code at least once (`claude` in your terminal). No separate auth step needed.
|
|
22
|
+
|
|
23
|
+
## RUBYN.md — Project Instructions
|
|
24
|
+
|
|
25
|
+
Just like Claude Code has `CLAUDE.md`, Rubyn Code looks for instruction files to understand your project's conventions, preferences, and rules.
|
|
26
|
+
|
|
27
|
+
**Rubyn Code detects all three conventions:**
|
|
28
|
+
- `RUBYN.md` — Rubyn Code native
|
|
29
|
+
- `CLAUDE.md` — Claude Code compatible (works out of the box)
|
|
30
|
+
- `AGENT.md` — Generic agent convention
|
|
31
|
+
|
|
32
|
+
If your project already has a `CLAUDE.md` or `AGENT.md`, Rubyn Code will read it automatically. No migration needed.
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# Create project instructions
|
|
36
|
+
cat > RUBYN.md << 'EOF'
|
|
37
|
+
# My Project
|
|
38
|
+
|
|
39
|
+
- Always use RSpec, never Minitest
|
|
40
|
+
- Use FactoryBot for test data
|
|
41
|
+
- Follow the service object pattern for business logic
|
|
42
|
+
- API endpoints use Grape, not Rails controllers
|
|
43
|
+
- Run rubocop before committing
|
|
44
|
+
EOF
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Where to put RUBYN.md
|
|
48
|
+
|
|
49
|
+
Rubyn Code loads `RUBYN.md` from multiple locations, all merged together:
|
|
50
|
+
|
|
51
|
+
| Location | Scope | Loaded |
|
|
52
|
+
|----------|-------|--------|
|
|
53
|
+
| `~/.rubyn-code/RUBYN.md` | Global | Always — applies to all projects |
|
|
54
|
+
| Parent directories above project root | Monorepo | Auto — walks up to find shared instructions |
|
|
55
|
+
| `./RUBYN.md` / `./CLAUDE.md` / `./AGENT.md` | Project | Auto — main project instructions |
|
|
56
|
+
| `./.rubyn-code/RUBYN.md` | Project | Auto — alternative location |
|
|
57
|
+
| `./subdir/RUBYN.md` (or CLAUDE.md, AGENT.md) | Subfolder | Auto — one level deep at startup |
|
|
58
|
+
| Any directory Rubyn navigates to | Dynamic | On demand — Rubyn checks when entering new dirs |
|
|
59
|
+
|
|
60
|
+
**Priority:** Project-level instructions override global ones. All files are concatenated into the system prompt.
|
|
61
|
+
|
|
62
|
+
### Example: Monorepo with multiple services
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
my-monorepo/
|
|
66
|
+
├── RUBYN.md # Shared conventions (loaded for all services)
|
|
67
|
+
├── api/
|
|
68
|
+
│ ├── RUBYN.md # API-specific: "Use Grape, JSON:API format"
|
|
69
|
+
│ └── ...
|
|
70
|
+
├── web/
|
|
71
|
+
│ ├── RUBYN.md # Web-specific: "Use Hotwire, ViewComponents"
|
|
72
|
+
│ └── ...
|
|
73
|
+
└── workers/
|
|
74
|
+
├── RUBYN.md # Worker-specific: "Use Sidekiq, idempotent jobs"
|
|
75
|
+
└── ...
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Skills — 112 Ruby/Rails Best Practice Documents
|
|
79
|
+
|
|
80
|
+
Rubyn Code ships with 112 best practice documents organized by topic. Skills load **on-demand** — only their names appear in memory until Rubyn needs the full content.
|
|
81
|
+
|
|
82
|
+
### Built-in skill categories
|
|
83
|
+
|
|
84
|
+
| Category | Topics |
|
|
85
|
+
|----------|--------|
|
|
86
|
+
| **Ruby** | Collections, error handling, metaprogramming, concurrency |
|
|
87
|
+
| **Rails** | Controllers, models, views, migrations, ActiveRecord |
|
|
88
|
+
| **RSpec** | Matchers, factories, request specs, performance |
|
|
89
|
+
| **Minitest** | Assertions, system tests, fixtures |
|
|
90
|
+
| **Design Patterns** | Observer, strategy, decorator, builder, and more |
|
|
91
|
+
| **SOLID** | All five principles with Ruby examples |
|
|
92
|
+
| **Refactoring** | Extract method, replace conditional, code smells |
|
|
93
|
+
| **Code Quality** | Naming, YAGNI, value objects, null object |
|
|
94
|
+
| **Gems** | Development, versioning, publishing |
|
|
95
|
+
| **Sinatra** | Application structure, middleware, testing |
|
|
96
|
+
|
|
97
|
+
### Custom skills
|
|
98
|
+
|
|
99
|
+
Add your own skills or override built-in ones:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
# Project-specific skills
|
|
103
|
+
mkdir -p .rubyn-code/skills
|
|
104
|
+
cat > .rubyn-code/skills/our_api_conventions.md << 'EOF'
|
|
105
|
+
# Our API Conventions
|
|
106
|
+
|
|
107
|
+
- All endpoints return JSON:API format
|
|
108
|
+
- Use Grape for API controllers
|
|
109
|
+
- Version APIs with /v1/ prefix
|
|
110
|
+
- Always paginate collections with Kaminari
|
|
111
|
+
EOF
|
|
112
|
+
|
|
113
|
+
# Global skills (apply to all projects)
|
|
114
|
+
mkdir -p ~/.rubyn-code/skills
|
|
115
|
+
cat > ~/.rubyn-code/skills/my_preferences.md << 'EOF'
|
|
116
|
+
# My Coding Preferences
|
|
117
|
+
|
|
118
|
+
- Use double quotes for strings
|
|
119
|
+
- Prefer guard clauses over nested conditionals
|
|
120
|
+
- Always add frozen_string_literal comment
|
|
121
|
+
EOF
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**Skill priority:** Project `.rubyn-code/skills/` > User `~/.rubyn-code/skills/` > Bundled defaults
|
|
125
|
+
|
|
126
|
+
## PR Review — Best Practice Code Review
|
|
127
|
+
|
|
128
|
+
Rubyn Code can review your current branch against Ruby/Rails best practices, giving you line-by-line suggestions before you open a PR.
|
|
129
|
+
|
|
130
|
+
### Quick usage
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
rubyn > /review # Review current branch vs main
|
|
134
|
+
rubyn > /review develop # Review against develop branch
|
|
135
|
+
rubyn > /review main security # Security-focused review only
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Focus areas
|
|
139
|
+
|
|
140
|
+
| Focus | What it checks |
|
|
141
|
+
|-------|---------------|
|
|
142
|
+
| `all` *(default)* | Everything — code quality, security, performance, testing, conventions |
|
|
143
|
+
| `security` | SQL injection, XSS, CSRF, mass assignment, auth gaps, sensitive data exposure |
|
|
144
|
+
| `performance` | N+1 queries, missing indexes, eager loading, caching, pagination |
|
|
145
|
+
| `style` | Ruby idioms, naming, method length, DRY violations, dead code |
|
|
146
|
+
| `testing` | Missing coverage, test quality, factory usage, edge cases, flaky test risks |
|
|
147
|
+
|
|
148
|
+
### What it does
|
|
149
|
+
|
|
150
|
+
1. Gets the diff of your current branch vs the base branch
|
|
151
|
+
2. Categorizes changed files (Ruby, templates, specs, migrations, config)
|
|
152
|
+
3. Loads relevant best practice skills automatically
|
|
153
|
+
4. Reviews every change with actionable suggestions
|
|
154
|
+
5. Rates each issue by severity:
|
|
155
|
+
|
|
156
|
+
| Severity | Meaning |
|
|
157
|
+
|----------|---------|
|
|
158
|
+
| **[critical]** | Must fix — security vulnerability, data loss risk, or broken functionality |
|
|
159
|
+
| **[warning]** | Should fix — performance issue, missing test, or convention violation |
|
|
160
|
+
| **[suggestion]** | Nice to have — cleaner approach, better naming, or Ruby idiom |
|
|
161
|
+
| **[nitpick]** | Optional — style preference or minor readability improvement |
|
|
162
|
+
|
|
163
|
+
### Example output
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
[warning] app/models/user.rb:15
|
|
167
|
+
User.where(active: true).each { |u| u.posts.count }
|
|
168
|
+
↳ N+1 query — `posts.count` fires a separate query per user.
|
|
169
|
+
Fix: User.where(active: true).includes(:posts).each { ... }
|
|
170
|
+
Or use counter_cache: true on the association.
|
|
171
|
+
|
|
172
|
+
[critical] app/controllers/admin_controller.rb:8
|
|
173
|
+
params[:user_id] used directly in SQL
|
|
174
|
+
↳ SQL injection risk. Use parameterized queries.
|
|
175
|
+
Fix: User.where(id: params[:user_id])
|
|
176
|
+
|
|
177
|
+
[suggestion] app/services/create_order.rb:22
|
|
178
|
+
Method `process` is 45 lines long
|
|
179
|
+
↳ Extract into smaller private methods for readability.
|
|
180
|
+
Consider: extract_line_items, calculate_totals, apply_discounts
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Natural language works too
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
rubyn > Review my PR against best practices
|
|
187
|
+
rubyn > Check this branch for security issues
|
|
188
|
+
rubyn > Are there any N+1 queries in my changes?
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Architecture
|
|
192
|
+
|
|
193
|
+
Rubyn Code implements a 16-layer agentic architecture:
|
|
194
|
+
|
|
195
|
+
```
|
|
196
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
197
|
+
│ Layer 16: Continuous Learning (pattern extraction) │
|
|
198
|
+
│ Layer 15: MCP (external tool servers via protocol) │
|
|
199
|
+
│ Layer 14: Hooks & Events (pre/post tool interception) │
|
|
200
|
+
│ Layer 13: Observability (cost tracking, token counting) │
|
|
201
|
+
│ Layer 12: Memory (persistent knowledge across sessions) │
|
|
202
|
+
│ Layer 11: Autonomous Operation (idle polling, KAIROS) │
|
|
203
|
+
│ Layer 10: Protocols (shutdown handshake, plan approval) │
|
|
204
|
+
│ Layer 9: Teams (persistent teammates, mailbox messaging) │
|
|
205
|
+
│ Layer 8: Background Execution (async tasks, notifications) │
|
|
206
|
+
│ Layer 7: Task System (persistent DAG, dependencies) │
|
|
207
|
+
│ Layer 6: Sub-Agents (isolated context, summary return) │
|
|
208
|
+
│ Layer 5: Skills (112 Ruby/Rails best practice docs) │
|
|
209
|
+
│ Layer 4: Context Management (compression pipeline) │
|
|
210
|
+
│ Layer 3: Permissions (tiered access, deny lists) │
|
|
211
|
+
│ Layer 2: Tool System (28 tools, dispatch map) │
|
|
212
|
+
│ Layer 1: THE AGENT LOOP (while tool_use → execute → repeat) │
|
|
213
|
+
└──────────────────────────────────────────────────────────────┘
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
The core is six lines:
|
|
217
|
+
|
|
218
|
+
```ruby
|
|
219
|
+
while response.tool_use?
|
|
220
|
+
results = execute_tools(response)
|
|
221
|
+
conversation.add_tool_results(results)
|
|
222
|
+
response = llm.chat(conversation.messages)
|
|
223
|
+
end
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
Everything else is a layer around that loop.
|
|
227
|
+
|
|
228
|
+
## Tools (28 built-in)
|
|
229
|
+
|
|
230
|
+
| Category | Tools |
|
|
231
|
+
|----------|-------|
|
|
232
|
+
| **File I/O** | `read_file`, `write_file`, `edit_file` |
|
|
233
|
+
| **Search** | `glob`, `grep` |
|
|
234
|
+
| **Execution** | `bash` (sandboxed, dangerous commands blocked) |
|
|
235
|
+
| **Web** | `web_search` (DuckDuckGo), `web_fetch` (fetch any URL as text) |
|
|
236
|
+
| **Git** | `git_status`, `git_diff`, `git_log`, `git_commit` |
|
|
237
|
+
| **Rails** | `rails_generate`, `db_migrate`, `run_specs`, `bundle_install`, `bundle_add` |
|
|
238
|
+
| **Review** | `review_pr` (diff-based best practice code review) |
|
|
239
|
+
| **Agents** | `spawn_agent` (isolated sub-agent), `spawn_teammate` (persistent named agent), `background_run` |
|
|
240
|
+
| **Agent** | `compact`, `load_skill`, `task` |
|
|
241
|
+
| **Memory** | `memory_search`, `memory_write` |
|
|
242
|
+
| **Teams** | `send_message`, `read_inbox` |
|
|
243
|
+
|
|
244
|
+
## CLI Commands
|
|
245
|
+
|
|
246
|
+
### Flags
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
rubyn-code # Start interactive REPL
|
|
250
|
+
rubyn-code --yolo # Auto-approve all tool calls
|
|
251
|
+
rubyn-code -p "prompt" # Run a single prompt and exit
|
|
252
|
+
rubyn-code --resume [ID] # Resume a previous session
|
|
253
|
+
rubyn-code --auth # Set up authentication
|
|
254
|
+
rubyn-code --version # Show version
|
|
255
|
+
rubyn-code --help # Show help
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### Interactive Commands
|
|
259
|
+
|
|
260
|
+
Type `/` to see all available commands, or `/` + Tab for autocomplete:
|
|
261
|
+
|
|
262
|
+
```
|
|
263
|
+
/help Show help
|
|
264
|
+
/quit Exit Rubyn Code
|
|
265
|
+
/review [base] PR review against best practices (default: main)
|
|
266
|
+
/spawn name role Spawn a persistent teammate agent
|
|
267
|
+
/compact Compress conversation context
|
|
268
|
+
/cost Show token usage and costs
|
|
269
|
+
/clear Clear the terminal
|
|
270
|
+
/undo Remove last exchange
|
|
271
|
+
/tasks List all tasks
|
|
272
|
+
/budget [amt] Show or set session budget
|
|
273
|
+
/skill [name] Load or list available skills
|
|
274
|
+
/resume [id] Resume or list sessions
|
|
275
|
+
/version Show version
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### Tips
|
|
279
|
+
|
|
280
|
+
- Use `@filename` to include file contents in your message
|
|
281
|
+
- End a line with `\` for multiline input
|
|
282
|
+
- Ctrl-C once to interrupt, twice to exit
|
|
283
|
+
- `/` + Tab autocompletes slash commands
|
|
284
|
+
|
|
285
|
+
## Permission Modes
|
|
286
|
+
|
|
287
|
+
| Mode | Flag | Behavior |
|
|
288
|
+
|------|------|----------|
|
|
289
|
+
| **Allow Read** | *(default)* | Read tools auto-approved, writes need approval |
|
|
290
|
+
| **YOLO** | `--yolo` | Everything auto-approved — no prompts |
|
|
291
|
+
|
|
292
|
+
## Streaming Output
|
|
293
|
+
|
|
294
|
+
Rubyn Code streams responses in real-time — text appears character-by-character as the model generates it, just like Claude Code. No more waiting for the full response to render.
|
|
295
|
+
|
|
296
|
+
When Rubyn calls tools mid-response, you see each tool call and result live:
|
|
297
|
+
|
|
298
|
+
```
|
|
299
|
+
rubyn > Fix the N+1 query in UsersController
|
|
300
|
+
> read_file: path=app/controllers/users_controller.rb
|
|
301
|
+
class UsersController < ApplicationController...
|
|
302
|
+
> edit_file: path=app/controllers/users_controller.rb, old_text=User.all, new_text=User.includes(:posts).all
|
|
303
|
+
Edited app/controllers/users_controller.rb
|
|
304
|
+
> run_specs: path=spec/controllers/users_controller_spec.rb
|
|
305
|
+
3 examples, 0 failures
|
|
306
|
+
|
|
307
|
+
Fixed the N+1 by adding `.includes(:posts)` to the query. Specs pass. ✓
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
## Sub-Agents & Teams
|
|
311
|
+
|
|
312
|
+
### Sub-Agents (disposable)
|
|
313
|
+
|
|
314
|
+
Rubyn can spawn isolated sub-agents for research or parallel work. Sub-agents get their own fresh context and return only a summary — keeping Rubyn's main conversation clean.
|
|
315
|
+
|
|
316
|
+
```bash
|
|
317
|
+
rubyn > Go explore the app/services directory and summarize the patterns used
|
|
318
|
+
|
|
319
|
+
Spawning explore agent...
|
|
320
|
+
> sub-agent > glob: pattern=app/services/**/*.rb
|
|
321
|
+
> sub-agent > read_file: path=app/services/create_user.rb
|
|
322
|
+
> sub-agent > read_file: path=app/services/process_payment.rb
|
|
323
|
+
Agent finished.
|
|
324
|
+
|
|
325
|
+
## Sub-Agent Result (explore)
|
|
326
|
+
The services directory uses a consistent .call pattern...
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
Two types:
|
|
330
|
+
- **Explore** (`agent_type: "explore"`) — read-only tools, for research
|
|
331
|
+
- **Worker** (`agent_type: "worker"`) — full write access, for doing work
|
|
332
|
+
|
|
333
|
+
### Teams (persistent)
|
|
334
|
+
|
|
335
|
+
Spawn named teammates that persist, have their own inbox, and communicate via messages:
|
|
336
|
+
|
|
337
|
+
```bash
|
|
338
|
+
rubyn > /spawn alice tester
|
|
339
|
+
Spawned teammate alice as tester
|
|
340
|
+
|
|
341
|
+
rubyn > Send alice a message to write specs for the User model
|
|
342
|
+
> send_message: to=alice, content=Write specs for the User model...
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
Teammates run in background threads with their own agent loop, can claim tasks from the task board, and communicate via mailbox messaging.
|
|
346
|
+
|
|
347
|
+
## User Hooks
|
|
348
|
+
|
|
349
|
+
Customize Rubyn's behavior with `.rubyn-code/hooks.yml` in your project or `~/.rubyn-code/hooks.yml` globally:
|
|
350
|
+
|
|
351
|
+
```yaml
|
|
352
|
+
# Block dangerous operations
|
|
353
|
+
pre_tool_use:
|
|
354
|
+
- tool: bash
|
|
355
|
+
match: "rm -rf"
|
|
356
|
+
action: deny
|
|
357
|
+
reason: "Destructive recursive delete blocked"
|
|
358
|
+
|
|
359
|
+
- tool: write_file
|
|
360
|
+
path: "db/migrate/**"
|
|
361
|
+
action: deny
|
|
362
|
+
reason: "Use rails generate migration instead"
|
|
363
|
+
|
|
364
|
+
- tool: bash
|
|
365
|
+
match: "git push --force"
|
|
366
|
+
action: deny
|
|
367
|
+
reason: "Force push blocked — use regular push"
|
|
368
|
+
|
|
369
|
+
# Audit trail for file writes
|
|
370
|
+
post_tool_use:
|
|
371
|
+
- tool: write_file
|
|
372
|
+
action: log
|
|
373
|
+
- tool: edit_file
|
|
374
|
+
action: log
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
Hook actions:
|
|
378
|
+
- **`deny`** — block the tool call with a reason (shown to the model)
|
|
379
|
+
- **`log`** — append to `.rubyn-code/audit.log`
|
|
380
|
+
|
|
381
|
+
Matching:
|
|
382
|
+
- **`tool`** — exact tool name match
|
|
383
|
+
- **`match`** — string match anywhere in the parameters
|
|
384
|
+
- **`path`** — glob pattern match on the `path` parameter
|
|
385
|
+
|
|
386
|
+
## Continuous Learning
|
|
387
|
+
|
|
388
|
+
Rubyn learns from every session and gets smarter over time.
|
|
389
|
+
|
|
390
|
+
### How it works
|
|
391
|
+
|
|
392
|
+
1. **During conversation** — Rubyn saves preferences and patterns via `memory_write`
|
|
393
|
+
2. **On session end** — extracts reusable patterns ("instincts") with confidence scores
|
|
394
|
+
3. **On next startup** — injects top instincts and recent memories into the system prompt
|
|
395
|
+
4. **Over time** — unused instincts decay, reinforced ones strengthen
|
|
396
|
+
|
|
397
|
+
### Instinct lifecycle
|
|
398
|
+
|
|
399
|
+
```
|
|
400
|
+
Session 1: You correct Rubyn → instinct saved (confidence: 0.5)
|
|
401
|
+
Session 2: Same pattern confirmed → confidence: 0.7
|
|
402
|
+
Session 3: Not used → confidence: 0.65 (decay)
|
|
403
|
+
Session 4: Reinforced again → confidence: 0.8
|
|
404
|
+
Session 10: Never used again → deleted (below 0.05)
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
### Feedback reinforcement
|
|
408
|
+
|
|
409
|
+
Rubyn detects your feedback and adjusts:
|
|
410
|
+
- **"yes that fixed it"** / **"perfect"** → reinforces recent instincts
|
|
411
|
+
- **"no, use X instead"** / **"that's wrong"** → penalizes and learns the correction
|
|
412
|
+
|
|
413
|
+
## Web Tools
|
|
414
|
+
|
|
415
|
+
Rubyn can search the web and fetch documentation:
|
|
416
|
+
|
|
417
|
+
```bash
|
|
418
|
+
rubyn > Search for how to set up Sidekiq with Rails 8
|
|
419
|
+
> web_search: query=Sidekiq Rails 8 setup guide
|
|
420
|
+
|
|
421
|
+
rubyn > Fetch the Sidekiq README
|
|
422
|
+
> web_fetch: url=https://github.com/sidekiq/sidekiq/blob/main/README.md
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
### Search Providers
|
|
426
|
+
|
|
427
|
+
Rubyn auto-detects the best available search provider based on your environment variables. No configuration needed — just set the key and it switches automatically.
|
|
428
|
+
|
|
429
|
+
| Provider | Env Variable | Free Tier | Notes |
|
|
430
|
+
|----------|-------------|-----------|-------|
|
|
431
|
+
| **DuckDuckGo** | *(none needed)* | Unlimited | Default. No API key required |
|
|
432
|
+
| **Tavily** | `TAVILY_API_KEY` | 1,000/mo | Built for AI agents. Includes AI-generated answer |
|
|
433
|
+
| **Brave** | `BRAVE_API_KEY` | 2,000/mo | Fast, good quality results |
|
|
434
|
+
| **SerpAPI** | `SERPAPI_API_KEY` | 100/mo | Google results via API |
|
|
435
|
+
| **Google** | `GOOGLE_SEARCH_API_KEY` + `GOOGLE_SEARCH_CX` | 100/day | Official Google Custom Search |
|
|
436
|
+
|
|
437
|
+
**Priority order:** Tavily > Brave > SerpAPI > Google > DuckDuckGo
|
|
438
|
+
|
|
439
|
+
To switch providers, just export the key:
|
|
440
|
+
|
|
441
|
+
```bash
|
|
442
|
+
export TAVILY_API_KEY=tvly-xxxxxxxxxxxxx
|
|
443
|
+
rubyn-code # Now uses Tavily automatically
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
## Git Integration
|
|
447
|
+
|
|
448
|
+
Full git workflow without leaving the REPL:
|
|
449
|
+
|
|
450
|
+
```bash
|
|
451
|
+
rubyn > What files have I changed?
|
|
452
|
+
> git_status
|
|
453
|
+
|
|
454
|
+
rubyn > Show me the diff
|
|
455
|
+
> git_diff: target=unstaged
|
|
456
|
+
|
|
457
|
+
rubyn > Commit these changes
|
|
458
|
+
> git_commit: message=Fix N+1 query in UsersController, files=all
|
|
459
|
+
|
|
460
|
+
rubyn > Review my branch before I open a PR
|
|
461
|
+
> /review
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
## Authentication
|
|
465
|
+
|
|
466
|
+
Rubyn Code uses your existing Claude subscription — no API keys needed.
|
|
467
|
+
|
|
468
|
+
### How it works
|
|
469
|
+
|
|
470
|
+
1. You log into Claude Code once (`claude` in terminal)
|
|
471
|
+
2. Rubyn Code reads the OAuth token from your macOS Keychain
|
|
472
|
+
3. It authenticates directly with the Anthropic API using your subscription
|
|
473
|
+
|
|
474
|
+
### Fallback chain
|
|
475
|
+
|
|
476
|
+
| Priority | Source | How |
|
|
477
|
+
|----------|--------|-----|
|
|
478
|
+
| 1 | macOS Keychain | Reads Claude Code's OAuth token automatically |
|
|
479
|
+
| 2 | `~/.rubyn-code/tokens.yml` | Manual token file |
|
|
480
|
+
| 3 | `ANTHROPIC_API_KEY` env var | Standard API key (pay-per-use) |
|
|
481
|
+
|
|
482
|
+
### Supported plans
|
|
483
|
+
|
|
484
|
+
Works with Claude Pro, Max, Team, and Enterprise subscriptions. Default model: **Claude Opus 4.6**.
|
|
485
|
+
|
|
486
|
+
## Context Compression
|
|
487
|
+
|
|
488
|
+
Three-layer pipeline for infinite sessions:
|
|
489
|
+
|
|
490
|
+
1. **Micro Compact** — runs every turn, replaces old tool results with placeholders (zero cost)
|
|
491
|
+
2. **Auto Compact** — triggers at 50K tokens, saves transcript to disk, LLM-summarizes
|
|
492
|
+
3. **Manual Compact** — `/compact` at strategic moments (between phases of work)
|
|
493
|
+
|
|
494
|
+
## Task System
|
|
495
|
+
|
|
496
|
+
SQLite-backed DAG with dependency resolution:
|
|
497
|
+
|
|
498
|
+
```
|
|
499
|
+
Task 1: Set up database schema
|
|
500
|
+
Task 2: Build API endpoints (blocked by: Task 1)
|
|
501
|
+
Task 3: Write integration tests (blocked by: Task 2)
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
## Memory
|
|
505
|
+
|
|
506
|
+
Three-tier persistence with full-text search:
|
|
507
|
+
|
|
508
|
+
- **Short-term** — current session
|
|
509
|
+
- **Medium-term** — per-project (`.rubyn-code/`)
|
|
510
|
+
- **Long-term** — global (`~/.rubyn-code/`)
|
|
511
|
+
|
|
512
|
+
## MCP Support
|
|
513
|
+
|
|
514
|
+
Connect external tool servers via Model Context Protocol:
|
|
515
|
+
|
|
516
|
+
```json
|
|
517
|
+
// .rubyn-code/mcp.json
|
|
518
|
+
{
|
|
519
|
+
"servers": {
|
|
520
|
+
"github": {
|
|
521
|
+
"command": "npx",
|
|
522
|
+
"args": ["-y", "@anthropic/github-mcp-server"]
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
## Configuration
|
|
529
|
+
|
|
530
|
+
### Global config
|
|
531
|
+
|
|
532
|
+
`~/.rubyn-code/config.yml`:
|
|
533
|
+
|
|
534
|
+
```yaml
|
|
535
|
+
model: claude-opus-4-6
|
|
536
|
+
permission_mode: allow_read
|
|
537
|
+
session_budget: 5.00
|
|
538
|
+
daily_budget: 10.00
|
|
539
|
+
max_iterations: 200
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
### Project config
|
|
543
|
+
|
|
544
|
+
`.rubyn-code/config.yml` (overrides global):
|
|
545
|
+
|
|
546
|
+
```yaml
|
|
547
|
+
model: claude-sonnet-4-6
|
|
548
|
+
permission_mode: autonomous
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
## Data Storage
|
|
552
|
+
|
|
553
|
+
All data stored locally in SQLite:
|
|
554
|
+
|
|
555
|
+
| Location | Purpose |
|
|
556
|
+
|----------|---------|
|
|
557
|
+
| `~/.rubyn-code/config.yml` | Global settings |
|
|
558
|
+
| `~/.rubyn-code/tokens.yml` | Auth tokens (0600 permissions) |
|
|
559
|
+
| `~/.rubyn-code/rubyn_code.db` | Sessions, tasks, memories, costs |
|
|
560
|
+
| `~/.rubyn-code/RUBYN.md` | Global project instructions |
|
|
561
|
+
| `~/.rubyn-code/skills/*.md` | Global custom skills |
|
|
562
|
+
| `.rubyn-code/config.yml` | Project settings |
|
|
563
|
+
| `.rubyn-code/skills/*.md` | Project custom skills |
|
|
564
|
+
| `RUBYN.md` | Project instructions |
|
|
565
|
+
|
|
566
|
+
## Development
|
|
567
|
+
|
|
568
|
+
```bash
|
|
569
|
+
# Run tests
|
|
570
|
+
bundle exec rspec
|
|
571
|
+
|
|
572
|
+
# Run a specific test
|
|
573
|
+
bundle exec rspec spec/rubyn_code/agent/loop_spec.rb
|
|
574
|
+
|
|
575
|
+
# Interactive console
|
|
576
|
+
ruby -Ilib bin/console
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
## Project Structure
|
|
580
|
+
|
|
581
|
+
```
|
|
582
|
+
rubyn-code/
|
|
583
|
+
├── exe/rubyn-code # CLI entry point
|
|
584
|
+
├── lib/rubyn_code/
|
|
585
|
+
│ ├── agent/ # Layer 1: Core agent loop
|
|
586
|
+
│ ├── tools/ # Layer 2: 18 tool implementations
|
|
587
|
+
│ ├── permissions/ # Layer 3: Tiered access control
|
|
588
|
+
│ ├── context/ # Layer 4: Compression pipeline
|
|
589
|
+
│ ├── skills/ # Layer 5: Skill loader
|
|
590
|
+
│ ├── sub_agents/ # Layer 6: Isolated child agents
|
|
591
|
+
│ ├── tasks/ # Layer 7: Task DAG
|
|
592
|
+
│ ├── background/ # Layer 8: Async execution
|
|
593
|
+
│ ├── teams/ # Layer 9: Agent teams
|
|
594
|
+
│ ├── protocols/ # Layer 10: Coordination
|
|
595
|
+
│ ├── autonomous/ # Layer 11: KAIROS daemon
|
|
596
|
+
│ ├── memory/ # Layer 12: Persistence
|
|
597
|
+
│ ├── observability/ # Layer 13: Cost tracking
|
|
598
|
+
│ ├── hooks/ # Layer 14: Event system
|
|
599
|
+
│ ├── mcp/ # Layer 15: MCP client
|
|
600
|
+
│ ├── learning/ # Layer 16: Continuous learning
|
|
601
|
+
│ ├── llm/ # Claude API client (OAuth + API key)
|
|
602
|
+
│ ├── auth/ # Token management (Keychain + file + env)
|
|
603
|
+
│ ├── db/ # SQLite connection & migrations
|
|
604
|
+
│ ├── cli/ # REPL, input handling, rendering
|
|
605
|
+
│ └── config/ # Settings management
|
|
606
|
+
├── skills/ # 112 Ruby/Rails best practice docs
|
|
607
|
+
│ ├── ruby/ # Ruby language patterns
|
|
608
|
+
│ ├── rails/ # Rails framework conventions
|
|
609
|
+
│ ├── rspec/ # RSpec testing patterns
|
|
610
|
+
│ ├── design_patterns/ # GoF and Ruby patterns
|
|
611
|
+
│ ├── solid/ # SOLID principles
|
|
612
|
+
│ ├── refactoring/ # Refactoring techniques
|
|
613
|
+
│ └── ... # + code_quality, gems, minitest, sinatra
|
|
614
|
+
├── db/migrations/ # 11 SQL migration files
|
|
615
|
+
└── spec/ # 48 RSpec test files (314 examples)
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
## License
|
|
619
|
+
|
|
620
|
+
MIT
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
CREATE TABLE IF NOT EXISTS sessions (
|
|
2
|
+
id TEXT PRIMARY KEY,
|
|
3
|
+
project_path TEXT NOT NULL,
|
|
4
|
+
title TEXT,
|
|
5
|
+
status TEXT NOT NULL DEFAULT 'active' CHECK(status IN ('active','paused','completed')),
|
|
6
|
+
model TEXT NOT NULL DEFAULT 'claude-sonnet-4-20250514',
|
|
7
|
+
total_input_tokens INTEGER NOT NULL DEFAULT 0,
|
|
8
|
+
total_output_tokens INTEGER NOT NULL DEFAULT 0,
|
|
9
|
+
total_cost_usd REAL NOT NULL DEFAULT 0.0,
|
|
10
|
+
metadata TEXT DEFAULT '{}',
|
|
11
|
+
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ','now')),
|
|
12
|
+
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ','now'))
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
CREATE INDEX IF NOT EXISTS idx_sessions_project ON sessions(project_path);
|
|
16
|
+
CREATE INDEX IF NOT EXISTS idx_sessions_status ON sessions(status);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
CREATE TABLE IF NOT EXISTS messages (
|
|
2
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
3
|
+
session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
4
|
+
role TEXT NOT NULL CHECK(role IN ('system','user','assistant')),
|
|
5
|
+
content TEXT,
|
|
6
|
+
tool_calls TEXT,
|
|
7
|
+
tool_use_id TEXT,
|
|
8
|
+
tool_name TEXT,
|
|
9
|
+
token_count INTEGER,
|
|
10
|
+
is_compacted INTEGER NOT NULL DEFAULT 0,
|
|
11
|
+
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ','now'))
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
CREATE INDEX IF NOT EXISTS idx_messages_session ON messages(session_id);
|
|
15
|
+
CREATE INDEX IF NOT EXISTS idx_messages_role ON messages(session_id, role);
|
|
16
|
+
CREATE INDEX IF NOT EXISTS idx_messages_tool_use ON messages(tool_use_id);
|