codrsync 1.0.0__tar.gz

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.
Files changed (57) hide show
  1. codrsync-1.0.0/PKG-INFO +166 -0
  2. codrsync-1.0.0/README.md +127 -0
  3. codrsync-1.0.0/codrsync/__init__.py +9 -0
  4. codrsync-1.0.0/codrsync/__main__.py +6 -0
  5. codrsync-1.0.0/codrsync/ai/__init__.py +9 -0
  6. codrsync-1.0.0/codrsync/ai/backend.py +252 -0
  7. codrsync-1.0.0/codrsync/ai/build.py +582 -0
  8. codrsync-1.0.0/codrsync/ai/kickstart.py +416 -0
  9. codrsync-1.0.0/codrsync/ai/prp.py +545 -0
  10. codrsync-1.0.0/codrsync/auth.py +164 -0
  11. codrsync-1.0.0/codrsync/cli.py +427 -0
  12. codrsync-1.0.0/codrsync/cloud/__init__.py +5 -0
  13. codrsync-1.0.0/codrsync/cloud/storage.py +301 -0
  14. codrsync-1.0.0/codrsync/cloud_auth.py +155 -0
  15. codrsync-1.0.0/codrsync/config.py +182 -0
  16. codrsync-1.0.0/codrsync/connect/__init__.py +13 -0
  17. codrsync-1.0.0/codrsync/connect/base.py +44 -0
  18. codrsync-1.0.0/codrsync/connect/connect.py +155 -0
  19. codrsync-1.0.0/codrsync/connect/digitalocean.py +42 -0
  20. codrsync-1.0.0/codrsync/connect/github.py +92 -0
  21. codrsync-1.0.0/codrsync/connect/mcp.py +82 -0
  22. codrsync-1.0.0/codrsync/connect/supabase.py +75 -0
  23. codrsync-1.0.0/codrsync/connect/tailwind.py +109 -0
  24. codrsync-1.0.0/codrsync/connect/vercel.py +82 -0
  25. codrsync-1.0.0/codrsync/i18n/__init__.py +104 -0
  26. codrsync-1.0.0/codrsync/i18n/lazy.py +38 -0
  27. codrsync-1.0.0/codrsync/i18n/loader.py +53 -0
  28. codrsync-1.0.0/codrsync/i18n/strings.py +1268 -0
  29. codrsync-1.0.0/codrsync/i18n/translator.py +95 -0
  30. codrsync-1.0.0/codrsync/local/__init__.py +10 -0
  31. codrsync-1.0.0/codrsync/local/export.py +283 -0
  32. codrsync-1.0.0/codrsync/local/roadmap.py +226 -0
  33. codrsync-1.0.0/codrsync/local/sprint.py +324 -0
  34. codrsync-1.0.0/codrsync/local/status.py +220 -0
  35. codrsync-1.0.0/codrsync/next_steps.py +33 -0
  36. codrsync-1.0.0/codrsync/onboarding.py +122 -0
  37. codrsync-1.0.0/codrsync/scanner/__init__.py +21 -0
  38. codrsync-1.0.0/codrsync/scanner/context_generator.py +117 -0
  39. codrsync-1.0.0/codrsync/scanner/detector.py +282 -0
  40. codrsync-1.0.0/codrsync/scanner/doc_scanner.py +79 -0
  41. codrsync-1.0.0/codrsync/scanner/github_scanner.py +101 -0
  42. codrsync-1.0.0/codrsync/scanner/scan.py +160 -0
  43. codrsync-1.0.0/codrsync/utils/__init__.py +7 -0
  44. codrsync-1.0.0/codrsync/utils/doctor.py +128 -0
  45. codrsync-1.0.0/codrsync.egg-info/PKG-INFO +166 -0
  46. codrsync-1.0.0/codrsync.egg-info/SOURCES.txt +55 -0
  47. codrsync-1.0.0/codrsync.egg-info/dependency_links.txt +1 -0
  48. codrsync-1.0.0/codrsync.egg-info/entry_points.txt +2 -0
  49. codrsync-1.0.0/codrsync.egg-info/requires.txt +14 -0
  50. codrsync-1.0.0/codrsync.egg-info/top_level.txt +3 -0
  51. codrsync-1.0.0/pyproject.toml +72 -0
  52. codrsync-1.0.0/setup.cfg +4 -0
  53. codrsync-1.0.0/tests/__init__.py +1 -0
  54. codrsync-1.0.0/tests/conftest.py +85 -0
  55. codrsync-1.0.0/tests/test_cli.py +141 -0
  56. codrsync-1.0.0/tests/test_config.py +90 -0
  57. codrsync-1.0.0/tests/test_detector.py +108 -0
@@ -0,0 +1,166 @@
1
+ Metadata-Version: 2.4
2
+ Name: codrsync
3
+ Version: 1.0.0
4
+ Summary: Turn any dev into jedi ninja codr
5
+ Author-email: Ciro Arendt <ciro@ciroarendt.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://codrsync.dev
8
+ Project-URL: Documentation, https://codrsync.dev/docs
9
+ Project-URL: Repository, https://github.com/ciroarendt/codrsync
10
+ Project-URL: Issues, https://github.com/ciroarendt/codrsync/issues
11
+ Keywords: cli,ai,development,orchestrator,claude,prp,codrsync
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Topic :: Software Development
23
+ Classifier: Topic :: Software Development :: Code Generators
24
+ Requires-Python: >=3.10
25
+ Description-Content-Type: text/markdown
26
+ Requires-Dist: typer>=0.9.0
27
+ Requires-Dist: rich>=13.0.0
28
+ Requires-Dist: anthropic>=0.18.0
29
+ Requires-Dist: pydantic>=2.0.0
30
+ Requires-Dist: python-dotenv>=1.0.0
31
+ Requires-Dist: openpyxl>=3.1.0
32
+ Requires-Dist: questionary>=2.0.0
33
+ Provides-Extra: dev
34
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
35
+ Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
36
+ Requires-Dist: black>=23.0.0; extra == "dev"
37
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
38
+ Requires-Dist: mypy>=1.0.0; extra == "dev"
39
+
40
+ # codrsync CLI
41
+
42
+ **Turn any dev into jedi ninja codr** - AI-powered development orchestrator.
43
+
44
+ ## Installation
45
+
46
+ ```bash
47
+ pip install codrsync
48
+ ```
49
+
50
+ Or from source:
51
+
52
+ ```bash
53
+ cd cli
54
+ pip install -e .
55
+ ```
56
+
57
+ ## Quick Start
58
+
59
+ ```bash
60
+ # Configure authentication (uses YOUR Claude Code or API key)
61
+ codrsync auth
62
+
63
+ # Create a new project
64
+ codrsync init
65
+
66
+ # Check project status
67
+ codrsync status
68
+
69
+ # View roadmap
70
+ codrsync roadmap
71
+
72
+ # Start a sprint
73
+ codrsync sprint start
74
+
75
+ # Export to Excel/Jira/Trello
76
+ codrsync export excel
77
+ ```
78
+
79
+ ## Commands
80
+
81
+ ### Local (work offline)
82
+
83
+ | Command | Description |
84
+ |---------|-------------|
85
+ | `codrsync status` | Show project dashboard |
86
+ | `codrsync roadmap` | Show timeline and dependencies |
87
+ | `codrsync sprint` | Manage sprints |
88
+ | `codrsync export` | Export to Excel, Jira, Trello, Notion |
89
+
90
+ ### AI-powered (use your Claude)
91
+
92
+ | Command | Description |
93
+ |---------|-------------|
94
+ | `codrsync init` | Interactive project kickstart |
95
+ | `codrsync build` | AI-guided development |
96
+ | `codrsync prp` | Manage PRPs |
97
+
98
+ ## Authentication
99
+
100
+ codrsync uses YOUR Claude Code installation or Anthropic API key.
101
+
102
+ ```bash
103
+ # Configure once
104
+ codrsync auth
105
+
106
+ # Options:
107
+ # 1. Use Claude Code (if installed) - recommended
108
+ # 2. Use Anthropic API key
109
+ # 3. Offline mode (limited features)
110
+ ```
111
+
112
+ **You pay for your own AI usage.** codrsync provides the intelligence through prompts.
113
+
114
+ ## How It Works
115
+
116
+ ```
117
+ ┌─────────────────────────────────────────────────────────────┐
118
+ │ CODRSYNC CLI │
119
+ ├─────────────────────────────────────────────────────────────┤
120
+ │ │
121
+ │ LOCAL (free, offline) AI (your Claude/API) │
122
+ │ ──────────────────── ────────────────── │
123
+ │ • status • init (kickstart) │
124
+ │ • roadmap • build (implement) │
125
+ │ • sprint • prp generate │
126
+ │ • export • research │
127
+ │ │
128
+ │ Reads JSON files Uses YOUR account │
129
+ │ No API calls You pay for usage │
130
+ │ │
131
+ └─────────────────────────────────────────────────────────────┘
132
+ ```
133
+
134
+ ## Project Structure
135
+
136
+ When you run `codrsync init`, it creates:
137
+
138
+ ```
139
+ your-project/
140
+ ├── doc/project/
141
+ │ ├── manifest.json # Project metadata
142
+ │ └── progress.json # Progress tracking
143
+ ├── doc/task/
144
+ │ └── context-session.md # Current context
145
+ ├── PRPs/ # Product Requirement Prompts
146
+ ├── src/ # Your code
147
+ ├── tests/ # Your tests
148
+ └── exports/ # Exported reports
149
+ ```
150
+
151
+ ## Diagnostics
152
+
153
+ ```bash
154
+ codrsync doctor
155
+ ```
156
+
157
+ Shows:
158
+ - Python version
159
+ - Claude Code installation
160
+ - API key status
161
+ - Current project
162
+ - Dependencies
163
+
164
+ ## License
165
+
166
+ MIT
@@ -0,0 +1,127 @@
1
+ # codrsync CLI
2
+
3
+ **Turn any dev into jedi ninja codr** - AI-powered development orchestrator.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install codrsync
9
+ ```
10
+
11
+ Or from source:
12
+
13
+ ```bash
14
+ cd cli
15
+ pip install -e .
16
+ ```
17
+
18
+ ## Quick Start
19
+
20
+ ```bash
21
+ # Configure authentication (uses YOUR Claude Code or API key)
22
+ codrsync auth
23
+
24
+ # Create a new project
25
+ codrsync init
26
+
27
+ # Check project status
28
+ codrsync status
29
+
30
+ # View roadmap
31
+ codrsync roadmap
32
+
33
+ # Start a sprint
34
+ codrsync sprint start
35
+
36
+ # Export to Excel/Jira/Trello
37
+ codrsync export excel
38
+ ```
39
+
40
+ ## Commands
41
+
42
+ ### Local (work offline)
43
+
44
+ | Command | Description |
45
+ |---------|-------------|
46
+ | `codrsync status` | Show project dashboard |
47
+ | `codrsync roadmap` | Show timeline and dependencies |
48
+ | `codrsync sprint` | Manage sprints |
49
+ | `codrsync export` | Export to Excel, Jira, Trello, Notion |
50
+
51
+ ### AI-powered (use your Claude)
52
+
53
+ | Command | Description |
54
+ |---------|-------------|
55
+ | `codrsync init` | Interactive project kickstart |
56
+ | `codrsync build` | AI-guided development |
57
+ | `codrsync prp` | Manage PRPs |
58
+
59
+ ## Authentication
60
+
61
+ codrsync uses YOUR Claude Code installation or Anthropic API key.
62
+
63
+ ```bash
64
+ # Configure once
65
+ codrsync auth
66
+
67
+ # Options:
68
+ # 1. Use Claude Code (if installed) - recommended
69
+ # 2. Use Anthropic API key
70
+ # 3. Offline mode (limited features)
71
+ ```
72
+
73
+ **You pay for your own AI usage.** codrsync provides the intelligence through prompts.
74
+
75
+ ## How It Works
76
+
77
+ ```
78
+ ┌─────────────────────────────────────────────────────────────┐
79
+ │ CODRSYNC CLI │
80
+ ├─────────────────────────────────────────────────────────────┤
81
+ │ │
82
+ │ LOCAL (free, offline) AI (your Claude/API) │
83
+ │ ──────────────────── ────────────────── │
84
+ │ • status • init (kickstart) │
85
+ │ • roadmap • build (implement) │
86
+ │ • sprint • prp generate │
87
+ │ • export • research │
88
+ │ │
89
+ │ Reads JSON files Uses YOUR account │
90
+ │ No API calls You pay for usage │
91
+ │ │
92
+ └─────────────────────────────────────────────────────────────┘
93
+ ```
94
+
95
+ ## Project Structure
96
+
97
+ When you run `codrsync init`, it creates:
98
+
99
+ ```
100
+ your-project/
101
+ ├── doc/project/
102
+ │ ├── manifest.json # Project metadata
103
+ │ └── progress.json # Progress tracking
104
+ ├── doc/task/
105
+ │ └── context-session.md # Current context
106
+ ├── PRPs/ # Product Requirement Prompts
107
+ ├── src/ # Your code
108
+ ├── tests/ # Your tests
109
+ └── exports/ # Exported reports
110
+ ```
111
+
112
+ ## Diagnostics
113
+
114
+ ```bash
115
+ codrsync doctor
116
+ ```
117
+
118
+ Shows:
119
+ - Python version
120
+ - Claude Code installation
121
+ - API key status
122
+ - Current project
123
+ - Dependencies
124
+
125
+ ## License
126
+
127
+ MIT
@@ -0,0 +1,9 @@
1
+ """
2
+ codrsync - Turn any dev into jedi ninja codr
3
+
4
+ AI-powered development orchestrator with guided development,
5
+ interactive validation, and persistent context.
6
+ """
7
+
8
+ __version__ = "1.0.0"
9
+ __author__ = "Ciro Arendt"
@@ -0,0 +1,6 @@
1
+ """Entry point for python -m codrsync"""
2
+
3
+ from codrsync.cli import app
4
+
5
+ if __name__ == "__main__":
6
+ app()
@@ -0,0 +1,9 @@
1
+ """
2
+ AI-powered commands (require Claude Code or API)
3
+ """
4
+
5
+ from codrsync.ai import kickstart
6
+ from codrsync.ai import build
7
+ from codrsync.ai import prp
8
+
9
+ __all__ = ["kickstart", "build", "prp"]
@@ -0,0 +1,252 @@
1
+ """
2
+ AI Backend abstraction - supports Claude Code CLI or Anthropic API
3
+ """
4
+
5
+ import os
6
+ import subprocess
7
+ import json
8
+ from abc import ABC, abstractmethod
9
+ from typing import Optional, Generator
10
+ from pathlib import Path
11
+
12
+ from rich.console import Console
13
+
14
+ from codrsync.auth import AIBackend
15
+
16
+
17
+ console = Console()
18
+
19
+
20
+ class AIBackendBase(ABC):
21
+ """Abstract base for AI backends"""
22
+
23
+ @abstractmethod
24
+ def run_prompt(
25
+ self,
26
+ prompt: str,
27
+ context: Optional[dict] = None,
28
+ system: Optional[str] = None,
29
+ ) -> str:
30
+ """Run a prompt and return the response"""
31
+ pass
32
+
33
+ @abstractmethod
34
+ def run_interactive(
35
+ self,
36
+ prompt: str,
37
+ context: Optional[dict] = None,
38
+ system: Optional[str] = None,
39
+ ) -> Generator[str, None, None]:
40
+ """Run an interactive session, yielding responses"""
41
+ pass
42
+
43
+ def run_conversation(
44
+ self,
45
+ messages: list[dict],
46
+ system: Optional[str] = None,
47
+ ) -> str:
48
+ """Run a multi-turn conversation. Default: use last user message as prompt."""
49
+ last_user = ""
50
+ for msg in reversed(messages):
51
+ if msg.get("role") == "user":
52
+ last_user = msg["content"]
53
+ break
54
+ return self.run_prompt(last_user, system=system)
55
+
56
+
57
+ class ClaudeCodeBackend(AIBackendBase):
58
+ """Uses Claude Code CLI"""
59
+
60
+ def __init__(self):
61
+ self.claude_path = "claude"
62
+
63
+ def run_prompt(
64
+ self,
65
+ prompt: str,
66
+ context: Optional[dict] = None,
67
+ system: Optional[str] = None,
68
+ ) -> str:
69
+ """Run prompt via Claude Code CLI"""
70
+ full_prompt = self._build_prompt(prompt, context, system)
71
+ cmd = [self.claude_path, "-p", full_prompt]
72
+
73
+ try:
74
+ result = subprocess.run(
75
+ cmd,
76
+ capture_output=True,
77
+ text=True,
78
+ timeout=300 # 5 min timeout
79
+ )
80
+ return result.stdout
81
+ except subprocess.TimeoutExpired:
82
+ return "Error: Command timed out"
83
+ except Exception as e:
84
+ return f"Error: {str(e)}"
85
+
86
+ def run_interactive(
87
+ self,
88
+ prompt: str,
89
+ context: Optional[dict] = None,
90
+ system: Optional[str] = None,
91
+ ) -> Generator[str, None, None]:
92
+ """Run interactive Claude Code session"""
93
+ yield self.run_prompt(prompt, context, system)
94
+
95
+ def run_conversation(
96
+ self,
97
+ messages: list[dict],
98
+ system: Optional[str] = None,
99
+ ) -> str:
100
+ """Run conversation via Claude Code CLI using --continue flag"""
101
+ # Claude Code CLI doesn't support multi-turn natively via -p,
102
+ # so we concatenate the conversation into a single prompt.
103
+ parts = []
104
+ if system:
105
+ parts.append(f"<system>\n{system}\n</system>\n")
106
+
107
+ for msg in messages:
108
+ role = msg["role"].upper()
109
+ parts.append(f"[{role}]\n{msg['content']}\n")
110
+
111
+ full_prompt = "\n".join(parts)
112
+ cmd = [self.claude_path, "-p", full_prompt]
113
+
114
+ try:
115
+ result = subprocess.run(
116
+ cmd,
117
+ capture_output=True,
118
+ text=True,
119
+ timeout=300,
120
+ )
121
+ return result.stdout
122
+ except subprocess.TimeoutExpired:
123
+ return "Error: Command timed out"
124
+ except Exception as e:
125
+ return f"Error: {str(e)}"
126
+
127
+ @staticmethod
128
+ def _build_prompt(
129
+ prompt: str,
130
+ context: Optional[dict] = None,
131
+ system: Optional[str] = None,
132
+ ) -> str:
133
+ """Combine system, context, and prompt into a single string for CLI mode."""
134
+ parts = []
135
+
136
+ if system:
137
+ parts.append(f"<system>\n{system}\n</system>\n")
138
+
139
+ if context:
140
+ context_str = json.dumps(context, indent=2, ensure_ascii=False)
141
+ parts.append(f"<context>\n{context_str}\n</context>\n")
142
+
143
+ parts.append(prompt)
144
+ return "\n".join(parts)
145
+
146
+
147
+ class AnthropicAPIBackend(AIBackendBase):
148
+ """Uses Anthropic API directly"""
149
+
150
+ def __init__(self, api_key: Optional[str] = None):
151
+ self.api_key = api_key or os.getenv("ANTHROPIC_API_KEY")
152
+
153
+ if not self.api_key:
154
+ raise ValueError("ANTHROPIC_API_KEY not set")
155
+
156
+ try:
157
+ from anthropic import Anthropic
158
+ self.client = Anthropic(api_key=self.api_key)
159
+ except ImportError:
160
+ raise ImportError("anthropic package not installed")
161
+
162
+ def run_prompt(
163
+ self,
164
+ prompt: str,
165
+ context: Optional[dict] = None,
166
+ system: Optional[str] = None,
167
+ ) -> str:
168
+ """Run prompt via Anthropic API"""
169
+ messages = []
170
+
171
+ if context:
172
+ context_str = json.dumps(context, indent=2, ensure_ascii=False)
173
+ messages.append({
174
+ "role": "user",
175
+ "content": f"Context:\n```json\n{context_str}\n```\n\n{prompt}"
176
+ })
177
+ else:
178
+ messages.append({
179
+ "role": "user",
180
+ "content": prompt
181
+ })
182
+
183
+ kwargs = {
184
+ "model": "claude-sonnet-4-20250514",
185
+ "max_tokens": 4096,
186
+ "messages": messages,
187
+ }
188
+ if system:
189
+ kwargs["system"] = system
190
+
191
+ response = self.client.messages.create(**kwargs)
192
+ return response.content[0].text
193
+
194
+ def run_interactive(
195
+ self,
196
+ prompt: str,
197
+ context: Optional[dict] = None,
198
+ system: Optional[str] = None,
199
+ ) -> Generator[str, None, None]:
200
+ """Run with streaming"""
201
+ messages = []
202
+
203
+ if context:
204
+ context_str = json.dumps(context, indent=2, ensure_ascii=False)
205
+ messages.append({
206
+ "role": "user",
207
+ "content": f"Context:\n```json\n{context_str}\n```\n\n{prompt}"
208
+ })
209
+ else:
210
+ messages.append({
211
+ "role": "user",
212
+ "content": prompt
213
+ })
214
+
215
+ kwargs = {
216
+ "model": "claude-sonnet-4-20250514",
217
+ "max_tokens": 4096,
218
+ "messages": messages,
219
+ }
220
+ if system:
221
+ kwargs["system"] = system
222
+
223
+ with self.client.messages.stream(**kwargs) as stream:
224
+ for text in stream.text_stream:
225
+ yield text
226
+
227
+ def run_conversation(
228
+ self,
229
+ messages: list[dict],
230
+ system: Optional[str] = None,
231
+ ) -> str:
232
+ """Run a multi-turn conversation via API"""
233
+ kwargs = {
234
+ "model": "claude-sonnet-4-20250514",
235
+ "max_tokens": 4096,
236
+ "messages": messages,
237
+ }
238
+ if system:
239
+ kwargs["system"] = system
240
+
241
+ response = self.client.messages.create(**kwargs)
242
+ return response.content[0].text
243
+
244
+
245
+ def get_backend_instance(backend: AIBackend) -> AIBackendBase:
246
+ """Get appropriate backend instance"""
247
+ if backend == AIBackend.CLAUDE_CODE:
248
+ return ClaudeCodeBackend()
249
+ elif backend == AIBackend.ANTHROPIC_API:
250
+ return AnthropicAPIBackend()
251
+ else:
252
+ raise ValueError("No AI backend available")