Skip to content
Closed
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: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ no-plugin = [
# The release workflow builds the Windows target with this set.
windows-default = ['no-plugin']
loop = []
vigil = []
# Run dirge itself as an MCP server (`dirge mcp`) so another agent (e.g.
# Claude Code) can delegate implementation tasks to dirge and review them.
# Pulls rmcp's server side + stdio transport + the tool macros.
Expand Down
1 change: 1 addition & 0 deletions docs/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ Accepted top-level keys:
| `mcp_servers` | object | MCP server map when compiled with the `mcp` feature. When omitted, defaults to a single Exa Web Search server; see below. |
| `acp_servers` | object | ACP server config map when compiled with the `acp` feature. See the ACP section below. |
| `editor_open_command` | string | Opt-in editor follow-along: a command template with `{path}` and `{line}` placeholders (e.g. `"zed {path}:{line}"`, `"code --goto {path}:{line}"`). When set, dirge opens files it reads or edits in this external GUI editor, detached and non-blocking — the editor "follows along" like Zed's AI panel. `None` (unset) disables the feature entirely. |
| `vigils` | array | Vigil definitions consulted only when `--vigil` is active (compiled with the `vigil` feature). Each entry: `name`, a `trigger` (`toll` timer with `interval_secs`, `watcher` on a `path`, or `harbinger` TCP socket with `address` and `socket_mode`), an optional `reap_interval_secs` (default 30), an optional `prompt` for the observance turn, and optional `procession` (Janet) and `rite` gate. |

### Desktop Notifications

Expand Down
42 changes: 42 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,48 @@ pub enum Command {
#[arg(long = "sandbox")]
sandbox: Option<String>,
},
/// Manage vigils — list, add, remove, pause, resume, restart.
#[cfg(feature = "vigil")]
Vigil {
#[command(subcommand)]
action: VigilAction,
},
}

/// Vigil management subcommands.
#[cfg(feature = "vigil")]
#[derive(clap::Subcommand, Debug)]
pub enum VigilAction {
/// List all configured vigils and their status.
List,
/// Add a new vigil trigger.
Add {
/// Vigil name.
name: String,
/// Trigger type: toll, watcher, or harbinger.
#[arg(value_enum)]
trigger: VigilAddTrigger,
/// Additional trigger args as key=value pairs.
#[arg(trailing_var_arg = true, allow_hyphen_values = true)]
args: Vec<String>,
},
/// Remove a vigil by name.
Remove { name: String },
/// Pause a running vigil.
Pause { name: String },
/// Resume a paused vigil.
Resume { name: String },
/// Restart a vigil (stop and re-create its trigger).
Rest { name: String },
}

/// Trigger type for `dirge vigil add`.
#[cfg(feature = "vigil")]
#[derive(clap::ValueEnum, Debug, Clone)]
pub enum VigilAddTrigger {
Toll,
Watcher,
Harbinger,
}

#[derive(clap::Subcommand, Debug)]
Expand Down
88 changes: 88 additions & 0 deletions src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ use std::collections::HashMap;
use std::path::{Path, PathBuf};

use serde::Deserialize;
#[cfg(feature = "vigil")]
use serde::Serialize;

use crate::session::storage;

Expand Down Expand Up @@ -1367,6 +1369,92 @@ pub struct Config {
/// future expansion but are not honored today.
#[cfg(feature = "acp")]
pub acp_servers: Option<HashMap<String, AcpServerConfig>>,

/// Vigil definitions loaded from `config.toml` under `[vigils.<name>]`.
/// Only consulted when `--vigil` is active.
#[cfg(feature = "vigil")]
#[serde(default)]
pub vigils: Option<Vec<VigilEntry>>,
}

/// A single vigil definition from config.
#[cfg(feature = "vigil")]
#[derive(Debug, Clone, Deserialize, Serialize, Default)]
#[serde(default)]
pub struct VigilEntry {
pub name: String,
pub trigger: VigilTrigger,
#[serde(default = "default_reap_interval")]
pub reap_interval_secs: u64,
#[serde(default)]
pub prompt: String,
/// Optional Janet script for per-observance procession.
#[serde(default)]
pub procession: Option<String>,
#[serde(default)]
pub rite: Option<VigilRite>,
}

#[cfg(feature = "vigil")]
fn default_reap_interval() -> u64 {
30
}

/// What triggers a vigil to fire.
#[cfg(feature = "vigil")]
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(tag = "type", rename_all = "kebab-case")]
pub enum VigilTrigger {
/// Timer-based: fires every N seconds.
Toll { interval_secs: u64 },
/// Filesystem watcher: fires on changes under `path`.
Watcher { path: String },
/// Network socket: external process sends events to a TCP port.
Harbinger {
address: String,
#[serde(default)]
protocol: String,
/// `template` or `commands` — see `SocketMode`.
#[serde(default)]
socket_mode: SocketMode,
#[serde(default)]
commands: HashMap<String, VigilCommand>,
},
}

#[cfg(feature = "vigil")]
impl Default for VigilTrigger {
fn default() -> Self {
VigilTrigger::Toll { interval_secs: 30 }
}
}

/// Harbinger socket mode.
#[cfg(feature = "vigil")]
#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq)]
#[serde(rename_all = "kebab-case")]
pub enum SocketMode {
#[default]
Template,
Commands,
}

/// A pre-registered command for `commands` socket mode.
#[cfg(feature = "vigil")]
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct VigilCommand {
pub tool: String,
#[serde(default)]
pub args: serde_json::Map<String, serde_json::Value>,
}

/// Optional gate condition checked before an observance runs.
#[cfg(feature = "vigil")]
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
pub struct VigilRite {
pub cmd: Option<String>,
#[serde(default)]
pub git_dirty: bool,
}

impl Config {
Expand Down
1 change: 1 addition & 0 deletions src/extras/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,4 @@ pub mod session_search;
pub mod skill_db;
pub mod skills;
pub mod spec_db;
pub mod vigil_db;
Loading
Loading