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
4 changes: 2 additions & 2 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
},
"metadata": {
"description": "Official Rayfin agent skills for AI coding assistants",
"version": "0.4.0"
"version": "0.4.1"
},
"plugins": [
{
"name": "rayfin",
"description": "Getting-started router for Rayfin - gets an agent from zero into a working Rayfin project via the Rayfin CLI (scaffold/init), then hands off to the version-locked in-project skill the scaffold installs.",
"version": "0.4.0",
"version": "0.4.1",
"source": "./"
}
]
Expand Down
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "rayfin",
"version": "0.4.0",
"version": "0.4.1",
"description": "Getting-started router skill for Rayfin - scaffold a new app with the Rayfin CLI, then use the version-locked skill installed in the project.",
"author": {
"name": "Microsoft",
Expand Down
2 changes: 1 addition & 1 deletion .codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "rayfin",
"version": "0.4.0",
"version": "0.4.1",
"description": "Getting-started router skill for Rayfin - scaffold a new app with the Rayfin CLI, then use the version-locked skill installed in the project.",
"author": {
"name": "Microsoft",
Expand Down
2 changes: 1 addition & 1 deletion .cursor-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "rayfin",
"version": "0.4.0",
"version": "0.4.1",
"description": "Getting-started router skill for Rayfin - scaffold a new app with the Rayfin CLI, then use the version-locked skill installed in the project.",
"author": {
"name": "Microsoft",
Expand Down
4 changes: 2 additions & 2 deletions .github/plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
},
"metadata": {
"description": "Official Rayfin agent skills for AI coding assistants",
"version": "0.4.0"
"version": "0.4.1"
},
"plugins": [
{
"name": "rayfin",
"description": "Getting-started router for Rayfin — gets an agent from zero into a working Rayfin project via the Rayfin CLI (scaffold/init), then hands off to the version-locked in-project skill the scaffold installs.",
"version": "0.4.0",
"version": "0.4.1",
"source": "./"
}
]
Expand Down
55 changes: 55 additions & 0 deletions .github/workflows/validate-start-prompt.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: Validate start.md prompt

on:
pull_request:
paths:
- content/start.md
- .github/workflows/validate-start-prompt.yml
push:
branches: [main]
paths:
- content/start.md
- .github/workflows/validate-start-prompt.yml

permissions:
contents: read

jobs:
no-straight-quotes:
name: No straight double quotes in start.md
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Reject straight double quotes
run: |
if grep -n '"' content/start.md; then
echo
echo "::error file=content/start.md::start.md must not contain straight double quotes"
cat <<'EOF'
content/start.md contains straight double quotes (") on the lines above.

Why this breaks:
The README documents launching the prompt as a single command, which
fetches this file and passes it to copilot as a native-process argument:

copilot -i "$(curl -sSfL https://aka.ms/rayfin/start.md)"
copilot -i (irm https://aka.ms/rayfin/start.md)

Windows PowerShell 5.1 is still the default shell on Windows, and its
legacy argument parser splits native-command arguments on embedded
straight double quotes. The prompt arrives truncated, with the remainder
passed as stray operands, so the user lands in a broken session.
pwsh 7 handles it correctly, but 5.1 is the default path we document.

How to fix:
Reword to avoid the quotes (preferred), for example
"20 or later" -> 20-or-later
or use single quotes, or backticks for inline code.

Apostrophes and backticks are fine: only straight double quotes break the
PowerShell 5.1 argument parser.
EOF
exit 1
fi
echo "OK: no straight double quotes in content/start.md"
2 changes: 1 addition & 1 deletion .grok-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "rayfin",
"version": "0.4.0",
"version": "0.4.1",
"description": "Getting-started router skill for Rayfin - scaffold a new app with the Rayfin CLI, then use the version-locked skill installed in the project.",
"author": {
"name": "Microsoft",
Expand Down
2 changes: 1 addition & 1 deletion .kimi-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "rayfin",
"version": "0.4.0",
"version": "0.4.1",
"description": "Getting-started router skill for Rayfin - scaffold a new app with the Rayfin CLI, then use the version-locked skill installed in the project.",
"author": {
"name": "Microsoft",
Expand Down
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,22 @@ npm create @microsoft/rayfin@latest

This CLI scaffolds a new Rayfin project with everything you need: data models, authentication, APIs, and a ready-to-deploy app.

> [!TIP]
> **Prefer to build with a coding agent?** Hand it the guided setup prompt and
> describe what you want to build:
>
> ```bash
> copilot -i "$(curl -sSfL https://aka.ms/rayfin/start.md)"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if curl fails here, command substitution still expands (to an empty string) and copilot gets launched with an empty prompt, so the user lands in an unprimed session instead of the rayfin flow. worth fetching first and gating launch on both success and non-empty content, something like:

prompt=$(curl -sSfL https://aka.ms/rayfin/start.md) && [ -n "$prompt" ] && copilot -i "$prompt"

@sinedied Yohan Lasorsa (sinedied) Sep 8, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to push back on this one: splitting the command like this would only catch network failures, but a wrong aka.ms or temp failures return HTML without a 404 or any error. Not sure the catch here is worth the added complexity, keeping the command simple is part of the quickstart appeal IMHO.

Worst case, having an empty starter prompt is harmless as it just start copilot CLI and idle.
I considered doing something like `copilot -i "$(curl -sSfL https://aka.ms/rayfin/start.md || echo 'Error while fetching rayfin starter')", but showing "error" or something alike in a starter command doesn't send a good message for folks just scanning text and it also triggers copilot CLI instead of standing by. I don't think the tradeoff is worth it.

For reference, other frameworks using this "start.md" command just keep the command simple, ie: https://plainframework.com/

> ```
>
Comment thread
sinedied marked this conversation as resolved.
> On Windows (PowerShell):
>
> ```powershell
> copilot -i (irm https://aka.ms/rayfin/start.md)
Comment thread
sinedied marked this conversation as resolved.
> ```
>
> This loads the [Rayfin starter prompt](content/start.md): it checks your environment, picks a template, scaffolds the project, and helps you customize.

### Agent plugin

Install the Rayfin getting-started skill through your agent's native marketplace or extension manager:
Expand Down
46 changes: 46 additions & 0 deletions content/start.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Rayfin: New Project Setup

You're helping a developer create a new Rayfin project. Rayfin is a TypeScript Backend-as-a-Service: decorate data models to get auto-generated APIs (REST + GraphQL), typed clients, auth, storage, and a local dev stack.

**Core rule:** Rayfin's specifics are version-locked per project, so once a project exists, never answer schema/API/auth/storage/deployment questions from memory: remembered Rayfin APIs are routinely wrong. Defer to the project's installed skill, `rayfin docs`, and `rayfin` MCP (Step 4).

**One question at a time:** whenever you need input from the user, ask a single question and wait for the answer before asking the next.

## Step 1: Ask what they want to build

Ask what they want to build, and confirm a kebab-case project name. Infer whether it targets Microsoft Fabric or should be self-contained, only clarifying if it's unclear. This guides the template choice in Step 3 and the customization in Step 4.

Keep it short if the working directory already looks like an existing app: Step 3 determines the exact situation and never creates a project nested inside or beside another one.

## Step 2: Check prerequisites

Before running any `npx` command: `node --version` and `git --version`. Rayfin supports Node **LTS** releases, currently v20, v22 and v24. Odd-numbered major like 21, 23 or 25 are unsupported. Install anything missing first:

- macOS: install the LTS build from [nodejs.org/en/download](https://nodejs.org/en/download), which defaults to LTS. Homebrew's `node` formula tracks Current, so avoid it here. For git, use `brew install git` or the Xcode Command Line Tools.
- Windows: `winget install -e --id OpenJS.NodeJS.LTS` then `winget install -e --id Git.Git`
- Linux (Debian/Ubuntu): `curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -` then `sudo apt install -y nodejs git`

Don't proceed until `node --version` reports an LTS release, meaning v20.x, v22.x or v24.x today. When a newer LTS line ships, prefer it, and fall back to the most recent LTS the scaffolder accepts if it rejects the brand-new one.

## Step 3: Get into a project

Don't scaffold from memory: fetch the getting-started skill and follow it. It is the canonical source for project detection, the default template, and the exact CLI commands, and it is kept up to date as those change.

Fetch and read this URL:

<https://raw.githubusercontent.com/microsoft/rayfin/main/skills/rayfin-getting-started/SKILL.md>

Then follow it to detect whether you're already in a Rayfin project, in an existing non-Rayfin app, or in an empty directory, and to run the right command for that case. Feed it what you learned in Step 1: what the user wants to build, and a kebab-case project name you've confirmed with them.

Once it has scaffolded, make sure you're at the project root before continuing: `create-rayfin` creates a child directory, while an in-place init leaves you where you are. Then continue to Step 4.

## Step 4: Load the in-project skill, then plan & customize

Before writing any Rayfin-specific code, hand off to the project's authoritative, version-locked sources:

1. Load `.agents/skills/rayfin/SKILL.md` and follow it; if your tooling supports it, reload tools to bring the `rayfin` MCP online.
2. Look up version-matched APIs via `rayfin docs` and the `rayfin` MCP instead of guessing. The skill file and `rayfin docs` work as soon as the project exists, so don't block waiting on the MCP reload.

Then plan before you build: outline the first changes for what they described in Step 1 (entities under `rayfin/data/`, views under `src/`, packages to install) and confirm that plan with the user before writing code. If your tooling has a planning mode, use it.

Don't start the backend or frontend; the user runs the app themselves when ready (see the project's `README.md`).
2 changes: 1 addition & 1 deletion gemini-extension.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "rayfin",
"version": "0.4.0",
"version": "0.4.1",
"description": "Getting-started router skill for Rayfin - scaffold a new app with the Rayfin CLI, then use the version-locked skill installed in the project."
}
2 changes: 1 addition & 1 deletion kimi-marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
{
"id": "rayfin",
"displayName": "Rayfin",
"version": "0.4.0",
"version": "0.4.1",
"description": "Get started building a Rayfin app with the Rayfin CLI.",
"homepage": "https://github.com/microsoft/rayfin",
"keywords": [
Expand Down
2 changes: 1 addition & 1 deletion plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
"name": "rayfin",
"version": "0.4.0",
"version": "0.4.1",
"description": "Getting-started router skill for Rayfin - scaffold a new app with the Rayfin CLI, then use the version-locked skill installed in the project.",
"author": {
"name": "Microsoft",
Expand Down
9 changes: 5 additions & 4 deletions skills/rayfin-getting-started/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: rayfin-getting-started
description: "Use when starting or creating a NEW Rayfin app, or when a Rayfin task comes up and you are not yet inside a Rayfin project. Gets you into a project with the Rayfin CLI, then hands off to the authoritative, version-locked in-project rayfin skill/MCP/docs that own all in-project work. Triggers: build a Rayfin app, start a Rayfin project, create a new Rayfin app, create-rayfin, npm create @microsoft/rayfin, rayfin init, scaffold rayfin, rayfin CLI, rayfin template, universal app, awesome-rayfin gallery, get started with Rayfin"
metadata:
author: microsoft
version: "0.2.0"
version: "0.2.1"
---

# Rayfin (Getting Started)
Expand Down Expand Up @@ -46,7 +46,8 @@ project and continue in place. Never stand up a nested or sibling project.

- **Already in one →** load `.agents/skills/rayfin/SKILL.md` and use the `rayfin` MCP /
`rayfin docs`. Stop using this skill.
- **Existing non-Rayfin app here →** add Rayfin in place with `npx rayfin init` (don't
- **Existing non-Rayfin app here →** add Rayfin in place with
`npx -y -p @microsoft/rayfin-cli@latest rayfin init --project-name <app-name>` (don't
scaffold a separate project), then load the in-project skill.
- **Empty directory →** scaffold (below), then load the in-project skill from the project root.

Expand All @@ -64,8 +65,8 @@ mishandle piped stdin and strip flags, and `--project-name` is **required** non-
# it fails to parse instead of continuing.
npx -y @microsoft/create-rayfin@latest --project-name <app-name> --template https://github.com/microsoft/awesome-rayfin --template-name "Universal App"

# Or add Rayfin into an existing/empty directory
npx rayfin init [directory]
# Or add Rayfin into an existing directory.
npx -y -p @microsoft/rayfin-cli@latest rayfin init --project-name <app-name> [directory]

# Templates bundled with the CLI (JSON), only if you need a different starting point
npx -y @microsoft/create-rayfin@latest --list-templates
Expand Down