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
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,9 @@ Options:
-C string
Change to directory before doing anything. (default ".")
-d value
Remote directory containing rules and tasks. Can be specified multiple times. Supports various protocols via go-getter (http://, https://, git::, s3::, etc.).
Directory containing rules and tasks (strict: errors are fatal). Can be specified multiple times. Supports various protocols via go-getter (http://, https://, git::, s3::, file:// etc.).
-D value
Directory containing rules and tasks (lenient: errors are warnings). Can be specified multiple times. Supports various protocols via go-getter (http://, https://, git::, s3::, file:// etc.).
-m string
Go Getter URL to a manifest file containing search paths (one per line). Every line is included as-is.
-p value
Expand All @@ -164,7 +166,9 @@ Options:
Include rules with matching frontmatter. Can be specified multiple times as key=value.
Note: Only matches top-level YAML fields in frontmatter.
-a string
Target agent to use. Required when using -w to write rules to the agent's user rules path. Supported agents: cursor, opencode, copilot, claude, gemini, augment, windsurf, codex.
Target agent to use (strict: errors are fatal). Required when using -w to write rules to the agent's user rules path. Supported agents: cursor, opencode, copilot, claude, gemini, augment, windsurf, codex.
-A string
Target agent with lenient error handling (errors are warnings, missing skill names inferred from directory). Mutually exclusive with -a. Supported agents: cursor, opencode, copilot, claude, gemini, augment, windsurf, codex.
-w Write rules to agent's config file and output only task to stdout. Requires agent (via task or -a flag).
--skip-bootstrap
Skip discovering rules, skills, and running bootstrap scripts.
Expand Down
4 changes: 3 additions & 1 deletion SPECIFICATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -1062,10 +1062,12 @@ Writes rules to: `~/.github/agents/AGENTS.md`

### 10.1 Search Path Order

1. Directories specified via `-d` flags (in order)
1. Directories specified via `-d` (strict) or `-D` (lenient) flags (in order)
2. Working directory (auto-added): `.`, parent dirs for some files
3. User home directory (auto-added): `~`

**Lenient search paths** (`-D`): Errors are logged as warnings and problematic files are skipped instead of causing a fatal error. For skills with a missing `name` field, the name is inferred from the directory name.

### 10.2 Task Discovery

**Search locations (in order):**
Expand Down
4 changes: 3 additions & 1 deletion docs/reference/search-paths.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ Complete reference for where the CLI searches for task files and rule files.

## Search Paths Overview

The CLI searches for rules and tasks in directories specified via the `-d` flag. The working directory (`-C` or current directory) and home directory (`~`) are **automatically added** to the search paths, so they don't need to be specified explicitly.
The CLI searches for rules and tasks in directories specified via the `-d` (strict) or `-D` (lenient) flags. The working directory (`-C` or current directory) and home directory (`~`) are **automatically added** as strict search paths, so they don't need to be specified explicitly.

**Lenient search paths** (`-D`): Errors are logged as warnings and problematic files are skipped instead of causing a fatal error. For skills with a missing `name` field, the name is inferred from the directory name. This is useful for third-party or shared directories where you don't control file quality.

All directories (local and remote) are processed via go-getter, which downloads remote directories to temporary locations and processes local directories directly.

Expand Down
54 changes: 37 additions & 17 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,27 @@ import (
)

var (
errInvalidUsage = errors.New("invalid usage: expected one task name argument and optional user-prompt")
errWriteRulesNoAgent = errors.New("-w flag requires an agent to be specified (via task 'agent' field or -a flag)")
errNoUserRulePath = errors.New("no user rule path available for agent")
errRulesPathEscapesHome = errors.New("rules path escapes home directory")
errInvalidUsage = errors.New("invalid usage: expected one task name argument and optional user-prompt")
errWriteRulesNoAgent = errors.New("-w flag requires an agent to be specified (via task 'agent' field or -a flag)")
errNoUserRulePath = errors.New("no user rule path available for agent")
errRulesPathEscapesHome = errors.New("rules path escapes home directory")
errAgentFlagsMutExcl = errors.New("-a and -A flags are mutually exclusive")
)

type cliConfig struct {
workDir string
resume bool
skipBootstrap bool
writeRules bool
agent codingcontext.Agent
params taskparser.Params
includes selectors.Selectors
searchPaths []string
manifestURL string
taskName string
userPrompt string
workDir string
resume bool
skipBootstrap bool
writeRules bool
agent codingcontext.Agent
lenientAgent codingcontext.Agent
params taskparser.Params
includes selectors.Selectors
searchPaths []string
lenientSearchPaths []string
manifestURL string
taskName string
userPrompt string
}

func main() {
Expand Down Expand Up @@ -70,12 +73,14 @@ func run(ctx context.Context, logger *slog.Logger) error {
codingcontext.WithParams(cfg.params),
codingcontext.WithSelectors(cfg.includes),
codingcontext.WithSearchPaths(cfg.searchPaths...),
codingcontext.WithLenientSearchPaths(cfg.lenientSearchPaths...),
codingcontext.WithLogger(logger),
codingcontext.WithResume(cfg.resume),
codingcontext.WithBootstrap(!cfg.skipBootstrap),
codingcontext.WithAgent(cfg.agent),
codingcontext.WithManifestURL(cfg.manifestURL),
codingcontext.WithUserPrompt(cfg.userPrompt),
codingcontext.WithAgent(cfg.agent),
codingcontext.WithLenientAgent(cfg.lenientAgent),
)

result, err := cc.Run(ctx, cfg.taskName)
Expand Down Expand Up @@ -128,14 +133,25 @@ func parseFlags(logger *slog.Logger) (*cliConfig, error) {
flag.Var(&cfg.agent, "a",
"Target agent to use. Required when using -w to write rules to the agent's user rules path. "+
"Supported agents: cursor, opencode, copilot, claude, gemini, augment, windsurf, codex.")
flag.Var(&cfg.lenientAgent, "A",
"Target agent with lenient error handling (errors are warnings, missing skill names inferred from directory). "+
"Mutually exclusive with -a. Supported agents: cursor, opencode, copilot, claude, gemini, augment, windsurf, codex.")
flag.Var(&cfg.params, "p", "Parameter to substitute in the prompt. Can be specified multiple times as key=value.")
flag.Var(&cfg.includes, "s", "Include rules with matching frontmatter. Can be specified multiple times as key=value.")
flag.Func("d",
"Directory containing rules and tasks. Can be specified multiple times. "+
"Directory containing rules and tasks (strict: errors are fatal). Can be specified multiple times. "+
"Supports various protocols via go-getter (http://, https://, git::, s3::, file:// etc.).",
func(s string) error {
cfg.searchPaths = append(cfg.searchPaths, s)

return nil
})
flag.Func("D",
"Directory containing rules and tasks (lenient: errors are warnings). Can be specified multiple times. "+
"Supports various protocols via go-getter (http://, https://, git::, s3::, file:// etc.).",
func(s string) error {
cfg.lenientSearchPaths = append(cfg.lenientSearchPaths, s)

return nil
})
flag.StringVar(&cfg.manifestURL, "m", "",
Expand Down Expand Up @@ -165,6 +181,10 @@ func setupUsage(logger *slog.Logger) {
}

func parseFlagArgs(cfg *cliConfig) (*cliConfig, error) {
if cfg.agent.IsSet() && cfg.lenientAgent.IsSet() {
return nil, errAgentFlagsMutExcl
}

args := flag.Args()

const maxArgs = 2
Expand Down
Loading
Loading