[[task]]
name = "prompt-templates"
agent = "codex"
skills = ["implementer"]
prompt = """
Add built-in prompt template support via `aid run codex --template bug-fix "description"`.
GOAL: Templates are markdown files in ~/.aid/templates/ that wrap user prompts with structured methodology. They complement skills (which inject methodology sections) by providing full prompt scaffolding.
IMPLEMENTATION:
1. Create src/templates.rs (extend or replace the existing minimal templates.rs):
pub fn list_templates() -> Vec<String> — scan ~/.aid/templates/ for .md files, return stems
pub fn load_template(name: &str) -> Result<String> — read template file content
pub fn apply_template(template_content: &str, user_prompt: &str) -> String — replace {{prompt}} placeholder with user prompt
2. In src/main.rs Commands::Run, add:
#[arg(long)]
template: Option<String>,
3. In src/cmd/run.rs RunArgs, add: pub template: Option<String>
In run(), after resolving skills but before dispatch, if template is set:
- Load the template via templates::load_template()
- Apply it: effective_prompt = templates::apply_template(&template_content, &args.prompt)
- Use effective_prompt as the prompt sent to the agent
4. In src/main.rs Commands::Config, add a Templates variant (like Skills and Agents):
aid config templates — list available templates
5. Ship 3 default templates (create in a new directory default-templates/ for reference):
- bug-fix.md: structured reproduction → root cause → fix → verify workflow
- feature.md: understand context → implement → test → document workflow
- refactor.md: map dependencies → make change → verify behavior preserved workflow
Each template should have {{prompt}} as the placeholder for the user's actual task description.
6. Add test for apply_template replacing {{prompt}}.
CONSTRAINTS:
- Create/modify: src/templates.rs, src/main.rs, src/cmd/run.rs, src/cmd/config.rs
- Create: default-templates/bug-fix.md, default-templates/feature.md, default-templates/refactor.md
- Keep templates.rs under 60 lines
- Do NOT reformat existing code
- cargo check and cargo test must pass
"""
dir = "."
worktree = "feat/prompt-templates"
verify = "auto"
[[task]]
name = "webhook-notifications"
agent = "codex"
skills = ["implementer"]
prompt = """
Add webhook notification support for task completion events.
GOAL: Configure webhooks in config.toml that fire on task completion, enabling Slack/Discord/custom notifications.
IMPLEMENTATION:
1. In src/config.rs, add webhook config:
#[derive(Debug, Clone, Deserialize)]
pub struct WebhookConfig {
pub name: String,
pub url: String,
#[serde(default)]
pub on_done: bool, // fire on task success
#[serde(default)]
pub on_failed: bool, // fire on task failure
#[serde(default)]
pub headers: Vec<(String, String)>, // custom headers
}
Add to AidConfig:
#[serde(default)]
pub webhooks: Vec<WebhookConfig>,
Config.toml example:
[[webhook]]
name = "slack-notify"
url = "https://hooks.slack.com/..."
on_done = true
on_failed = true
2. Create src/webhook.rs (~60 lines):
pub async fn fire_webhooks(config: &AidConfig, task: &Task, status: &str) {
for webhook in &config.webhooks {
if (status == "done" && webhook.on_done) || (status == "failed" && webhook.on_failed) {
send_webhook(webhook, task).await;
}
}
}
async fn send_webhook(webhook: &WebhookConfig, task: &Task) {
// Use std::process::Command to call curl (avoid adding reqwest dependency)
// POST JSON body: { "task_id": "...", "agent": "...", "status": "...", "prompt": "...", "duration_ms": ... }
// Fire and forget — log errors but don't block
}
3. In src/background.rs run_task(), after recording completion, call fire_webhooks().
Also in src/cmd/run.rs after foreground task completes, call fire_webhooks().
4. Add test for webhook config parsing.
CONSTRAINTS:
- Create: src/webhook.rs (under 80 lines)
- Modify: src/config.rs, src/background.rs, src/cmd/run.rs, src/main.rs (add mod webhook)
- Do NOT add reqwest or any HTTP client dependency — use curl via Command
- Do NOT reformat existing code
- cargo check and cargo test must pass
"""
dir = "."
worktree = "feat/webhooks"
verify = "auto"
[[task]]
name = "agent-benchmark"
agent = "codex"
skills = ["implementer"]
prompt = """
Add `aid benchmark` command to dispatch the same task to multiple agents and compare results.
GOAL: `aid benchmark "Fix the truncate bug" --agents codex,opencode --dir .` dispatches the task to both agents in parallel worktrees, waits for completion, and produces a comparison report.
IMPLEMENTATION:
1. In src/main.rs Commands enum, add:
/// Benchmark a task across multiple agents
Benchmark {
/// Task prompt
prompt: String,
/// Comma-separated agents to compare
#[arg(long)]
agents: String,
/// Working directory
#[arg(short, long)]
dir: Option<String>,
/// Verify command
#[arg(long, num_args = 0..=1, default_missing_value = "auto")]
verify: Option<String>,
},
2. Create src/cmd/benchmark.rs (~100 lines):
pub async fn run(store: Arc<Store>, prompt: String, agents: String, dir: Option<String>, verify: Option<String>) -> Result<()> {
let agent_list: Vec<&str> = agents.split(',').map(|s| s.trim()).collect();
let mut task_ids = Vec::new();
// Dispatch to each agent in parallel with unique worktree branches
for agent_name in &agent_list {
let branch = format!("bench/{agent_name}");
let run_args = RunArgs { agent_name, prompt, dir, worktree: Some(branch), verify, bg: true, ... };
let task_id = cmd::run::run(store.clone(), run_args).await?;
task_ids.push((agent_name.to_string(), task_id));
}
// Wait for all tasks to complete
println!("Waiting for {} agents...", agent_list.len());
// Poll store until all tasks have terminal status (Done/Failed)
loop {
let all_done = task_ids.iter().all(|(_, id)| {
store.get_task(id.as_str()).ok().flatten()
.map(|t| t.status.is_terminal()).unwrap_or(false)
});
if all_done { break; }
tokio::time::sleep(Duration::from_secs(3)).await;
}
// Print comparison report
println!("\n=== Benchmark Results ===");
for (agent, task_id) in &task_ids {
let task = store.get_task(task_id.as_str())?.unwrap();
let duration = task.duration_ms.map(|ms| format!("{}s", ms/1000)).unwrap_or("-".into());
let tokens = task.tokens.map(|t| t.to_string()).unwrap_or("-".into());
let cost = cost::format_cost(task.cost_usd);
println!("{:<12} {:<8} {:<10} {:<10} {:<8}", agent, task.status.label(), duration, tokens, cost);
}
}
3. Wire in main.rs match block.
4. Add mod benchmark to src/cmd/mod.rs.
CONSTRAINTS:
- Create: src/cmd/benchmark.rs (under 120 lines)
- Modify: src/main.rs, src/cmd/mod.rs
- Do NOT reformat existing code
- cargo check and cargo test must pass
"""
dir = "."
worktree = "feat/benchmark"
verify = "auto"
[[task]]
name = "multi-repo-dispatch"
agent = "codex"
skills = ["implementer"]
prompt = """
Add multi-repo task dispatch: `aid run codex "task" --repo /path/to/other-project`.
GOAL: Allow dispatching tasks to repos other than the current directory.
This is different from --dir (which sets the agent's working directory within the current repo).
--repo specifies a completely different git repository, and aid creates the worktree there.
IMPLEMENTATION:
1. In src/main.rs Commands::Run, add:
/// Target repository path (defaults to current dir's git root)
#[arg(long)]
repo: Option<String>,
2. In src/cmd/run.rs RunArgs, add: pub repo: Option<String>
3. In run(), when --repo is set:
- Use repo path as the base for worktree creation (instead of current dir)
- Set the agent's --dir to the worktree path within that repo
- Store the repo path in the task record for reference
4. In src/types.rs Task, add:
pub repo_path: Option<String>,
5. In src/store.rs, add repo_path column to tasks table (in migrate()):
ALTER TABLE tasks ADD COLUMN repo_path TEXT;
6. Show repo_path in `aid board` when it's set (add a column or show in task detail).
7. In src/cmd/run.rs where worktree is created, if repo is set:
- Change to use the repo path as the git root for worktree::create_worktree()
- The worktree will be created as a subdirectory of the repo's .git/worktrees
CONSTRAINTS:
- Modify: src/main.rs, src/cmd/run.rs, src/types.rs, src/store.rs, src/board.rs
- ~30 lines of new logic
- Do NOT reformat existing code
- Add test for migration adding repo_path column
- cargo check and cargo test must pass
"""
dir = "."
worktree = "feat/multi-repo"
verify = "auto"