dynamic-ralph 0.1.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.
- dynamic_ralph-0.1.0/PKG-INFO +8 -0
- dynamic_ralph-0.1.0/README.md +116 -0
- dynamic_ralph-0.1.0/bin/__init__.py +0 -0
- dynamic_ralph-0.1.0/bin/run_agent.py +94 -0
- dynamic_ralph-0.1.0/bin/run_dynamic_ralph.py +993 -0
- dynamic_ralph-0.1.0/bin/run_retrospective.py +369 -0
- dynamic_ralph-0.1.0/dynamic_ralph.egg-info/PKG-INFO +8 -0
- dynamic_ralph-0.1.0/dynamic_ralph.egg-info/SOURCES.txt +43 -0
- dynamic_ralph-0.1.0/dynamic_ralph.egg-info/dependency_links.txt +1 -0
- dynamic_ralph-0.1.0/dynamic_ralph.egg-info/entry_points.txt +4 -0
- dynamic_ralph-0.1.0/dynamic_ralph.egg-info/requires.txt +1 -0
- dynamic_ralph-0.1.0/dynamic_ralph.egg-info/top_level.txt +2 -0
- dynamic_ralph-0.1.0/multi_agent/__init__.py +63 -0
- dynamic_ralph-0.1.0/multi_agent/backend.py +180 -0
- dynamic_ralph-0.1.0/multi_agent/backends/__init__.py +1 -0
- dynamic_ralph-0.1.0/multi_agent/backends/claude_code.py +240 -0
- dynamic_ralph-0.1.0/multi_agent/compose.py +17 -0
- dynamic_ralph-0.1.0/multi_agent/constants.py +117 -0
- dynamic_ralph-0.1.0/multi_agent/docker.py +30 -0
- dynamic_ralph-0.1.0/multi_agent/filelock.py +44 -0
- dynamic_ralph-0.1.0/multi_agent/models.py +100 -0
- dynamic_ralph-0.1.0/multi_agent/prd.py +35 -0
- dynamic_ralph-0.1.0/multi_agent/prompts.py +60 -0
- dynamic_ralph-0.1.0/multi_agent/stream.py +99 -0
- dynamic_ralph-0.1.0/multi_agent/workflow/__init__.py +102 -0
- dynamic_ralph-0.1.0/multi_agent/workflow/editing.py +289 -0
- dynamic_ralph-0.1.0/multi_agent/workflow/executor.py +685 -0
- dynamic_ralph-0.1.0/multi_agent/workflow/models.py +212 -0
- dynamic_ralph-0.1.0/multi_agent/workflow/prompts.py +365 -0
- dynamic_ralph-0.1.0/multi_agent/workflow/scratch.py +134 -0
- dynamic_ralph-0.1.0/multi_agent/workflow/state.py +235 -0
- dynamic_ralph-0.1.0/multi_agent/workflow/steps.py +90 -0
- dynamic_ralph-0.1.0/pyproject.toml +67 -0
- dynamic_ralph-0.1.0/setup.cfg +4 -0
- dynamic_ralph-0.1.0/tests/test_backend.py +400 -0
- dynamic_ralph-0.1.0/tests/test_executor_bugs.py +175 -0
- dynamic_ralph-0.1.0/tests/test_git_identity.py +158 -0
- dynamic_ralph-0.1.0/tests/test_log_paths.py +159 -0
- dynamic_ralph-0.1.0/tests/test_migration.py +299 -0
- dynamic_ralph-0.1.0/tests/test_retrospective.py +380 -0
- dynamic_ralph-0.1.0/tests/test_run_agent.py +110 -0
- dynamic_ralph-0.1.0/tests/test_run_directory.py +89 -0
- dynamic_ralph-0.1.0/tests/test_summary_log.py +59 -0
- dynamic_ralph-0.1.0/tests/test_third_party_mode.py +225 -0
- dynamic_ralph-0.1.0/tests/test_workflow.py +1150 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# Dynamic Ralph
|
|
2
|
+
|
|
3
|
+
A step-based multi-agent workflow orchestrator for [Claude Code](https://docs.anthropic.com/en/docs/claude-code).
|
|
4
|
+
|
|
5
|
+
Dynamic Ralph decomposes user stories into focused, sequential steps and executes them via Claude Code agents. It supports three execution modes:
|
|
6
|
+
|
|
7
|
+
- **One-shot**: Single task, ephemeral state, full 10-step workflow
|
|
8
|
+
- **PRD serial**: Stories from a PRD file, executed one at a time
|
|
9
|
+
- **PRD parallel**: Multiple agents via git worktrees for concurrent story execution
|
|
10
|
+
|
|
11
|
+
## Requirements
|
|
12
|
+
|
|
13
|
+
- Python 3.13+
|
|
14
|
+
- [uv](https://github.com/astral-sh/uv) package manager
|
|
15
|
+
- Docker (for containerized agent execution)
|
|
16
|
+
- Claude Code CLI (`npx @anthropic-ai/claude-code`)
|
|
17
|
+
|
|
18
|
+
## Setup
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# Install dependencies
|
|
22
|
+
uv sync
|
|
23
|
+
|
|
24
|
+
# Install as a tool
|
|
25
|
+
uv tool install -e .
|
|
26
|
+
|
|
27
|
+
# Build the Docker agent image
|
|
28
|
+
uv tool run --from=dynamic-ralph dynamic-ralph --build "dummy"
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Usage
|
|
32
|
+
|
|
33
|
+
### Interactive agent
|
|
34
|
+
|
|
35
|
+
Launch an interactive Claude Code session inside the ralph-agent container:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
uv tool run --from=dynamic-ralph ralph-agent
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### One-shot mode
|
|
42
|
+
|
|
43
|
+
Execute a single task through the full workflow:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
uv tool run --from=dynamic-ralph dynamic-ralph "Add a logout button to the settings page"
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### PRD serial mode
|
|
50
|
+
|
|
51
|
+
Execute stories from a PRD file one at a time:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
uv tool run --from=dynamic-ralph dynamic-ralph --prd prd.json
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### PRD parallel mode
|
|
58
|
+
|
|
59
|
+
Execute stories concurrently with multiple agents:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
uv tool run --from=dynamic-ralph dynamic-ralph --prd prd.json --agents 3
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Resume a previous run
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
uv tool run --from=dynamic-ralph dynamic-ralph --prd prd.json --resume
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Configuration
|
|
72
|
+
|
|
73
|
+
Dynamic Ralph uses environment variables for project-specific configuration:
|
|
74
|
+
|
|
75
|
+
| Variable | Default | Description |
|
|
76
|
+
|----------|---------|-------------|
|
|
77
|
+
| `RALPH_IMAGE` | `ralph-agent:latest` | Docker image for agent containers |
|
|
78
|
+
| `RALPH_COMPOSE_FILE` | `compose.test.yml` | Docker Compose file for infrastructure |
|
|
79
|
+
| `RALPH_ENV_FILE` | `.env` | Environment file for Docker Compose |
|
|
80
|
+
| `RALPH_SERVICE` | `app` | Main service name in Docker Compose |
|
|
81
|
+
| `RALPH_INFRA_SERVICES` | `mysql,redis` | Comma-separated infrastructure services |
|
|
82
|
+
| `RALPH_GIT_EMAIL` | `claude-agent@dynamic-ralph.dev` | Git email for agent commits |
|
|
83
|
+
|
|
84
|
+
## Workflow Steps
|
|
85
|
+
|
|
86
|
+
The default 10-step workflow:
|
|
87
|
+
|
|
88
|
+
1. **Context Gathering** - Explore codebase, understand relevant files
|
|
89
|
+
2. **Planning** - Design implementation approach
|
|
90
|
+
3. **Architecture** - Plan file changes and interfaces
|
|
91
|
+
4. **Test Architecture** - Design test strategy
|
|
92
|
+
5. **Coding** - Implement the changes
|
|
93
|
+
6. **Linting** - Format and lint (mandatory)
|
|
94
|
+
7. **Initial Testing** - Run tests, fix failures
|
|
95
|
+
8. **Review** - Self-review the implementation
|
|
96
|
+
9. **Prune Tests** - Remove redundant tests
|
|
97
|
+
10. **Final Review** - Final verification (mandatory)
|
|
98
|
+
|
|
99
|
+
Agents can dynamically edit the workflow (add, split, skip, reorder steps) during execution.
|
|
100
|
+
|
|
101
|
+
## Development
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
# Install dev dependencies
|
|
105
|
+
uv sync
|
|
106
|
+
|
|
107
|
+
# Run tests
|
|
108
|
+
uv run pytest
|
|
109
|
+
|
|
110
|
+
# Format and lint
|
|
111
|
+
uv run pre-commit run -a
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## License
|
|
115
|
+
|
|
116
|
+
Apache-2.0
|
|
File without changes
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Run an interactive Claude Code session inside the ralph-agent container.
|
|
3
|
+
|
|
4
|
+
Mounts host credentials (~/.claude, ~/.config/claude), the current directory
|
|
5
|
+
as /workspace, and the Docker socket. Uses ``os.execvp`` so the container
|
|
6
|
+
gets direct TTY access for a regular interactive Claude experience.
|
|
7
|
+
|
|
8
|
+
Extra arguments after ``--`` are forwarded to the ``claude`` CLI.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import os
|
|
12
|
+
import sys
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
|
|
15
|
+
from multi_agent.constants import GIT_EMAIL, RALPH_IMAGE, RALPH_MODE, get_git_author_identity
|
|
16
|
+
from multi_agent.docker import build_image, docker_sock_gid, image_exists
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def build_interactive_docker_command(
|
|
20
|
+
*,
|
|
21
|
+
image: str = RALPH_IMAGE,
|
|
22
|
+
workspace: str | None = None,
|
|
23
|
+
extra_args: list[str] | None = None,
|
|
24
|
+
) -> list[str]:
|
|
25
|
+
"""Build a ``docker run -it`` command for interactive Claude Code use."""
|
|
26
|
+
if workspace is None:
|
|
27
|
+
workspace = os.getcwd()
|
|
28
|
+
|
|
29
|
+
author_name, author_email = get_git_author_identity()
|
|
30
|
+
home = Path.home()
|
|
31
|
+
claude_dir = home / '.claude'
|
|
32
|
+
config_claude = home / '.config' / 'claude'
|
|
33
|
+
|
|
34
|
+
cmd: list[str] = [
|
|
35
|
+
'docker',
|
|
36
|
+
'run',
|
|
37
|
+
'-it',
|
|
38
|
+
'--rm',
|
|
39
|
+
'--group-add',
|
|
40
|
+
docker_sock_gid(),
|
|
41
|
+
'-e',
|
|
42
|
+
'IS_SANDBOX=1',
|
|
43
|
+
'-e',
|
|
44
|
+
'UV_PROJECT_ENVIRONMENT=/tmp/venv',
|
|
45
|
+
'-e',
|
|
46
|
+
f'GIT_AUTHOR_NAME={author_name}',
|
|
47
|
+
'-e',
|
|
48
|
+
f'GIT_AUTHOR_EMAIL={author_email}',
|
|
49
|
+
'-e',
|
|
50
|
+
'GIT_COMMITTER_NAME=Claude Agent',
|
|
51
|
+
'-e',
|
|
52
|
+
f'GIT_COMMITTER_EMAIL={GIT_EMAIL}',
|
|
53
|
+
'-e',
|
|
54
|
+
f'RALPH_MODE={RALPH_MODE}',
|
|
55
|
+
'-v',
|
|
56
|
+
'/var/run/docker.sock:/var/run/docker.sock',
|
|
57
|
+
'-v',
|
|
58
|
+
f'{workspace}:/workspace',
|
|
59
|
+
'-v',
|
|
60
|
+
'/workspace/.venv',
|
|
61
|
+
'-v',
|
|
62
|
+
f'{claude_dir}:/home/agent/.claude',
|
|
63
|
+
'-v',
|
|
64
|
+
f'{config_claude}:/home/agent/.config/claude',
|
|
65
|
+
'-w',
|
|
66
|
+
'/workspace',
|
|
67
|
+
image,
|
|
68
|
+
'claude',
|
|
69
|
+
'--dangerously-skip-permissions',
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
if extra_args:
|
|
73
|
+
cmd.extend(extra_args)
|
|
74
|
+
|
|
75
|
+
return cmd
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def main() -> None:
|
|
79
|
+
# Ensure the Docker image is available
|
|
80
|
+
if not image_exists():
|
|
81
|
+
build_image()
|
|
82
|
+
|
|
83
|
+
# Everything after '--' is forwarded to claude
|
|
84
|
+
extra: list[str] = []
|
|
85
|
+
if '--' in sys.argv:
|
|
86
|
+
sep = sys.argv.index('--')
|
|
87
|
+
extra = sys.argv[sep + 1 :]
|
|
88
|
+
|
|
89
|
+
cmd = build_interactive_docker_command(extra_args=extra or None)
|
|
90
|
+
os.execvp(cmd[0], cmd)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
if __name__ == '__main__':
|
|
94
|
+
main()
|