lean_ctx/rules_inject/
content.rs1use std::path::{Path, PathBuf};
8
9use super::RulesFormat;
10use crate::core::config::CompressionLevel;
11use crate::core::rules_canonical::{self as rc, Wrapper};
12
13pub(super) fn cursor_wrapper_for_mdc(mdc_path: &Path) -> Wrapper {
19 let covered = mdc_path
20 .ancestors()
21 .find(|path| {
22 path.file_name()
23 .is_some_and(|name| name == std::ffi::OsStr::new(".cursor"))
24 })
25 .is_some_and(|cursor_dir| {
26 crate::core::rules_channel::cursor_hooks_json_covers(&cursor_dir.join("hooks.json"))
27 });
28 if covered {
29 Wrapper::HookCovered
30 } else {
31 Wrapper::Dedicated
32 }
33}
34
35pub(crate) fn cursor_mdc_document(body: &str) -> String {
39 format!(
40 "---\n\
41 description: \"lean-ctx: context compression layer — \
42 tool guidance in rule body.\"\n\
43 globs: **/*\n\
44 alwaysApply: true\n\
45 ---\n\n\
46 {body}"
47 )
48}
49
50pub(super) fn rules_content(
51 format: &RulesFormat,
52 level: CompressionLevel,
53 wrapper: Wrapper,
54 tool_profile: &crate::core::tool_profiles::ToolProfile,
55) -> String {
56 let shadow = crate::core::config::Config::load().shadow_mode;
57 match format {
58 RulesFormat::SharedMarkdown => rc::render(shadow, Wrapper::Shared, level, tool_profile),
59 RulesFormat::DedicatedMarkdown => {
60 rc::render(shadow, Wrapper::Dedicated, level, tool_profile)
61 }
62 RulesFormat::CursorMdc => {
63 cursor_mdc_document(&rc::render(shadow, wrapper, level, tool_profile))
64 }
65 }
66}
67
68pub fn opencode_dedicated_rules_path(home: &std::path::Path) -> PathBuf {
69 home.join(".config/opencode/rules/lean-ctx.md")
70}
71
72pub fn gemini_dedicated_rules_path(home: &std::path::Path) -> PathBuf {
73 home.join(".gemini").join(GEMINI_DEDICATED_CONTEXT_FILENAME)
74}
75
76pub const GEMINI_DEDICATED_CONTEXT_FILENAME: &str = "LEANCTX.md";