Skip to content
Merged
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
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,6 @@ At minimum, you need one LLM provider API key (e.g., Anthropic or OpenAI) config

## Documentation

- [CLAUDE-ARCHITECTURE.md](CLAUDE-ARCHITECTURE.md) - Deep architecture reference (node types, state management, execution model)
- [CONTRIBUTING.md](CONTRIBUTING.md) - How to contribute
- [docs/editor.md](docs/editor.md) - Editor features and usage
- [frontend/ELECTRON.md](frontend/ELECTRON.md) - Build and distribution
Expand Down
813 changes: 440 additions & 373 deletions backend/package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"dependencies": {
"@anthropic-ai/sdk": "^0.65.0",
"@google/generative-ai": "^0.24.1",
"@prompd/cli": "file:../../prompd-cli/typescript",
"@prompd/cli": "^0.5.0-beta.6",
"adm-zip": "^0.5.10",
"archiver": "^6.0.1",
"axios": "^1.6.2",
Expand Down
1 change: 1 addition & 0 deletions backend/src/prompts/modes/agent.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"description": "AI assistant that can read, write, search, and execute",
"responseFormat": "xml",
"systemPromptFile": "agent.md",
"includeFiles": ["prmd-syntax.md"],
"tools": [
{
"name": "read_file",
Expand Down
47 changes: 0 additions & 47 deletions backend/src/prompts/modes/agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,53 +64,6 @@ You operate in a batch-approval workflow:
| `ask_user` | `question`, `options` | Ask clarifying question. Options are optional clickable buttons plus freeform input. |
| `present_plan` | `content` | Present a plan for review. Use when: 3+ files affected, destructive ops, or multiple valid approaches. Skip for single-file edits with clear intent. When result says user APPROVED, immediately execute using actual tool calls. |

### Package Path Parsing

If `inherits: "@prompd/public-examples@1.1.0/assistants/code-assistant.prmd"`:
- `package_name` = `@prompd/public-examples`
- `version` = `1.1.0`
- `file_path` = `assistants/code-assistant.prmd`

## .prmd File Format

```
--- <-- Line 1: OPENING delimiter (always first)
id: example-id
name: "Example"
version: 1.0.0
parameters:
- name: foo
type: string
inherits: "@p/base.prmd"
--- <-- CLOSING delimiter (ends frontmatter)

# Title <-- Markdown goes AFTER the closing ---

## Section
Content here.
```

**Rules:**
1. Line 1 is ALWAYS `---` (opening frontmatter delimiter)
2. YAML frontmatter goes between opening and closing `---`
3. ALL markdown content goes AFTER the closing `---`
4. NOTHING goes before the opening `---` on line 1

**Adding markdown to a file that only has frontmatter:** Search for the LAST YAML LINE + closing `---` and append markdown after it:

```xml
<search>inherits: "@p/template.prmd"
---</search>
<replace>inherits: "@p/template.prmd"
---

# Title

## New Section

Content here.</replace>
```

## Response Format

### Tool call:
Expand Down
1 change: 1 addition & 0 deletions backend/src/prompts/modes/brainstorm.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"description": "Collaborative document editor that iterates with you on a working copy",
"responseFormat": "xml",
"systemPromptFile": "brainstorm.md",
"includeFiles": ["prmd-syntax.md"],
"tools": [
{
"name": "edit_file",
Expand Down
44 changes: 0 additions & 44 deletions backend/src/prompts/modes/brainstorm.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,50 +100,6 @@ You are a **collaborative document editor** brainstorming with the user on a sin
</tool_call>
```

## .prmd File Format

If the document is a `.prmd` file (Prompd prompt file):

```
--- <-- YAML frontmatter
id: example-id
name: "Example"
version: 1.0.0
parameters:
- name: foo
type: string
description: "A parameter"
required: true
inherits: "@alias/base.prmd"
--- <-- End of frontmatter

# Title <-- Markdown + Nunjucks body

## Section
Content with {{foo}} parameter references.

{% if foo %}
Conditional content using Nunjucks template syntax.
{% endif %}
```

**Syntax:**
- **Frontmatter** (between `---` delimiters): YAML
- **Body** (after closing `---`): Markdown with Nunjucks template syntax
- Parameters: `- name:` array in frontmatter, `{{name}}` references in body
- Conditionals: `{% if value %}...{% endif %}` (Nunjucks, NOT `{{#if}}`)
- Loops: `{% for item in items %}...{% endfor %}`
- `inherits:` references a base template from a package

### Package Path Parsing

If `inherits: "@prompd/public-examples@1.1.0/assistants/code-assistant.prmd"`:
- `package_name` = `@prompd/public-examples`
- `version` = `1.1.0`
- `file_path` = `assistants/code-assistant.prmd`

Use `read_package_file` with these values to read the base template.

## Response Format

### Making edits:
Expand Down
1 change: 1 addition & 0 deletions backend/src/prompts/modes/help-chat.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"description": "App usage guide for Prompd",
"responseFormat": "markdown",
"systemPromptFile": "help-chat.md",
"includeFiles": ["prmd-syntax.md"],
"tools": [],
"settings": {
"maxIterations": 1,
Expand Down
1 change: 1 addition & 0 deletions backend/src/prompts/modes/planner.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"description": "AI planning assistant that explores and designs before executing",
"responseFormat": "xml",
"systemPromptFile": "planner.md",
"includeFiles": ["prmd-syntax.md"],
"tools": [
{
"name": "read_file",
Expand Down
28 changes: 0 additions & 28 deletions backend/src/prompts/modes/planner.md
Original file line number Diff line number Diff line change
Expand Up @@ -279,34 +279,6 @@ When you receive tool execution results (wrapped in <tool_results>):
3. **Present plan when ready** - Once you have enough information, call `present_plan`.
4. **Don't repeat tools** - If you already read a file, don't read it again.

## .prmd File Format

A .prmd file has this structure:

```
--- <-- OPENING --- (line 1, starts frontmatter)
id: example-id
name: "Example"
version: 1.0.0
parameters:
- name: foo
type: string
inherits: "@p/base.prmd"
--- <-- CLOSING --- (ends frontmatter)

# Title <-- Markdown goes HERE, AFTER the CLOSING ---

## Section
Content here.
```

**STRUCTURE RULES:**
1. Line 1 is ALWAYS `---` (the OPENING frontmatter delimiter)
2. YAML frontmatter goes between the opening `---` and closing `---`
3. The closing `---` marks the END of the frontmatter
4. ALL markdown content goes AFTER the CLOSING `---`
5. NOTHING goes BEFORE the opening `---` on line 1

## Context Compaction

If you see a `[Context compacted: N earlier messages were removed...]` system message, earlier parts of the conversation have been trimmed to stay within context limits. When this happens:
Expand Down
169 changes: 169 additions & 0 deletions backend/src/prompts/modes/prmd-syntax.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
## .prmd File Format

A `.prmd` file has two sections: **YAML frontmatter** (metadata) and **Markdown body** (content with template syntax).

```
--- <-- Line 1: OPENING delimiter (always first line)
id: example-id
name: "Example Prompt"
version: 1.0.0
description: "What this prompt does"
parameters:
- name: topic
type: string
description: "The topic to write about"
required: true
- name: tools
type: json
description: "Tool definitions as JSON"
required: false
default: ["read_file", "write_file"]
inherits: "@namespace/package@1.0.0/base.prmd"
context:
- docs/reference.md
--- <-- CLOSING delimiter (ends frontmatter)

# Title <-- Markdown body starts AFTER closing ---

## Section
Content with {{ topic }} variable references.
```

### Structure Rules

1. Line 1 is ALWAYS `---` (opening frontmatter delimiter) -- nothing before it
2. YAML frontmatter goes between opening and closing `---`
3. ALL markdown content goes AFTER the closing `---`
4. NEVER put markdown headers (# Title) inside the YAML frontmatter section

### Frontmatter Fields

| Field | Type | Description |
|-------|------|-------------|
| `id` | string | Unique identifier (required) |
| `name` | string | Display name (required) |
| `version` | string | Semver version (required) |
| `description` | string | What the prompt does |
| `parameters` | array | Input parameters (see below) |
| `inherits` | string | Base template package reference |
| `context` / `contexts` | string or array | File paths for additional context |
| `override` | object | Override sections from inherited template |

### Parameter Types

Parameters are defined in frontmatter and referenced in the body:

```yaml
parameters:
- name: topic
type: string # Plain text
required: true
- name: count
type: number # Numeric value
default: 5
- name: tools
type: json # JSON array or object -- passed as structured data
default: ["tool_a", "tool_b"]
- name: verbose
type: boolean # true/false flag
default: false
```

### Template Syntax (Nunjucks)

The body uses Nunjucks template syntax. This is NOT Handlebars -- do not use `{{#if}}` or `{{#each}}`.

**Variable output:**
```
{{ topic }} <-- Render parameter value
{{ topic | upper }} <-- With filter (uppercase)
{{ name | default("unnamed") }} <-- With default fallback
```

**Conditionals:**
```
{% if verbose %}
Include extra detail here.
{% endif %}

{% if mode == "detailed" %}
Detailed instructions...
{% elif mode == "brief" %}
Brief instructions...
{% else %}
Standard instructions...
{% endif %}
```

**Loops:**
```
{% for tool in tools %}
- {{ tool }}
{% endfor %}

{% for item in items %}
### {{ item.name }}
{{ item.description }}
{% endfor %}
```

**Set variables:**
```
{% set parsed = schema %}
{% set greeting = "Hello " + name %}
```

**CRITICAL: Escaping literal curly braces**

If your template body contains literal `{` or `}` characters (JSON examples, code blocks, etc.), wrap them in `{% raw %}...{% endraw %}` to prevent the template engine from parsing them:

```
{% raw %}
{
"key": "value",
"nested": { "a": 1 }
}
{% endraw %}
```

For inline code fences containing braces:
```
{% raw %}```json{% endraw %}
{% raw %}{ "example": true }{% endraw %}
{% raw %}```{% endraw %}
```

Without `{% raw %}`, any `{` in the body triggers the template parser and causes `parseAggregate: expected colon after dict key` errors.

### Package Path Format

For `inherits:` references: `@namespace/package@version/path/to/file.prmd`

| Part | Example |
|------|---------|
| `package_name` | `@prompd/public-examples` |
| `version` | `1.1.0` |
| `file_path` | `assistants/code-assistant.prmd` |

Full: `inherits: "@prompd/public-examples@1.1.0/assistants/code-assistant.prmd"`

### Common Filters

| Filter | Example | Result |
|--------|---------|--------|
| `upper` | `{{ "hello" \| upper }}` | `HELLO` |
| `lower` | `{{ "HELLO" \| lower }}` | `hello` |
| `trim` | `{{ text \| trim }}` | Removes whitespace |
| `default` | `{{ val \| default("N/A") }}` | Fallback value |
| `join` | `{{ list \| join(", ") }}` | Array to string |
| `length` | `{{ items \| length }}` | Count items |
| `replace` | `{{ text \| replace("a", "b") }}` | String replace |
| `first` / `last` | `{{ items \| first }}` | First/last element |

### Edit Tips for AI Agents

- **ALWAYS read the file before editing** -- your search string must match the file content exactly
- **Prefer `edit_file` over `write_file`** for modifications to avoid losing content
- **When adding markdown to a frontmatter-only file**, search for the last YAML line + closing `---` and append after it
- **When adding parameters**, search for the existing `parameters:` line and extend the array
- **Preserve blank lines** -- if the file has a blank line between sections, keep it
Loading
Loading