reposer 1.3.0 โ†’ 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f0dac6cfdb3aabf4d7ac21336a8418b2ccc4d5915f461741d5fda5d2e1c3249e
4
- data.tar.gz: 40af3f7d39bf3d483c8746f94a6f8cc2dc458cd828aaa0c915f19feaea6bd208
3
+ metadata.gz: cfd38b233b7fb95d221618d58a19a306959e91896d96990c93e530411037bdb2
4
+ data.tar.gz: 71d6f80d183f237f42a5c6745c1991d02be0fe9445f78e5aa27b243da4127d85
5
5
  SHA512:
6
- metadata.gz: 6987ccdfcf352db9513bf43dd633423cf436b6552e473f044e9e4458aa1123967d854797bd58edf313d1330509345750d07aa7639c8ed14f17592943bd21b796
7
- data.tar.gz: a2459ea73a170297b74f4ef5487a4486ed674c0af182332cfb3ea0a642634f4f1462a37a2bb95433197f1e3686e19b7638e8dc1ee4fc86fcb5722f63f366996d
6
+ metadata.gz: 1d0e5a6272c2911ea0bec13e4bcdcf33fe2e03348ba8e377b10d8ba2d003820638015d483719cfb8930fd111ea3383ff4be04d4524261d465015705c6a04958b
7
+ data.tar.gz: 31452633c4d6e016ac658625a3211d93a5ca66d649259a100745c66cc2bb29f6020dfa6de6a7ecccc02542e1a2422410cb3f07a247b319dcb8184f6480b48a2f
data/AGENTS.md ADDED
@@ -0,0 +1,109 @@
1
+ # CLAUDE.md โ€” Project Conventions & AI Collaboration Guidelines
2
+
3
+ This file defines standing instructions for Claude when working on any project in this repository. Always read and follow these rules before writing, modifying, or deleting any code or documentation.
4
+
5
+ ---
6
+
7
+ ## ๐Ÿ—‚๏ธ Planning First
8
+
9
+ - **Always read `PLAN.md`, `ROADMAP.md`, or equivalent planning docs before starting any task.**
10
+ - Identify the relevant phase, step, or milestone before writing or modifying any code.
11
+ - If no plan exists, create one before proceeding and ask for confirmation.
12
+ - After completing work, update `PLAN.md`, `ROADMAP.md`, `README.md`, and any relevant docs to reflect what changed, what's done, and what's next.
13
+ - If a task deviates from the current plan, call it out explicitly before continuing.
14
+
15
+ ---
16
+
17
+ ## ๐Ÿงฑ Code Quality
18
+
19
+ - **All written code must be production-grade at all times.** No placeholders, no "good enough for now," no TODOs left in shipped code.
20
+ - Follow the language's idiomatic style and best practices (e.g., Rust ownership patterns, Python type hints, Go error handling).
21
+ - Prefer explicit over implicit. Avoid magic values โ€” use named constants.
22
+ - Keep functions small, focused, and single-responsibility.
23
+ - Handle all error cases. Never silently swallow errors.
24
+ - Avoid code duplication. Extract shared logic into reusable utilities or modules.
25
+ - Add inline comments only where intent is non-obvious. Code should be self-documenting first.
26
+
27
+ ---
28
+
29
+ ## ๐Ÿงช Testing
30
+
31
+ - **100% test coverage is required.** Every code file must have a corresponding test file.
32
+ - Tests live alongside their source file or in a dedicated `tests/` directory โ€” be consistent with the project's convention.
33
+ - Write unit tests for all functions, integration tests for module interactions, and end-to-end tests where applicable.
34
+ - Tests must be deterministic. No flaky tests, no time-dependent assertions without mocking.
35
+ - All tests must pass before committing. Never commit with known failing tests.
36
+ - Use table-driven or parameterized tests for functions with multiple input/output cases.
37
+ - Test edge cases, error paths, and boundary conditions โ€” not just the happy path.
38
+
39
+ ---
40
+
41
+ ## ๐Ÿ–ฅ๏ธ Command Output
42
+
43
+ - **Never suppress command output.** Do not use `2>/dev/null`, `2>&1`, `--quiet`, `-q`, or any flag that hides stderr/stdout unless the user explicitly requests it.
44
+ - All command output must be visible so failures, hangs, warnings, and progress can be assessed in real time.
45
+ - If a command is long-running, prefer flags that show progress (e.g., `--verbose`, `-v`) where available.
46
+ - If a command hangs, report it โ€” do not silently wait indefinitely.
47
+
48
+ ---
49
+
50
+ ## ๐Ÿ” Git Workflow
51
+
52
+ - **At the end of every completed prompt, if all tests pass: `git add`, `git commit`, and `git push`.**
53
+ - Write clear, imperative commit messages that describe *what* and *why*:
54
+ - โœ… `feat(inference): add KV cache eviction strategy for M3 memory pressure`
55
+ - โŒ `updates`, `fix stuff`, `WIP`
56
+ - Follow [Conventional Commits](https://www.conventionalcommits.org/) format: `type(scope): description`
57
+ - Types: `feat`, `fix`, `refactor`, `test`, `docs`, `chore`, `perf`, `ci`
58
+ - Never force-push to `main` or `master` without explicit instruction.
59
+ - Commit logical units of work โ€” don't bundle unrelated changes in one commit.
60
+
61
+ ---
62
+
63
+ ## ๐Ÿ“ File & Project Structure
64
+
65
+ - Follow the existing project structure. Do not reorganize directories without discussing it first.
66
+ - New modules, crates, or packages should match the naming convention already in use.
67
+ - Keep config, secrets, and environment-specific values out of source code. Use `.env` files or environment variables, and ensure `.gitignore` is up to date.
68
+ - Delete dead code. Don't comment it out and leave it โ€” use version control for history.
69
+
70
+ ---
71
+
72
+ ## ๐Ÿ“ Documentation
73
+
74
+ - Update `README.md` whenever public-facing behavior, setup steps, or architecture changes.
75
+ - Update `PLAN.md` / `ROADMAP.md` after every session โ€” mark completed items, add new findings, note blockers.
76
+ - Document all public APIs, functions, and types with docstrings/doc comments appropriate to the language.
77
+ - If a non-obvious architectural decision is made, add an `ADR` (Architecture Decision Record) entry or a note in the relevant doc.
78
+
79
+ ---
80
+
81
+ ## ๐Ÿ” Before You Build
82
+
83
+ Before writing any code, confirm:
84
+ 1. โœ… You've read the relevant plan/phase/step.
85
+ 2. โœ… You understand what "done" looks like for this task.
86
+ 3. โœ… You know where the new code lives in the project structure.
87
+ 4. โœ… You know what tests will prove it works.
88
+ 5. โœ… You know what docs need updating when it's done.
89
+
90
+ If any of these are unclear, ask before proceeding.
91
+
92
+ ---
93
+
94
+ ## ๐Ÿšซ Hard Stops
95
+
96
+ Do not proceed if:
97
+ - Tests are failing from a previous step (fix them first).
98
+ - The plan is ambiguous or missing for a non-trivial task.
99
+ - A change would break a public API or interface without a migration path.
100
+ - A required dependency is unavailable or untested on the target platform.
101
+
102
+ ---
103
+
104
+ ## ๐Ÿง  General Mindset
105
+
106
+ - Prefer boring, correct, and maintainable over clever.
107
+ - When in doubt, do less and confirm โ€” don't assume scope.
108
+ - Surface trade-offs and alternatives when they exist; don't just pick one silently.
109
+ - Treat every PR as if a senior engineer on the team will review it.
data/CHANGELOG.md CHANGED
@@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.4.0] - 2026-03-11
11
+
12
+ ### Added
13
+ - **Organization & Namespace Selection**: Choose where to create a new repository
14
+ - Fetches the authenticated user's personal account and all GitHub organization memberships via the API
15
+ - Presents an interactive `Create repository under:` selection prompt when multiple namespaces are available
16
+ - Automatically skips the prompt when the user has no org memberships (personal account only)
17
+ - New `--org ORG` CLI flag to specify the destination directly (bypasses the prompt for scripted use)
18
+ - Gracefully falls back to personal account if namespace fetching fails
19
+ - Preview output now shows `Destination: owner/repo-name` so the target is visible before confirming
20
+ - **`GitHubClient#available_namespaces`**: New public method returning personal + org namespaces
21
+ - **`GitHubClient#repository_exists?`**: Now accepts an optional `owner` parameter
22
+
23
+ ### Changed
24
+ - `GitHubClient#create_repository` accepts a new `owner:` keyword argument; passes `organization:` to the GitHub API when creating under an org
25
+
10
26
  ## [1.3.0] - 2025-11-21
11
27
 
12
28
  ### Added
data/CLAUDE.md ADDED
@@ -0,0 +1,109 @@
1
+ # CLAUDE.md โ€” Project Conventions & AI Collaboration Guidelines
2
+
3
+ This file defines standing instructions for Claude when working on any project in this repository. Always read and follow these rules before writing, modifying, or deleting any code or documentation.
4
+
5
+ ---
6
+
7
+ ## ๐Ÿ—‚๏ธ Planning First
8
+
9
+ - **Always read `PLAN.md`, `ROADMAP.md`, or equivalent planning docs before starting any task.**
10
+ - Identify the relevant phase, step, or milestone before writing or modifying any code.
11
+ - If no plan exists, create one before proceeding and ask for confirmation.
12
+ - After completing work, update `PLAN.md`, `ROADMAP.md`, `README.md`, and any relevant docs to reflect what changed, what's done, and what's next.
13
+ - If a task deviates from the current plan, call it out explicitly before continuing.
14
+
15
+ ---
16
+
17
+ ## ๐Ÿงฑ Code Quality
18
+
19
+ - **All written code must be production-grade at all times.** No placeholders, no "good enough for now," no TODOs left in shipped code.
20
+ - Follow the language's idiomatic style and best practices (e.g., Rust ownership patterns, Python type hints, Go error handling).
21
+ - Prefer explicit over implicit. Avoid magic values โ€” use named constants.
22
+ - Keep functions small, focused, and single-responsibility.
23
+ - Handle all error cases. Never silently swallow errors.
24
+ - Avoid code duplication. Extract shared logic into reusable utilities or modules.
25
+ - Add inline comments only where intent is non-obvious. Code should be self-documenting first.
26
+
27
+ ---
28
+
29
+ ## ๐Ÿงช Testing
30
+
31
+ - **100% test coverage is required.** Every code file must have a corresponding test file.
32
+ - Tests live alongside their source file or in a dedicated `tests/` directory โ€” be consistent with the project's convention.
33
+ - Write unit tests for all functions, integration tests for module interactions, and end-to-end tests where applicable.
34
+ - Tests must be deterministic. No flaky tests, no time-dependent assertions without mocking.
35
+ - All tests must pass before committing. Never commit with known failing tests.
36
+ - Use table-driven or parameterized tests for functions with multiple input/output cases.
37
+ - Test edge cases, error paths, and boundary conditions โ€” not just the happy path.
38
+
39
+ ---
40
+
41
+ ## ๐Ÿ–ฅ๏ธ Command Output
42
+
43
+ - **Never suppress command output.** Do not use `2>/dev/null`, `2>&1`, `--quiet`, `-q`, or any flag that hides stderr/stdout unless the user explicitly requests it.
44
+ - All command output must be visible so failures, hangs, warnings, and progress can be assessed in real time.
45
+ - If a command is long-running, prefer flags that show progress (e.g., `--verbose`, `-v`) where available.
46
+ - If a command hangs, report it โ€” do not silently wait indefinitely.
47
+
48
+ ---
49
+
50
+ ## ๐Ÿ” Git Workflow
51
+
52
+ - **At the end of every completed prompt, if all tests pass: `git add`, `git commit`, and `git push`.**
53
+ - Write clear, imperative commit messages that describe *what* and *why*:
54
+ - โœ… `feat(inference): add KV cache eviction strategy for M3 memory pressure`
55
+ - โŒ `updates`, `fix stuff`, `WIP`
56
+ - Follow [Conventional Commits](https://www.conventionalcommits.org/) format: `type(scope): description`
57
+ - Types: `feat`, `fix`, `refactor`, `test`, `docs`, `chore`, `perf`, `ci`
58
+ - Never force-push to `main` or `master` without explicit instruction.
59
+ - Commit logical units of work โ€” don't bundle unrelated changes in one commit.
60
+
61
+ ---
62
+
63
+ ## ๐Ÿ“ File & Project Structure
64
+
65
+ - Follow the existing project structure. Do not reorganize directories without discussing it first.
66
+ - New modules, crates, or packages should match the naming convention already in use.
67
+ - Keep config, secrets, and environment-specific values out of source code. Use `.env` files or environment variables, and ensure `.gitignore` is up to date.
68
+ - Delete dead code. Don't comment it out and leave it โ€” use version control for history.
69
+
70
+ ---
71
+
72
+ ## ๐Ÿ“ Documentation
73
+
74
+ - Update `README.md` whenever public-facing behavior, setup steps, or architecture changes.
75
+ - Update `PLAN.md` / `ROADMAP.md` after every session โ€” mark completed items, add new findings, note blockers.
76
+ - Document all public APIs, functions, and types with docstrings/doc comments appropriate to the language.
77
+ - If a non-obvious architectural decision is made, add an `ADR` (Architecture Decision Record) entry or a note in the relevant doc.
78
+
79
+ ---
80
+
81
+ ## ๐Ÿ” Before You Build
82
+
83
+ Before writing any code, confirm:
84
+ 1. โœ… You've read the relevant plan/phase/step.
85
+ 2. โœ… You understand what "done" looks like for this task.
86
+ 3. โœ… You know where the new code lives in the project structure.
87
+ 4. โœ… You know what tests will prove it works.
88
+ 5. โœ… You know what docs need updating when it's done.
89
+
90
+ If any of these are unclear, ask before proceeding.
91
+
92
+ ---
93
+
94
+ ## ๐Ÿšซ Hard Stops
95
+
96
+ Do not proceed if:
97
+ - Tests are failing from a previous step (fix them first).
98
+ - The plan is ambiguous or missing for a non-trivial task.
99
+ - A change would break a public API or interface without a migration path.
100
+ - A required dependency is unavailable or untested on the target platform.
101
+
102
+ ---
103
+
104
+ ## ๐Ÿง  General Mindset
105
+
106
+ - Prefer boring, correct, and maintainable over clever.
107
+ - When in doubt, do less and confirm โ€” don't assume scope.
108
+ - Surface trade-offs and alternatives when they exist; don't just pick one silently.
109
+ - Treat every PR as if a senior engineer on the team will review it.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- reposer (1.2.0)
4
+ reposer (1.4.0)
5
5
  faraday (~> 2.0)
6
6
  octokit (~> 6.0)
7
7
  ostruct (~> 0.6)
data/README.md CHANGED
@@ -20,6 +20,7 @@ Reposer is an intelligent CLI tool that uses AI to create GitHub repositories wi
20
20
  - **๐Ÿท๏ธ 20 Intelligent Topics**: Generates up to 20 relevant tags and topics automatically
21
21
  - **๐Ÿ˜Š Emoji Support**: Automatic emoji inclusion in descriptions and READMEs for visual appeal
22
22
  - **๐Ÿ“„ License Selection**: Interactive license picker (MIT, Apache, GPL, BSD, MPL, Unlicense)
23
+ - **๐Ÿข Organization Support**: Choose to create repos under your personal account or any GitHub org you belong to
23
24
  - **๐Ÿ—‚๏ธ Language-Specific Project Files**: Auto-generates boilerplate files (go.mod, package.json, requirements.txt, etc.)
24
25
  - **๐Ÿ‘๏ธ Preview Mode**: See generated content before creating repository
25
26
  - **๐Ÿ” Secure Configuration**: Encrypted storage of API keys and tokens
@@ -112,6 +113,12 @@ reposer create ai-chatbot --language python --framework fastapi --dry-run
112
113
  # Specify license type
113
114
  reposer create api-server --language go --framework gin --license apache-2.0
114
115
 
116
+ # Create under a GitHub organization
117
+ reposer create team-tool --language ruby --org my-company
118
+
119
+ # Create under an org with full options
120
+ reposer create infra-scripts --language python --org devops-team --private --license mit
121
+
115
122
  # Custom description and topics
116
123
  reposer create data-processor \
117
124
  --language python \
@@ -127,6 +134,7 @@ reposer create blog-api --language ruby --framework rails --license gpl-3.0 --pr
127
134
  $ reposer create awesome-api
128
135
  ๐ŸŽฏ Reposer - AI Repository Creator
129
136
  ========================================
137
+ Create repository under: yourusername (personal)
130
138
  Primary programming language: ruby
131
139
  Framework/Library: Rails
132
140
  Choose a license: MIT License (Permissive, most popular)
@@ -134,6 +142,7 @@ What will this project do? A REST API for user management
134
142
 
135
143
  ๐Ÿ“‹ Generated Repository Content
136
144
  ----------------------------------------
145
+ Destination: yourusername/awesome-api
137
146
  Name: awesome-api
138
147
  Description: ๐Ÿš€ A Ruby Rails REST API for user management ๐Ÿ’Ž
139
148
  Topics: ruby, rails, api, rest, web, backend, database, authentication,
@@ -204,9 +213,10 @@ Create a new repository with AI assistance.
204
213
 
205
214
  **Options:**
206
215
  - `--language LANG` - Primary programming language
207
- - `--framework FRAMEWORK` - Framework or library to use
216
+ - `--framework FRAMEWORK` - Framework or library to use
208
217
  - `--description TEXT` - Custom description override
209
218
  - `--license LICENSE` - License type (mit, apache-2.0, gpl-3.0, bsd-3-clause, mpl-2.0, unlicense)
219
+ - `--org ORG` - GitHub organization or user login to create the repository under (skips interactive selection)
210
220
  - `--private` - Create private repository (default: public)
211
221
  - `--topics TOPIC1,TOPIC2` - Custom topics/tags (up to 20)
212
222
  - `--dry-run` - Preview without creating
@@ -218,6 +228,7 @@ reposer create web-app --language typescript --framework react
218
228
  reposer create microservice --language go --license apache-2.0 --private
219
229
  reposer create ml-model --language python --topics ml,ai,data-science --dry-run
220
230
  reposer create api-server --language ruby --framework rails --license gpl-3.0
231
+ reposer create team-tool --language python --org my-company
221
232
  ```
222
233
 
223
234
  ### `repose configure`
data/lib/repose/cli.rb CHANGED
@@ -21,6 +21,7 @@ module Repose
21
21
  $ repose create my-awesome-project
22
22
  $ repose create web-scraper --language ruby --framework rails
23
23
  $ repose create api-server --license apache-2.0
24
+ $ repose create team-tool --org my-org
24
25
  DESC
25
26
  option :language, type: :string, desc: "Primary programming language"
26
27
  option :framework, type: :string, desc: "Framework or library to use"
@@ -30,6 +31,7 @@ module Repose
30
31
  option :topics, type: :array, desc: "Custom topics/tags"
31
32
  option :license, type: :string, desc: "License type (mit, apache-2.0, gpl-3.0, bsd-3-clause, unlicense, etc.)"
32
33
  option :dry_run, type: :boolean, default: false, desc: "Preview without creating"
34
+ option :org, type: :string, desc: "Organization or user login to create the repository under (skips interactive selection)"
33
35
  def create(name = nil)
34
36
  pastel = Pastel.new
35
37
  prompt = TTY::Prompt.new
@@ -42,9 +44,12 @@ module Repose
42
44
  q.validate(/\A[a-zA-Z0-9._-]+\z/, "Invalid repository name format")
43
45
  end
44
46
 
47
+ # Determine the owner (org or personal account)
48
+ owner = options[:org] || select_namespace(prompt, pastel)
49
+
45
50
  # Gather context
46
51
  context = gather_context(name, options, prompt)
47
-
52
+
48
53
  # Generate AI content
49
54
  spinner = TTY::Spinner.new("[:spinner] Generating repository content with AI...", format: :dots)
50
55
  spinner.auto_spin
@@ -59,12 +64,12 @@ module Repose
59
64
  end
60
65
 
61
66
  # Display preview
62
- display_preview(ai_content, pastel)
67
+ display_preview(ai_content, pastel, owner)
63
68
 
64
69
  # Confirm creation
65
70
  unless options[:dry_run]
66
71
  if prompt.yes?("Create repository?")
67
- create_repository(name, ai_content, options, pastel)
72
+ create_repository(name, ai_content, options, pastel, owner)
68
73
  else
69
74
  puts pastel.yellow("Repository creation cancelled.")
70
75
  end
@@ -98,6 +103,25 @@ module Repose
98
103
 
99
104
  private
100
105
 
106
+ # Fetches the authenticated user's personal account and all orgs they belong
107
+ # to, then prompts the user to choose where to create the new repository.
108
+ # Returns nil (personal account default) when there is only one namespace
109
+ # available or when the namespace list cannot be fetched.
110
+ def select_namespace(prompt, pastel)
111
+ github_client = GitHubClient.new
112
+ namespaces = github_client.available_namespaces
113
+
114
+ # No choice needed when the user has no org memberships
115
+ return nil if namespaces.size == 1
116
+
117
+ selected = prompt.select("Create repository under:", namespaces)
118
+ # nil signals "personal account" to create_repository
119
+ selected == namespaces.first[:value] ? nil : selected
120
+ rescue Errors::AuthenticationError, Errors::GitHubError => e
121
+ puts pastel.yellow("Warning: could not fetch organizations (#{e.message}). Defaulting to personal account.")
122
+ nil
123
+ end
124
+
101
125
  def gather_context(name, options, prompt)
102
126
  context = {
103
127
  name: name,
@@ -134,7 +158,7 @@ module Repose
134
158
  { name: "Other/Custom", value: "other" }
135
159
  ]
136
160
  context[:license] = prompt.select("Choose a license:", licenses)
137
-
161
+
138
162
  if context[:license] == "other"
139
163
  context[:license] = prompt.ask("Enter license name:", default: "MIT")
140
164
  end
@@ -142,7 +166,7 @@ module Repose
142
166
 
143
167
  # Additional context
144
168
  context[:purpose] = prompt.ask("What will this project do? (optional):")
145
-
169
+
146
170
  context
147
171
  end
148
172
 
@@ -167,21 +191,23 @@ module Repose
167
191
  frameworks[language] || []
168
192
  end
169
193
 
170
- def display_preview(content, pastel)
194
+ def display_preview(content, pastel, owner = nil)
171
195
  puts "\n" + pastel.cyan("๐Ÿ“‹ Generated Repository Content")
172
196
  puts pastel.dim("-" * 40)
173
-
197
+
198
+ destination = owner ? "#{owner}/#{content[:name]}" : content[:name]
199
+ puts pastel.bold("Destination: ") + destination
174
200
  puts pastel.bold("Name: ") + content[:name]
175
201
  puts pastel.bold("Description: ") + content[:description]
176
202
  puts pastel.bold("License: ") + (content[:license] || "MIT").upcase
177
203
  puts pastel.bold("Topics: ") + content[:topics].join(", ")
178
-
204
+
179
205
  puts "\n" + pastel.bold("README Preview:")
180
206
  puts pastel.dim(content[:readme][0..300] + "...")
181
207
  puts
182
208
  end
183
209
 
184
- def create_repository(name, content, options, pastel)
210
+ def create_repository(name, content, options, pastel, owner = nil)
185
211
  spinner = TTY::Spinner.new("[:spinner] Creating GitHub repository...", format: :dots)
186
212
  spinner.auto_spin
187
213
 
@@ -193,22 +219,23 @@ module Repose
193
219
  private: options[:private],
194
220
  topics: content[:topics],
195
221
  readme: content[:readme],
196
- license: content[:license]
222
+ license: content[:license],
223
+ owner: owner
197
224
  )
198
-
225
+
199
226
  spinner.success("โœ…")
200
-
227
+
201
228
  # Create language-specific project files
202
229
  project_files = ProjectFilesGenerator.generate(
203
230
  language: content[:language],
204
231
  framework: content[:framework],
205
232
  name: name
206
233
  )
207
-
234
+
208
235
  if project_files.any?
209
236
  file_spinner = TTY::Spinner.new("[:spinner] Adding project files...", format: :dots)
210
237
  file_spinner.auto_spin
211
-
238
+
212
239
  project_files.each do |file_path, file_content|
213
240
  github_client.create_file(
214
241
  repo.full_name,
@@ -217,10 +244,10 @@ module Repose
217
244
  file_content
218
245
  )
219
246
  end
220
-
247
+
221
248
  file_spinner.success("โœ…")
222
249
  end
223
-
250
+
224
251
  puts pastel.green("Repository created successfully!")
225
252
  puts pastel.cyan("๐Ÿ”— #{repo.html_url}")
226
253
  rescue => e
@@ -230,4 +257,4 @@ module Repose
230
257
  end
231
258
  end
232
259
  end
233
- end
260
+ end
data/lib/repose/errors.rb CHANGED
@@ -4,14 +4,16 @@ module Repose
4
4
  module Errors
5
5
  class Error < StandardError; end
6
6
  class ConfigError < Error; end
7
+ class ConfigurationError < Error; end
7
8
  class GitHubError < Error; end
9
+ class AuthenticationError < Error; end
8
10
  class AIError < Error; end
9
11
  class ValidationError < Error; end
10
12
  end
11
13
 
12
- # Convenience aliases for AI providers
13
- ConfigurationError = Errors::ConfigError
14
+ # Convenience aliases for AI providers at module level
15
+ ConfigurationError = Errors::ConfigurationError
14
16
  APIError = Errors::AIError
15
- AuthenticationError = Errors::AIError
17
+ AuthenticationError = Errors::AuthenticationError
16
18
  RateLimitError = Errors::AIError
17
19
  end
@@ -5,16 +5,34 @@ require "octokit"
5
5
  module Repose
6
6
  class GitHubClient
7
7
  def initialize
8
- token = Repose.config.github_token || ENV["GITHUB_TOKEN"]
9
-
10
- raise Errors::ConfigurationError, "GitHub token not configured. Set GITHUB_TOKEN environment variable or run 'repose configure'" if token.nil? || token.empty?
11
-
8
+ token = Repose.config.github_token || ENV["REPOSE_TOKEN"]
9
+
10
+ raise Errors::ConfigurationError, "GitHub token not configured. Set REPOSE_TOKEN environment variable or run 'repose configure'" if token.nil? || token.empty?
11
+
12
12
  @client = Octokit::Client.new(access_token: token)
13
13
  @client.auto_paginate = true
14
14
  end
15
15
 
16
- def create_repository(name:, description:, private: false, topics: [], readme: nil, license: nil)
17
- # Create the repository with license template if specified
16
+ # Returns an array of namespace hashes (personal account + orgs) the
17
+ # authenticated user can create repositories under. Each element has the
18
+ # shape: { name: "display label", value: "login" }.
19
+ def available_namespaces
20
+ user = @client.user
21
+ orgs = @client.organizations
22
+
23
+ namespaces = [{ name: "#{user.login} (personal)", value: user.login }]
24
+ orgs.each do |org|
25
+ namespaces << { name: org.login, value: org.login }
26
+ end
27
+
28
+ namespaces
29
+ rescue Octokit::Unauthorized => e
30
+ raise Errors::AuthenticationError, "GitHub authentication failed: #{e.message}"
31
+ rescue Octokit::Error => e
32
+ raise Errors::GitHubError, "Failed to fetch organizations: #{e.message}"
33
+ end
34
+
35
+ def create_repository(name:, description:, private: false, topics: [], readme: nil, license: nil, owner: nil)
18
36
  repo_options = {
19
37
  description: description,
20
38
  private: private,
@@ -23,12 +41,17 @@ module Repose
23
41
  has_wiki: true,
24
42
  has_projects: true
25
43
  }
26
-
44
+
27
45
  # Add license template if specified
28
46
  if license && !license.empty?
29
47
  repo_options[:license_template] = normalize_license_key(license)
30
48
  end
31
-
49
+
50
+ # Create under an org when the owner differs from the authenticated user
51
+ unless owner.nil? || owner.empty? || owner == current_user_login
52
+ repo_options[:organization] = owner
53
+ end
54
+
32
55
  repo = @client.create_repository(name, repo_options)
33
56
 
34
57
  # Add topics if provided
@@ -56,9 +79,9 @@ module Repose
56
79
  raise Errors::GitHubError, "GitHub API error: #{e.message}"
57
80
  end
58
81
 
59
- def repository_exists?(name)
60
- username = @client.user.login
61
- @client.repository?("#{username}/#{name}")
82
+ def repository_exists?(name, owner = nil)
83
+ namespace = owner || current_user_login
84
+ @client.repository?("#{namespace}/#{name}")
62
85
  rescue Octokit::NotFound
63
86
  false
64
87
  rescue Octokit::Unauthorized => e
@@ -89,6 +112,10 @@ module Repose
89
112
 
90
113
  private
91
114
 
115
+ def current_user_login
116
+ @current_user_login ||= @client.user.login
117
+ end
118
+
92
119
  def normalize_license_key(license)
93
120
  # GitHub API uses specific license keys
94
121
  license_map = {
@@ -103,9 +130,9 @@ module Repose
103
130
  "mpl-2.0" => "mpl-2.0",
104
131
  "unlicense" => "unlicense"
105
132
  }
106
-
133
+
107
134
  normalized = license_map[license.downcase] || license.downcase
108
135
  normalized
109
136
  end
110
137
  end
111
- end
138
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Repose
4
- VERSION = "1.3.0"
4
+ VERSION = "1.4.0"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reposer
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Wesley Scholl
@@ -133,7 +133,9 @@ files:
133
133
  - ".rspec"
134
134
  - ".rubocop.yml"
135
135
  - ".ruby-version"
136
+ - AGENTS.md
136
137
  - CHANGELOG.md
138
+ - CLAUDE.md
137
139
  - Gemfile
138
140
  - Gemfile.lock
139
141
  - LICENSE