lean_ctx/core/terse/
rules_inject.rs1use crate::core::config::CompressionLevel;
9
10const COMPRESSION_BLOCK_START: &str = "<!-- lean-ctx-compression -->";
11const COMPRESSION_BLOCK_END: &str = "<!-- /lean-ctx-compression -->";
12
13pub fn inject(level: &CompressionLevel) -> usize {
16 let prompt = super::agent_prompts::build_prompt_block(level);
17 let prompt_ascii = super::agent_prompts::build_prompt_block_for_client(level, "cursor");
18 let block = |p: &str| {
19 if p.is_empty() {
20 String::new()
21 } else {
22 format!("{COMPRESSION_BLOCK_START}\n{p}\n{COMPRESSION_BLOCK_END}")
23 }
24 };
25
26 let home = crate::core::home::resolve_home_dir().unwrap_or_default();
27 let cwd = std::env::current_dir().unwrap_or_default();
28 let mut updated = 0;
29
30 let cursor_paths: Vec<std::path::PathBuf> = vec![
31 home.join(".cursor/rules/lean-ctx.mdc"),
32 cwd.join(".cursorrules"),
33 ];
34 let other_paths: Vec<std::path::PathBuf> = vec![
35 cwd.join("AGENTS.md"),
36 cwd.join(".claude/rules/lean-ctx.md"),
37 cwd.join(".kiro/steering/lean-ctx.md"),
38 home.join(".config/crush/rules/lean-ctx.md"),
39 home.join(".qoder/rules/lean-ctx.md"),
40 ];
41
42 for path in cursor_paths {
43 if path.exists() {
44 if let Ok(content) = std::fs::read_to_string(&path) {
45 let new_content = upsert_block(&content, &block(&prompt_ascii));
46 if new_content != content {
47 let _ = std::fs::write(&path, &new_content);
48 updated += 1;
49 }
50 }
51 }
52 }
53
54 for path in other_paths {
55 if path.exists() {
56 if let Ok(content) = std::fs::read_to_string(&path) {
57 let new_content = upsert_block(&content, &block(&prompt));
58 if new_content != content {
59 let _ = std::fs::write(&path, &new_content);
60 updated += 1;
61 }
62 }
63 }
64 }
65
66 updated
67}
68
69fn upsert_block(content: &str, block: &str) -> String {
70 if content.contains(COMPRESSION_BLOCK_START) {
71 crate::marked_block::replace_marked_block(
72 content,
73 COMPRESSION_BLOCK_START,
74 COMPRESSION_BLOCK_END,
75 block,
76 )
77 } else if block.is_empty() {
78 content.to_string()
79 } else {
80 let mut out = content.trim_end().to_string();
81 out.push_str("\n\n");
82 out.push_str(block);
83 out.push('\n');
84 out
85 }
86}