Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/heavy-shoes-report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@techatnyu/ralph": patch
---

Add a \ralph init`command to scaffold a`.ralph` workspace for coding projects.`
8 changes: 8 additions & 0 deletions apps/tui/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@ In local development, run `bun run dev` from the repo root. Turborepo will run
the TUI and daemon together, and the TUI will wait for the foreground daemon
instead of spawning a detached background process.

## Scaffold a workspace

From the `apps/tui` directory, run:

```bash
bun run src/cli.ts init /path/to/project
```

## Advanced daemon control

```bash
Expand Down
3 changes: 2 additions & 1 deletion apps/tui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@
"typescript": "^5"
},
"dependencies": {
"@techatnyu/ralphd": "workspace:*",
"@crustjs/core": "^0.0.13",
"@crustjs/create": "^0.0.4",
"@crustjs/plugins": "^0.0.16",
"@opentui/core": "^0.1.77",
"@opentui/react": "^0.1.77",
"@techatnyu/ralphd": "workspace:*",
"react": "^19.2.4"
}
}
17 changes: 17 additions & 0 deletions apps/tui/src/cli.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Crust } from "@crustjs/core";
import { helpPlugin } from "@crustjs/plugins";
import { bootstrapRalphWorkspace } from "./scaffold";
import {
daemon,
type JobState,
Expand Down Expand Up @@ -36,6 +37,22 @@ const cli = new Crust("ralph")
.run(async () => {
await runTui();
})
.command("init", (cmd) =>
cmd
.meta({ description: "Create a Ralph workspace for a project" })
.args([
{
name: "directory",
type: "string",
required: true,
description: "Project directory where .ralph will be created",
},
])
.run(async ({ args }) => {
await bootstrapRalphWorkspace(args.directory);
console.log(`Created Ralph workspace in ${args.directory}/.ralph`);
}),
)
.command("daemon", (daemonCommand) =>
daemonCommand
.meta({ description: "Manage the background daemon" })
Expand Down
17 changes: 17 additions & 0 deletions apps/tui/src/scaffold.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { scaffold } from "@crustjs/create";
import { basename, resolve } from "node:path";

export async function bootstrapRalphWorkspace(
projectDirectory: string,
): Promise<void> {
const absoluteProjectDirectory = resolve(projectDirectory);
const projectName = basename(absoluteProjectDirectory);

await scaffold({
template: new URL("../templates/ralph-workspace", import.meta.url),
dest: resolve(absoluteProjectDirectory, ".ralph"),
context: {
projectName,
},
});
}
109 changes: 109 additions & 0 deletions apps/tui/templates/ralph-workspace/PROMPT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# Ralph Agent Instructions

You are an AI coding agent working through a project task by task. Each session, you complete EXACTLY ONE task and hand off to the next iteration.

## Step 1: Understand Context

Read these files to understand the current state:

1. **`SPEC.md`** - Project specification (what you're building)
2. **`prd.json`** - Task list with all tasks and their status
3. **`progress.md`** - Log of completed work and notes from previous iterations

> **Note**: These files may be located in a `.ralph/` subdirectory (e.g., `.ralph/SPEC.md`, `.ralph/prd.json`, `.ralph/progress.md`). Check both locations.

## Step 2: Select a Task

From `prd.json`, select **ONE** task to work on:

- Choose a task where `passed: false`
- Analyze task descriptions and the current project state to determine the best task to work on next
- Consider logical dependencies (e.g., "add authentication" should come before "add protected routes")
- If unclear, prefer tasks listed earlier in the file

## Step 3: Complete the Task

Work through the task:

1. Follow the `subtasks` array as your implementation guide
2. Write clean, well-structured code
3. **Verify your work** before marking complete:
- Run tests if they exist
- Run type checks if applicable (`tsc --noEmit`, `mypy`, etc.)
- Run linting if configured
- Manually verify the feature works as expected

## Step 4: Update Progress

After completing the task, update `progress.md`:

### Format

Each entry should be separated by "---" and include:

- Task: The task description from prd.json
- Completed: What was accomplished
- Files Changed: List of modified files
- Decisions: Key architectural or implementation decisions
- Notes for Next Agent: Context for future iterations

### Rules

- **APPEND ONLY**: Never modify or delete previous entries
- Each new entry starts with "---" separator
- Be specific about what was done and why
- Leave helpful context for future iterations

### Example Entry

```markdown
---

## Task: [Task description from prd.json]

### Completed

- [What you accomplished]

### Files Changed

- [List of files]

### Decisions

- [Any architectural or implementation decisions]

### Notes for Future Agent

- [Helpful context for future iterations]
```

## Step 5: Update prd.json

1. Set `passed: true` for the completed task
2. Update `notes` field of **any other tasks** if you discovered relevant context that is helpful for completing the given task

## Step 6: Commit Changes

- Create a git commit with a clear, descriptive message.
- Include what was implemented, not just "completed task"

## Step 7: Signal Completion

When finished, output this exact string on its own line:

```
RALPH_TASK_COMPLETE
```

This signals the orchestration script to start the next iteration.

---

## Important Rules

1. **One task per session** - Do not work on multiple tasks
2. **Verify before marking complete** - Ensure the implementation actually works
3. **Append-only progress** - Never edit previous progress.md entries
4. **Leave context** - Future iterations depend on your notes
5. **Commit your work** - All changes must be committed before signaling completion
2 changes: 2 additions & 0 deletions apps/tui/templates/ralph-workspace/SPEC.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# {{projectName}}
<!-- The high-level project specification. Captures what you're building and why — goals, scope, tech stack choices, and architectural decisions. Implementation details (concrete tasks, exact thresholds, file-level structure) belong in prd.json and the codebase itself. A good spec is stable and rarely needs updating as the project evolves. -->
5 changes: 5 additions & 0 deletions apps/tui/templates/ralph-workspace/config
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
RALPH_AGENT_CMD="opencode run"
RALPH_PROMPT_FILE="PROMPT.md"
RALPH_SPEC_FILE="SPEC.md"
RALPH_PRD_FILE="prd.json"
RALPH_PROGRESS_FILE="progress.md"
3 changes: 3 additions & 0 deletions apps/tui/templates/ralph-workspace/prd.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"tasks": []
}
1 change: 1 addition & 0 deletions apps/tui/templates/ralph-workspace/progress.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Progress Log
10 changes: 8 additions & 2 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading