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 README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ Prime Agent: A Self-Improving RLM Agent
Prime Agent is an open-source coding and research agent for general and long-running work. It is designed around two core abstractions:

- The **[Recursive Language Model (RLM)](https://www.primeintellect.ai/blog/rlm)** treats context as variables (*prompt-as-a-variable*) and tools like recursive subagents as function calls (*programmatic tool /sub-agent calling*) inside a persistent REPL.
- The **[Continual Harness](https://arxiv.org/abs/2605.09998)** stores supplemental prompts, memories, skill descriptions, and reusable subagent specifications as durable state that Prime Agent can refine through small, evidence-backed updates, local to the session by default.
- The **[Continual Harness](https://arxiv.org/abs/2605.09998)** stores supplemental prompts, memories, skill descriptions, and reusable subagent specifications as durable state that Prime Agent can refine through small, evidence-backed updates, scoped to the session, the repository, or all projects.

Prime Agent combines a persistent Python control environment with durable harness state, so useful working context and reusable operating patterns can outlive a single chat window.

- **Everything is programmatic:** persistent IPython is the built-in model tool; file operations, shell commands, tool use, subagents, and context management happen through code.
- **Subagents are built in:** `rlm(...)` spawns real child agents for parallel or background work and returns their results programmatically.
- **The harness can improve:** `/refine` reviews the current trajectory and can apply small, evidence-backed updates to supplemental harness state. It never rewrites the immutable base system prompt, and recorded snapshots support rollback.
- **The harness can improve:** `/refine` reviews the current trajectory and can apply small, evidence-backed updates to supplemental harness state, in this session, this repository (`--project`), or every project (`--global`). It never rewrites the immutable base system prompt, and recorded snapshots support rollback.
- **Skills are executable:** skills are importable Python packages, and the built-in skill creator can turn recurring workflows into project or personal skills.
- **Sessions run in the background:** daemon-backed agents keep running when the terminal disconnects and can be reattached later.
- **Agents communicate directly:** running agents can exchange messages and orchestrate one another without routing everything through the user.
Expand Down
5 changes: 5 additions & 0 deletions packages/coding-agent/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
- Added privacy-safe pseudonymous product analytics for onboarding, command use, execution modes, run outcomes, TTFT, latency, usage, tools, retries, and compactions, with disclosure and opt-out controls ([ENG-4682](https://linear.app/primeintellect/issue/ENG-4682/add-privacy-safe-posthog-analytics-to-prime-agent)).
- Changed sent agent messages in the IPython cell UI to show only the message text with a `╰─` gutter when expanded, matching received messages, and hid the raw `agent_message.send` receipt dictionary.
- Fixed Homebrew installs attempting to self-update their versioned Cellar keg instead of directing users to `brew upgrade prime-agent` ([#844](https://github.com/PrimeIntellect-ai/prime-agent/issues/844))
- Added a project harness scope stored in `<project>/.prime/agent/harness/`, selectable with `/refine --project`, `await refine.run(scope="project")`, and `rlm.harness.*(scope="project")`.
- Added `contextFiles` settings to disable `AGENTS.md`/`CLAUDE.md` discovery, drop the global `AGENTS.md`, or stop walking above the project root, with `/settings` toggles for the first two.
- Changed `rlmMaxDepth` to be read from project settings before global settings, and `/rlm-max-depth` to accept `--project` alongside `--global`.
- Changed project settings, `SYSTEM.md`, and `APPEND_SYSTEM.md` to resolve against the project root, so running Prime Agent from a subdirectory uses the repository's configuration.
- Changed the harness Python API from `global_=True` to `scope="local"|"project"|"global"` on `rlm.harness.*`, `rlm.get_harness_state()`, and `refine.run()`.

## [0.7.1] - 2026-08-07

Expand Down
19 changes: 17 additions & 2 deletions packages/coding-agent/docs/rlm-runtime.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,9 +208,24 @@ On reload, the aggregate is reapplied to the parent message. Context-tree report

`rlm.harness` is a persisted state ledger for prompt notes, memories, reusable skill descriptions, sub-agent specifications, and refinement events. It is not a second execution engine.

Session-local state lives in the session artifact directory under `harness/harness_state.json`. Explicitly global entries live under `~/.prime/agent/harness/`. The Python store reloads after external modification so host-side `/refine` writes and kernel writes do not overwrite each other.
State is stored in three scopes:

`/refine` runs a dedicated review over the current trajectory and applies small create/update/delete edits. Rollback uses recorded before/after snapshots. The base system prompt remains immutable; refinements are supplemental state.
| Scope | Location | Use for |
|---|---|---|
| `local` (default) | session artifact dir, `harness/harness_state.json` | current task progress, temporary blockers, session coordination |
| `project` | `<repo>/.prime/agent/harness/harness_state.json` | repository conventions, build/test commands, recurring pitfalls |
| `global` | `~/.prime/agent/harness/harness_state.json` | cross-project lessons, durable user preferences, reusable skills and subagent specs |

The system prompt shows all three merged, with narrower scopes winning id collisions and keeping a `<scope>:<id>` display key. Writes target one scope:

```python
rlm.harness.create_memory("Test command", "npm run check", scope="project")
await refine.run("record how this repository runs its tests", scope="project")
```

The kernel resolves scopes from `RLM_HARNESS_STATE_DIR`/`RLM_SESSION_DIR` (local), `RLM_PROJECT_HARNESS_STATE_DIR` (project), and `RLM_GLOBAL_HARNESS_STATE_DIR` (global). The Python store reloads after external modification so host-side `/refine` writes and kernel writes do not overwrite each other.

`/refine` runs a dedicated review over the current trajectory and applies small create/update/delete edits. `/refine --project` and `/refine --global` select the target store. Rollback uses recorded before/after snapshots; project and global refinements are also recorded in `refinements.jsonl` next to their store so they can be rolled back from a later session. The base system prompt remains immutable; refinements are supplemental state.

## Goal Requests

Expand Down
43 changes: 42 additions & 1 deletion packages/coding-agent/docs/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@ Prime Agent uses JSON settings files with project settings overriding global set
| Location | Scope |
|----------|-------|
| `~/.prime/agent/settings.json` | Global (all projects) |
| `.prime/agent/settings.json` | Project (current directory) |
| `<project>/.prime/agent/settings.json` | Project (this repository) |

The project directory is the nearest ancestor of the working directory that already has a
`.prime/agent` directory, otherwise the enclosing repository root, otherwise the working
directory itself. Starting Prime Agent in a subdirectory therefore uses the same project
settings, harness state, and `SYSTEM.md` as starting it at the repository root. The home
directory is never treated as a project.

Edit directly or use `/settings` for common options.

Expand Down Expand Up @@ -216,6 +222,41 @@ Normally the package manager's global modules location is queried using `root -g

When multiple sources specify a session directory, precedence is `--session-dir`, `PRIME_AGENT_SESSION_DIR`, the legacy `PRIME_AGENT_CODING_AGENT_SESSION_DIR`, then `sessionDir` in `settings.json`.

### Context Files

`AGENTS.md` and `CLAUDE.md` are loaded into the system prompt. Set these globally to change the
default, or per project to keep unrelated instructions out of one repository.

| Setting | Type | Default | Description |
|---------|------|---------|-------------|
| `contextFiles.enabled` | boolean | `true` | Load `AGENTS.md`/`CLAUDE.md` at all |
| `contextFiles.global` | boolean | `true` | Include `~/.prime/agent/AGENTS.md` in every project |
| `contextFiles.ancestors` | boolean | `true` | Include directories above the project root |

Keep only this repository's own instructions:

```json
{
"contextFiles": {
"global": false,
"ancestors": false
}
}
```

`--no-context-files` disables discovery for a single run regardless of these settings.
The `/settings` menu exposes the first two toggles as "AGENTS.md context" and "Global AGENTS.md".

### Recursive Agents

| Setting | Type | Default | Description |
|---------|------|---------|-------------|
| `rlmMaxDepth` | number | `1` | Default recursion depth for new sessions; `0` disables subagents |

`rlmMaxDepth` is read from project settings first, then global settings, then `RLM_MAX_DEPTH`.
`/rlm-max-depth <n>` changes the current chat only; `/rlm-max-depth <n> --project` and
`/rlm-max-depth <n> --global` also persist the default to that settings file.

### Model Cycling

| Setting | Type | Default | Description |
Expand Down
16 changes: 13 additions & 3 deletions packages/coding-agent/docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ Type `/` in the editor to open command completion. Extensions can register custo
| `/fork` | Create a new session from a previous user message |
| `/clone` | Duplicate the current active branch into a new session |
| `/compact [prompt]` | Manually compact context, optionally with custom instructions |
| `/refine [instructions]` | Refine or roll back session-backed harness state |
| `/refine [--project\|--global] [instructions]` | Refine or roll back session, project, or global harness state |
| `/copy` | Copy last assistant message to clipboard |
| `/btw <question>`, `/side <question>` | Ask an inline side question without adding it to the session; replies continue the side conversation, esc returns |
| `/export [file]` | Export session to HTML |
Expand Down Expand Up @@ -137,17 +137,27 @@ Prime Agent loads `AGENTS.md` or `CLAUDE.md` at startup from:
- parent directories, walking up from the current working directory
- the current directory

Use context files for project conventions, commands, safety rules, and preferences. Disable loading with `--no-context-files` or `-nc`.
Use context files for project conventions, commands, safety rules, and preferences. Disable loading for one run with `--no-context-files` or `-nc`.

To stop global or unrelated instructions from mixing into one repository, set `contextFiles` in
`<project>/.prime/agent/settings.json` (see [Settings](settings.md#context-files)):

```json
{ "contextFiles": { "global": false, "ancestors": false } }
```

### System Prompt Files

Replace the default system prompt with:

- `.prime/agent/SYSTEM.md` for a project
- `<project>/.prime/agent/SYSTEM.md` for a project
- `~/.prime/agent/SYSTEM.md` globally

Append to the default prompt without replacing it with `APPEND_SYSTEM.md` in either location.

Both files are resolved against the project root (the nearest `.prime/agent` directory or
enclosing repository root), so they apply from any subdirectory of the repository.

## Exporting and Sharing Sessions

Use `/export [file]` to write a session to HTML.
Expand Down
10 changes: 6 additions & 4 deletions packages/coding-agent/skills/refine/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,21 @@ IPython:
await refine.status()
await refine.run()
await refine.run("create a memory about always checking git status before committing")
await refine.run("promote the error-handling pattern to a global skill", global_=True)
await refine.run("record how this repository runs its tests", scope="project")
await refine.run("promote the error-handling pattern to a global skill", scope="global")
```

## API

- `await refine.status()` — current refine state as a dict: `pending` (whether a
requested refine is already queued for this turn) and `in_flight` (whether a
refine is currently planning or applying).
- `await refine.run(instructions=None, global_=False)` — schedule refinement.
- `await refine.run(instructions=None, scope=None)` — schedule refinement.
Returns `{"scheduled": True}` immediately, or `{"scheduled": False, "reason": ...}`
when refinement cannot start. Optional `instructions` focus the refinement on a
specific observation. Set `global_=True` to target the global harness store
(cross-session); omit for local (session-scoped) refinement.
specific observation. `scope` selects the target store: `"local"` (this session,
the default), `"project"` (this repository, across sessions), or `"global"`
(every session and project).

## Rules

Expand Down
18 changes: 11 additions & 7 deletions packages/coding-agent/skills/refine/src/refine/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,12 @@ async def status() -> dict[str, Any]:
return await host_request("refine.status")


SCOPES = ("local", "project", "global")


async def run(
instructions: str | None = None,
global_: bool = False,
scope: str | None = None,
) -> dict[str, Any]:
"""Schedule continual harness refinement.

Expand All @@ -33,18 +36,19 @@ async def run(
you automatically. Returns `{"scheduled": True}`, or
`{"scheduled": False, "reason": ...}` when refinement cannot start.
Optional `instructions` focus the refinement on a specific observation.
Set `global_=True` to target the global (cross-session) harness store;
omit for local (session-scoped) refinement.
`scope` selects the target store: "local" (this session, the default),
"project" (this repository, across sessions), or "global" (every session
and project).
"""
if instructions is not None and not isinstance(instructions, str):
raise TypeError(
f"instructions must be str or None, got {type(instructions).__name__}"
)
if not isinstance(global_, bool):
raise TypeError(f"global_ must be bool, got {type(global_).__name__}")
if scope is not None and scope not in SCOPES:
raise ValueError(f"scope must be one of {SCOPES}, got {scope!r}")
payload: dict[str, Any] = {}
if instructions is not None:
payload["instructions"] = instructions
if global_:
payload["global"] = True
if scope is not None:
payload["scope"] = scope
return await host_request("refine.run", payload)
53 changes: 53 additions & 0 deletions packages/coding-agent/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -662,3 +662,56 @@ export function getSessionDirEnvOverride(): string | undefined {
export function getDebugLogPath(): string {
return join(getAgentDir(), `${APP_NAME}-debug.log`);
}

// =============================================================================
// Project Config Paths (<project>/.prime/agent/*)
// =============================================================================

/**
* Resolve the project root for a working directory: the nearest ancestor that
* already holds a project config dir, else the nearest repository root, else the
* working directory itself. Running the agent from a subdirectory therefore uses
* the same project settings and harness state as running it from the repo root.
*/
export function getProjectDir(cwd: string): string {
// The home directory is never a project root: its config dir is the user's own
// agent dir, and a dotfiles repository there would otherwise make every project
// share one store.
const homeDir = resolve(homedir());
const resolvedCwd = resolve(cwd);
let currentDir = resolvedCwd;
let repoRoot: string | undefined;
let configRoot: string | undefined;

while (true) {
if (currentDir !== homeDir) {
if (!configRoot && existsSync(join(currentDir, CONFIG_DIR_NAME))) {
configRoot = currentDir;
}
if (!repoRoot && existsSync(join(currentDir, ".git"))) {
repoRoot = currentDir;
}
}
const parentDir = dirname(currentDir);
if (parentDir === currentDir) break;
currentDir = parentDir;
}

// A config dir above the repository root belongs to something else (an
// enclosing checkout or a home-like directory), so the repository wins.
if (repoRoot && (!configRoot || !isSameOrInside(configRoot, repoRoot))) {
return repoRoot;
}
return configRoot ?? resolvedCwd;
}

function isSameOrInside(target: string, root: string): boolean {
if (target === root) return true;
const prefix = root.endsWith(sep) ? root : `${root}${sep}`;
return target.startsWith(prefix);
}

/** Get the project config directory (e.g., <repo>/.prime/agent/) */
export function getProjectConfigDir(cwd: string): string {
return join(getProjectDir(cwd), CONFIG_DIR_NAME);
}
Loading