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
9 changes: 9 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
- 'release/**'
merge_group:
workflow_dispatch:
# Manual trigger - no inputs needed, uses repository variables

Check warning on line 16 in .github/workflows/ci.yml

View workflow job for this annotation

GitHub Actions / Lint (YAML)

16:5 [comments-indentation] comment not indented like content

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
Expand Down Expand Up @@ -153,14 +153,14 @@
- name: 'Install shellcheck' # Actionlint uses shellcheck
run: |-
mkdir -p "${RUNNER_TEMP}/shellcheck"
curl -sSLo "${RUNNER_TEMP}/.shellcheck.txz" "https://github.com/koalaman/shellcheck/releases/download/v${SHELLCHECK_VERSION}/shellcheck-v${SHELLCHECK_VERSION}.linux.x86_64.tar.xz"

Check warning on line 156 in .github/workflows/ci.yml

View workflow job for this annotation

GitHub Actions / Lint (YAML)

156:121 [line-length] line too long (189 > 120 characters)
tar -xf "${RUNNER_TEMP}/.shellcheck.txz" -C "${RUNNER_TEMP}/shellcheck" --strip-components=1
echo "${RUNNER_TEMP}/shellcheck" >> "${GITHUB_PATH}"

- name: 'Install actionlint'
run: |-
mkdir -p "${RUNNER_TEMP}/actionlint"
curl -sSLo "${RUNNER_TEMP}/.actionlint.tgz" "https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VERSION}/actionlint_${ACTIONLINT_VERSION}_linux_amd64.tar.gz"

Check warning on line 163 in .github/workflows/ci.yml

View workflow job for this annotation

GitHub Actions / Lint (YAML)

163:121 [line-length] line too long (184 > 120 characters)
tar -xzf "${RUNNER_TEMP}/.actionlint.tgz" -C "${RUNNER_TEMP}/actionlint"
echo "${RUNNER_TEMP}/actionlint" >> "${GITHUB_PATH}"

Expand Down Expand Up @@ -268,6 +268,10 @@
run: |-
npm run lint:genai-enclave

- name: 'Run legacy-global-path guard (#2606)'
run: |-
npm run lint:legacy-paths

- name: 'Run GenAI importer ratchet'
run: |-
npm run lint:genai-inventory
Expand Down Expand Up @@ -787,6 +791,11 @@
CI: true
run: npm run test:scripts

- name: 'Run shell-script behavioral tests (#2606)'
env:
CI: true
run: npm run test:shell

- name: 'Smoke test CLI entry (launcher -> Bun -> TypeScript, no Node)'
run: './packages/cli/bin/llxprt --version'

Expand Down
2 changes: 1 addition & 1 deletion dev-docs/cherrypicking.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ git cherry-pick <commit-hash>
- Gemini-specific release commits
- **Emoji-related commits** - LLxprt is emoji-free by design. Skip any commits that add, fix, or modify emoji handling (e.g., `a64394a4f`, `348fa6c7c`)
- **Automatic model routing** - LLxprt does not do automatic model routing/selection. Developers explicitly configure and choose models via profiles. Skip any commits that add `model: "auto"`, `ModelRouterService`, or automatic model selection for subagents/agents.
- **Upstream agent/subagent architecture** - LLxprt has its own subagent system (`SubagentManager`, `~/.llxprt/subagents/`, `task()` tool, `/subagent` command) that is completely different from upstream's `AgentRegistry`, `DelegateToAgentTool`, `/agents` command, and filesystem-scanned `.gemini/agents/` definitions. Skip upstream agent discovery/management commits. Upstream A2A (Agent-to-Agent) remote agent features are tracked separately in issue #1675.
- **Upstream agent/subagent architecture** - LLxprt has its own subagent system (`SubagentManager`, `<config>/subagents/` per [Application Directories](../docs/reference/application-directories.md), `task()` tool, `/subagent` command) that is completely different from upstream's `AgentRegistry`, `DelegateToAgentTool`, `/agents` command, and filesystem-scanned `.gemini/agents/` definitions. Skip upstream agent discovery/management commits. Upstream A2A (Agent-to-Agent) remote agent features are tracked separately in issue #1675.

#### Features Reimplemented (Don't Cherry-pick):

Expand Down
4 changes: 2 additions & 2 deletions dev-docs/profileandsettings.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ Ephemeral settings are runtime configuration values that can be changed during a

### Profiles

Profiles are JSON files stored in `~/.llxprt/profiles/` that contain:
Profiles are JSON files stored in `<config>/profiles/` (see [Application Directories](../docs/reference/application-directories.md)) that contain:

- `version` - Profile format version
- `provider` - Provider name (e.g., "openai", "anthropic", "gemini")
- `model` - Model identifier
- `modelParams` - Model-specific parameters (e.g., temperature)
- `ephemeralSettings` - All runtime configuration settings

Example profile (`~/.llxprt/profiles/synthetic.json`):
Example profile (`<config>/profiles/synthetic.json`, see [Application Directories](../docs/reference/application-directories.md)):

```json
{
Expand Down
2 changes: 1 addition & 1 deletion docs/EMOJI-FILTER.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Use the `/set` command to configure for the current session:

### 2. Default Configuration (Persistent)

Add to your `~/.llxprt/settings.json` file:
Add to your user [settings.json](./reference/application-directories.md) file (in LLxprt's config directory):

```json
{
Expand Down
4 changes: 2 additions & 2 deletions docs/architecture/message-bus-architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -743,15 +743,15 @@ evaluate(toolName: string, args: Record<string, unknown>, serverName?: string):
**CLI Command:**

```bash
llxprt test-policy ~/.llxprt/my-policy.toml \
llxprt test-policy /absolute/path/to/my-policy.toml \
--tool edit \
--args '{"file_path": "/etc/hosts"}'
```

**Output:**

```
Testing policy: ~/.llxprt/my-policy.toml
Testing policy: /absolute/path/to/my-policy.toml

Rule matched:
Priority: 2.7
Expand Down
6 changes: 3 additions & 3 deletions docs/checkpointing.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ llxprt --delete-session 3

### How It Works

Sessions are recorded to `~/.llxprt/sessions/`. Each session file contains the full conversation history — model responses, tool calls and results, and thinking blocks. When you resume, the conversation is replayed into the model's context so it picks up with full awareness of what happened before.
Sessions are recorded to LLxprt's [log/state directory](./reference/application-directories.md) under `<log>/tmp/<project_hash>/` (overridable via `LLXPRT_LOG_HOME`). Each session file contains the full conversation history — model responses, tool calls and results, and thinking blocks. When you resume, the conversation is replayed into the model's context so it picks up with full awareness of what happened before.

Sessions are per-project. Running `llxprt --continue` in a different directory shows that directory's sessions.

Expand Down Expand Up @@ -91,7 +91,7 @@ It's disabled by default. Enable it with `--checkpointing`:
llxprt --checkpointing
```

Or in `~/.llxprt/settings.json`:
Or in your [user `settings.json`](./reference/application-directories.md):

```json
{
Expand All @@ -101,7 +101,7 @@ Or in `~/.llxprt/settings.json`:
}
```

When enabled, LLxprt creates a shadow git snapshot (in `~/.llxprt/history/<project_hash>`, separate from your project's git) each time a `write_file` or `replace` tool is about to run. It also saves the conversation state and tool call details to `~/.llxprt/tmp/<project_hash>/checkpoints/`.
When enabled, LLxprt creates a shadow git snapshot (in `<data>/history/<project_hash>` within LLxprt's [data directory](./reference/application-directories.md), separate from your project's git) each time a `write_file` or `replace` tool is about to run. It also saves the conversation state and tool call details to `<log>/tmp/<project_hash>/checkpoints/` under LLxprt's [log/state directory](./reference/application-directories.md).

The `/restore` command (only available when checkpointing is enabled) lets you roll back:

Expand Down
18 changes: 10 additions & 8 deletions docs/cli/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ Extensions are managed from the terminal with `llxprt extensions` (not slash com

## Custom Commands

You can create your own slash commands by placing executable files in `~/.llxprt/commands/` or `.llxprt/commands/` in your project.
You can create your own slash commands by placing executable files in your [user `commands/` directory](../reference/application-directories.md) (`<config>/commands/`) or `.llxprt/commands/` in your project.

### How Custom Commands Work

Expand All @@ -141,7 +141,7 @@ When you type `/mycommand`, LLxprt looks for a matching executable in the comman
**Execution flow:**

1. User types `/mycommand some arguments`
2. LLxprt finds `~/.llxprt/commands/mycommand` (or `.llxprt/commands/mycommand`)
2. LLxprt finds `<config>/commands/mycommand` (or `.llxprt/commands/mycommand` in your project)
3. Runs the executable with the arguments
4. The command's stdout is sent to the model as context

Expand All @@ -158,7 +158,7 @@ When you type `/mycommand`, LLxprt looks for a matching executable in the comman
- **Editing commands:** Delete with `x`, change with `c`, insert with `i`, `a`, `o`, `O`; complex operations like `dd`, `cc`, `dw`, `cw`
- **Count support:** Prefix commands with numbers (e.g., `3h`, `5w`, `10G`)
- **Repeat last command:** Use `.` to repeat the last editing operation
- **Persistent setting:** Vim mode preference is saved to `~/.llxprt/settings.json` and restored between sessions
- **Persistent setting:** Vim mode preference is saved to your [user settings.json](../reference/application-directories.md) and restored between sessions
- **Status indicator:** When enabled, shows `[NORMAL]` or `[INSERT]` in the footer

- **`/init`**
Expand All @@ -174,7 +174,7 @@ Custom commands allow you to save and reuse your favorite or most frequently use

LLxprt Code discovers commands from two locations, loaded in a specific order:

1. **User Commands (Global):** Located in `~/.llxprt/commands/`. These commands are available in any project you are working on.
1. **User Commands (Global):** Located in `<config>/commands/` (see [Application Directories](../reference/application-directories.md)). These commands are available in any project you are working on.
2. **Project Commands (Local):** Located in `<your-project-root>/.llxprt/commands/`. These commands are specific to the current project and can be checked into version control to be shared with your team.

If a command in the project directory has the same name as a command in the user directory, the **project command will always be used.** This allows projects to override global commands with project-specific versions.
Expand All @@ -183,7 +183,7 @@ If a command in the project directory has the same name as a command in the user

The name of a command is determined by its file path relative to its `commands` directory. Subdirectories are used to create namespaced commands, with the path separator (`/` or `\`) being converted to a colon (`:`).

- A file at `~/.llxprt/commands/test.toml` becomes the command `/test`.
- A file at `<config>/commands/test.toml` (see [Application Directories](../reference/application-directories.md)) becomes the command `/test`.
- A file at `<project>/.llxprt/commands/git/commit.toml` becomes the namespaced command `/git:commit`.

#### TOML File Format (v1)
Expand Down Expand Up @@ -339,14 +339,16 @@ Let's create a global command that asks the model to refactor a piece of code.
First, ensure the user commands directory exists, then create a `refactor` subdirectory for organization and the final TOML file.

```bash
mkdir -p ~/.llxprt/commands
cat > ~/.llxprt/commands/git-diff << 'EOF'
mkdir -p "${LLXPRT_CONFIG_HOME:-$HOME/.config/llxprt-code}/commands"
cat > "${LLXPRT_CONFIG_HOME:-$HOME/.config/llxprt-code}/commands/git-diff" << 'EOF'
#!/bin/bash
git diff --stat
EOF
chmod +x ~/.llxprt/commands/git-diff
chmod +x "${LLXPRT_CONFIG_HOME:-$HOME/.config/llxprt-code}/commands/git-diff"
```

> The path above uses the Linux config default; see [Application Directories](../reference/application-directories.md) for the macOS/Windows equivalents and the `LLXPRT_CONFIG_HOME` override.

Now `/git-diff` will show your git changes and send the output to the model.

### Command Format
Expand Down
10 changes: 5 additions & 5 deletions docs/cli/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,16 @@ Configuration is applied in the following order of precedence (lower numbers are
LLxprt Code uses JSON settings files for persistent configuration. There are four locations for these files:

- **System defaults file:**
- **Location:** `/etc/llxprt-code/system-defaults.json` (Linux), `C:\ProgramData\llxprt-code\system-defaults.json` (Windows) or `/Library/Application Support/LLxprt-Code/system-defaults.json` (macOS). The path can be overridden using the `LLXPRT_CODE_SYSTEM_DEFAULTS_PATH` environment variable.
- **Location:** `/etc/llxprt-code/system-defaults.json` (Linux), `C:\ProgramData\llxprt-code\system-defaults.json` (Windows) or `/Library/Application Support/LlxprtCode/system-defaults.json` (macOS). The path can be overridden using the `LLXPRT_SYSTEM_DEFAULTS_PATH` environment variable (a legacy alias `LLXPRT_CODE_SYSTEM_DEFAULTS_PATH` is also honored for backward compatibility).
- **Scope:** Provides a base layer of system-wide default settings. These settings have the lowest precedence and are intended to be overridden by user, project, or system override settings.
- **User settings file:**
- **Location:** `~/.llxprt/settings.json` (where `~` is your home directory).
- **Location:** Your user `settings.json` in LLxprt's [config directory](../reference/application-directories.md) (overridable via `LLXPRT_CONFIG_HOME`).
- **Scope:** Applies to all LLxprt Code sessions for the current user. User settings override system defaults.
- **Project settings file:**
- **Location:** `.llxprt/settings.json` within your project's root directory.
- **Scope:** Applies only when running LLxprt Code from that specific project. Project settings override user settings and system defaults.
- **System settings file:**
- **Location:** `/etc/llxprt-code/settings.json` (Linux), `C:\ProgramData\llxprt-code\settings.json` (Windows) or `/Library/Application Support/LLxprt-Code/settings.json` (macOS). The path can be overridden using the `LLXPRT_CODE_SYSTEM_SETTINGS_PATH` environment variable.
- **Location:** `/etc/llxprt-code/settings.json` (Linux), `C:\ProgramData\llxprt-code\settings.json` (Windows) or `/Library/Application Support/LlxprtCode/settings.json` (macOS). The path can be overridden using the `LLXPRT_SYSTEM_SETTINGS_PATH` environment variable (a legacy alias `LLXPRT_CODE_SYSTEM_SETTINGS_PATH` is also honored for backward compatibility).
- **Scope:** Applies to all LLxprt Code sessions on the system, for all users. System settings act as overrides, taking precedence over all other settings files. May be useful for system administrators at enterprises to have controls over users' LLxprt Code setups.

**Note on environment variables in settings:** String values within your `settings.json` files can reference environment variables using either `$VAR_NAME` or `${VAR_NAME}` syntax. These variables will be automatically resolved when the settings are loaded. For example, if you have an environment variable `MY_API_TOKEN`, you could use it in `settings.json` like this: `"apiKey": "$MY_API_TOKEN"`.
Expand Down Expand Up @@ -1655,13 +1655,13 @@ The CLI automatically loads environment variables from `.env` files. The loading

1. `.env` in the current directory
2. `.env` in parent directories (up to filesystem root)
3. `~/.llxprt/.env` (user-level)
3. `<config>/.env` (user-level — see [Application Directories](../reference/application-directories.md))

String values in `settings.json` can reference environment variables using `$VAR_NAME` or `${VAR_NAME}` syntax.

## Shell History

Shell command history is stored per-project at `~/.llxprt/tmp/<project_hash>/shell_history`.
Shell command history is stored per-project under LLxprt's [log/state directory](../reference/application-directories.md) at `<log>/tmp/<project_hash>/shell_history` (overridable via `LLXPRT_LOG_HOME`).

## See Also

Expand Down
31 changes: 18 additions & 13 deletions docs/cli/context-dumping.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ The `/dumpcontext` command captures complete API request/response data for debug

## Dump Location

Dumps are saved to `~/.llxprt/dumps/` with filenames in the format:
Dumps are saved to `<cache>/dumps/` (see [Application Directories](../reference/application-directories.md)) with filenames in the format:

```text
YYYYMMDD-HHMMSS-<provider>-<random>.json
Expand Down Expand Up @@ -82,10 +82,12 @@ Dumps are OpenAI API compliant and can be replayed with curl. Since the dump inc
### Extract and Send Request

```bash
# Extract the request body and send to the API
jq '.request.body' ~/.llxprt/dumps/YOUR_DUMP.json > /tmp/body.json
# Linux example: LLXPRT_CACHE_HOME -> LLXPRT_CONFIG_HOME -> Linux default.
# See Application Directories for the macOS and Windows defaults.
DUMPS="${LLXPRT_CACHE_HOME:-${LLXPRT_CONFIG_HOME:-$HOME/.cache/llxprt-code}}/dumps"
jq '.request.body' "$DUMPS/YOUR_DUMP.json" > /tmp/body.json

curl -X POST "$(jq -r '.request.url' ~/.llxprt/dumps/YOUR_DUMP.json)" \
curl -X POST "$(jq -r '.request.url' "$DUMPS/YOUR_DUMP.json")" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-d @/tmp/body.json
Expand All @@ -95,7 +97,7 @@ curl -X POST "$(jq -r '.request.url' ~/.llxprt/dumps/YOUR_DUMP.json)" \

```bash
# Pipe the body directly to curl
jq '.request.body' ~/.llxprt/dumps/YOUR_DUMP.json | \
jq '.request.body' "$DUMPS/YOUR_DUMP.json" | \
curl -X POST "https://api.openai.com/v1/chat/completions" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $OPENAI_API_KEY" \
Expand All @@ -108,7 +110,7 @@ For OpenAI-compatible providers (like local models or alternative endpoints):

```bash
# Extract URL from dump and use with custom auth
DUMP=~/.llxprt/dumps/YOUR_DUMP.json
DUMP="$DUMPS/YOUR_DUMP.json"
jq '.request.body' "$DUMP" | \
curl -X POST "$(jq -r '.request.url' "$DUMP")" \
-H "Content-Type: application/json" \
Expand All @@ -128,21 +130,21 @@ jq '{
message_count: (.request.body.messages | length),
tool_count: (.request.body.tools | length),
response_status: .response.status
}' ~/.llxprt/dumps/YOUR_DUMP.json
}' "$DUMPS/YOUR_DUMP.json"
```

### Extract Conversation History

```bash
# Show messages with roles
jq '.request.body.messages[] | {role, content: .content[:100]}' ~/.llxprt/dumps/YOUR_DUMP.json
jq '.request.body.messages[] | {role, content: .content[:100]}' "$DUMPS/YOUR_DUMP.json"
```

### List Available Tools

```bash
# Show tool names and descriptions
jq '.request.body.tools[] | {name: .function.name, description: .function.description[:50]}' ~/.llxprt/dumps/YOUR_DUMP.json
jq '.request.body.tools[] | {name: .function.name, description: .function.description[:50]}' "$DUMPS/YOUR_DUMP.json"
```

### Check Response Details
Expand All @@ -152,7 +154,7 @@ jq '.request.body.tools[] | {name: .function.name, description: .function.descri
jq '{
finish_reason: .response.body.choices[0].finish_reason,
usage: .response.body.usage
}' ~/.llxprt/dumps/YOUR_DUMP.json
}' "$DUMPS/YOUR_DUMP.json"
```

## Use Cases
Expand Down Expand Up @@ -218,9 +220,12 @@ See [Debug Logging](../debug-logging.md) for more information.
- Consider redacting sensitive data before sharing dumps

```bash
# Clean up old dumps
rm ~/.llxprt/dumps/*.json
# Clean up old dumps. This Linux example honors LLXPRT_CACHE_HOME, then
# LLXPRT_CONFIG_HOME, then the Linux default; see Application Directories for
# the macOS and Windows defaults.
CACHE_DIR="${LLXPRT_CACHE_HOME:-${LLXPRT_CONFIG_HOME:-$HOME/.cache/llxprt-code}}"
rm -f "${CACHE_DIR}/dumps/"*.json

# Or keep only recent dumps
find ~/.llxprt/dumps -name "*.json" -mtime +7 -delete
find "${CACHE_DIR}/dumps" -name "*.json" -mtime +7 -delete
```
Loading
Loading