diff --git a/packages/types/src/global-settings.ts b/packages/types/src/global-settings.ts
index 91b37f3d6d..19a8659e54 100644
--- a/packages/types/src/global-settings.ts
+++ b/packages/types/src/global-settings.ts
@@ -164,6 +164,7 @@ export const globalSettingsSchema = z.object({
 	maxWorkspaceFiles: z.number().optional(),
 	showRooIgnoredFiles: z.boolean().optional(),
 	enableSubfolderRules: z.boolean().optional(),
+	maxReadFileLine: z.number().optional(),
 	maxImageFileSize: z.number().optional(),
 	maxTotalImageSize: z.number().optional(),
 
diff --git a/src/core/prompts/tools/native-tools/__tests__/read_file.spec.ts b/src/core/prompts/tools/native-tools/__tests__/read_file.spec.ts
index dded7fba50..4d7fb80fdf 100644
--- a/src/core/prompts/tools/native-tools/__tests__/read_file.spec.ts
+++ b/src/core/prompts/tools/native-tools/__tests__/read_file.spec.ts
@@ -1,122 +1,53 @@
-import type OpenAI from "openai"
-import { createReadFileTool } from "../read_file"
-
-// Helper type to access function tools
-type FunctionTool = OpenAI.Chat.ChatCompletionTool & { type: "function" }
-
-// Helper to get function definition from tool
-const getFunctionDef = (tool: OpenAI.Chat.ChatCompletionTool) => (tool as FunctionTool).function
+import { createReadFileTool, DEFAULT_LINE_LIMIT } from "../read_file"
 
 describe("createReadFileTool", () => {
-	describe("single-file-per-call documentation", () => {
-		it("should indicate single-file-per-call and suggest parallel tool calls", () => {
-			const tool = createReadFileTool()
-			const description = getFunctionDef(tool).description
-
-			expect(description).toContain("exactly one file per call")
-			expect(description).toContain("multiple parallel read_file calls")
-		})
+	function getToolDesc(options = {}): string {
+		const tool = createReadFileTool(options) as any
+		return tool.function.description ?? ""
+	}
+
+	function getToolLimitParamDesc(options = {}): string {
+		const tool = createReadFileTool(options) as any
+		return tool.function.parameters.properties.limit.description ?? ""
+	}
+
+	it("uses DEFAULT_LINE_LIMIT in description when maxReadFileLine is undefined", () => {
+		const desc = getToolDesc()
+		expect(desc).toContain(`returns up to ${DEFAULT_LINE_LIMIT} lines per file`)
+		expect(desc).not.toContain("no line limit")
 	})
 
-	describe("indentation mode", () => {
-		it("should always include indentation mode in description", () => {
-			const tool = createReadFileTool()
-			const description = getFunctionDef(tool).description
-
-			expect(description).toContain("indentation")
-		})
-
-		it("should always include indentation parameter in schema", () => {
-			const tool = createReadFileTool()
-			const schema = getFunctionDef(tool).parameters as any
-
-			expect(schema.properties).toHaveProperty("indentation")
-		})
-
-		it("should include mode parameter in schema", () => {
-			const tool = createReadFileTool()
-			const schema = getFunctionDef(tool).parameters as any
-
-			expect(schema.properties).toHaveProperty("mode")
-			expect(schema.properties.mode.enum).toContain("slice")
-			expect(schema.properties.mode.enum).toContain("indentation")
-		})
-
-		it("should include offset and limit parameters in schema", () => {
-			const tool = createReadFileTool()
-			const schema = getFunctionDef(tool).parameters as any
-
-			expect(schema.properties).toHaveProperty("offset")
-			expect(schema.properties).toHaveProperty("limit")
-		})
+	it("uses DEFAULT_LINE_LIMIT in description when maxReadFileLine is -1", () => {
+		const desc = getToolDesc({ maxReadFileLine: -1 })
+		expect(desc).toContain(`returns up to ${DEFAULT_LINE_LIMIT} lines per file`)
 	})
 
-	describe("supportsImages option", () => {
-		it("should include image format documentation when supportsImages is true", () => {
-			const tool = createReadFileTool({ supportsImages: true })
-			const description = getFunctionDef(tool).description
-
-			expect(description).toContain(
-				"Automatically processes and returns image files (PNG, JPG, JPEG, GIF, BMP, SVG, WEBP, ICO, AVIF) for visual analysis",
-			)
-		})
+	it("indicates no limit in description when maxReadFileLine is 0", () => {
+		const desc = getToolDesc({ maxReadFileLine: 0 })
+		expect(desc).toContain("no line limit")
+		expect(desc).not.toContain(`returns up to ${DEFAULT_LINE_LIMIT}`)
 
-		it("should not include image format documentation when supportsImages is false", () => {
-			const tool = createReadFileTool({ supportsImages: false })
-			const description = getFunctionDef(tool).description
-
-			expect(description).not.toContain(
-				"Automatically processes and returns image files (PNG, JPG, JPEG, GIF, BMP, SVG, WEBP, ICO, AVIF) for visual analysis",
-			)
-			expect(description).toContain("may not handle other binary files properly")
-		})
-
-		it("should default supportsImages to false", () => {
-			const tool = createReadFileTool({})
-			const description = getFunctionDef(tool).description
-
-			expect(description).not.toContain(
-				"Automatically processes and returns image files (PNG, JPG, JPEG, GIF, BMP, SVG, WEBP, ICO, AVIF) for visual analysis",
-			)
-		})
-
-		it("should always include PDF and DOCX support in description", () => {
-			const toolWithImages = createReadFileTool({ supportsImages: true })
-			const toolWithoutImages = createReadFileTool({ supportsImages: false })
-
-			expect(getFunctionDef(toolWithImages).description).toContain(
-				"Supports text extraction from PDF and DOCX files",
-			)
-			expect(getFunctionDef(toolWithoutImages).description).toContain(
-				"Supports text extraction from PDF and DOCX files",
-			)
-		})
+		const limitDesc = getToolLimitParamDesc({ maxReadFileLine: 0 })
+		expect(limitDesc).toContain("no limit")
 	})
 
-	describe("tool structure", () => {
-		it("should have correct tool name", () => {
-			const tool = createReadFileTool()
-
-			expect(getFunctionDef(tool).name).toBe("read_file")
-		})
+	it("uses custom limit in description when maxReadFileLine is a positive number", () => {
+		const desc = getToolDesc({ maxReadFileLine: 500 })
+		expect(desc).toContain("returns up to 500 lines per file")
+		// Should not mention DEFAULT_LINE_LIMIT as the line limit (but MAX_LINE_LENGTH=2000 chars is ok)
+		expect(desc).not.toContain(`up to ${DEFAULT_LINE_LIMIT} lines`)
 
-		it("should be a function type tool", () => {
-			const tool = createReadFileTool()
-
-			expect(tool.type).toBe("function")
-		})
-
-		it("should have strict mode enabled", () => {
-			const tool = createReadFileTool()
-
-			expect(getFunctionDef(tool).strict).toBe(true)
-		})
+		const limitDesc = getToolLimitParamDesc({ maxReadFileLine: 500 })
+		expect(limitDesc).toContain("500")
+	})
 
-		it("should require path parameter", () => {
-			const tool = createReadFileTool()
-			const schema = getFunctionDef(tool).parameters as any
+	it("includes image support note when supportsImages is true", () => {
+		const desc = getToolDesc({ supportsImages: true })
+		expect(desc).toContain("image files")
+	})
 
-			expect(schema.required).toContain("path")
-		})
+	it("does not include image support note when supportsImages is false", () => {
+		const desc = getToolDesc({ supportsImages: false })
+		expect(desc).not.toContain("image files")
 	})
 })
diff --git a/src/core/prompts/tools/native-tools/index.ts b/src/core/prompts/tools/native-tools/index.ts
index 758914d2d6..cfeb374aa1 100644
--- a/src/core/prompts/tools/native-tools/index.ts
+++ b/src/core/prompts/tools/native-tools/index.ts
@@ -31,6 +31,8 @@ export type { ReadFileToolOptions } from "./read_file"
 export interface NativeToolsOptions {
 	/** Whether the model supports image processing (default: false) */
 	supportsImages?: boolean
+	/** Maximum line limit for read_file tool. -1 or undefined = DEFAULT_LINE_LIMIT, 0 = no limit */
+	maxReadFileLine?: number
 }
 
 /**
@@ -40,10 +42,11 @@ export interface NativeToolsOptions {
  * @returns Array of native tool definitions
  */
 export function getNativeTools(options: NativeToolsOptions = {}): OpenAI.Chat.ChatCompletionTool[] {
-	const { supportsImages = false } = options
+	const { supportsImages = false, maxReadFileLine } = options
 
 	const readFileOptions: ReadFileToolOptions = {
 		supportsImages,
+		maxReadFileLine,
 	}
 
 	return [
diff --git a/src/core/prompts/tools/native-tools/read_file.ts b/src/core/prompts/tools/native-tools/read_file.ts
index af781556ef..ff93cfbd0c 100644
--- a/src/core/prompts/tools/native-tools/read_file.ts
+++ b/src/core/prompts/tools/native-tools/read_file.ts
@@ -34,6 +34,8 @@ function getReadFileSupportsNote(supportsImages: boolean): string {
 export interface ReadFileToolOptions {
 	/** Whether the model supports image processing (default: false) */
 	supportsImages?: boolean
+	/** Maximum line limit for read_file tool. -1 or undefined = DEFAULT_LINE_LIMIT, 0 = no limit */
+	maxReadFileLine?: number
 }
 
 // ─── Schema Builder ───────────────────────────────────────────────────────────
@@ -58,7 +60,21 @@ export interface ReadFileToolOptions {
  * @returns Native tool definition for read_file
  */
 export function createReadFileTool(options: ReadFileToolOptions = {}): OpenAI.Chat.ChatCompletionTool {
-	const { supportsImages = false } = options
+	const { supportsImages = false, maxReadFileLine } = options
+
+	// Resolve the effective line limit for the tool description.
+	// -1 or undefined: use DEFAULT_LINE_LIMIT (2000)
+	// 0: no limit (read entire file)
+	// positive number: use that value
+	const hasNoLimit = maxReadFileLine === 0
+	const effectiveLimit =
+		maxReadFileLine === undefined || maxReadFileLine === -1
+			? DEFAULT_LINE_LIMIT
+			: maxReadFileLine === 0
+				? undefined // no limit
+				: maxReadFileLine > 0
+					? maxReadFileLine
+					: DEFAULT_LINE_LIMIT
 
 	// Build description based on capabilities
 	const descriptionIntro =
@@ -70,7 +86,9 @@ export function createReadFileTool(options: ReadFileToolOptions = {}): OpenAI.Ch
 		` PREFER indentation mode when you have a specific line number from search results, error messages, or definition lookups - it guarantees complete, syntactically valid code blocks without mid-function truncation.` +
 		` IMPORTANT: Indentation mode requires anchor_line to be useful. Without it, only header content (imports) is returned.`
 
-	const limitNote = ` By default, returns up to ${DEFAULT_LINE_LIMIT} lines per file. Lines longer than ${MAX_LINE_LENGTH} characters are truncated.`
+	const limitNote = hasNoLimit
+		? ` Reads the entire file by default (no line limit). Lines longer than ${MAX_LINE_LENGTH} characters are truncated.`
+		: ` By default, returns up to ${effectiveLimit} lines per file. Lines longer than ${MAX_LINE_LENGTH} characters are truncated.`
 
 	const description =
 		descriptionIntro +
@@ -125,7 +143,9 @@ export function createReadFileTool(options: ReadFileToolOptions = {}): OpenAI.Ch
 		},
 		limit: {
 			type: "integer",
-			description: `Maximum number of lines to return (slice mode, default: ${DEFAULT_LINE_LIMIT})`,
+			description: hasNoLimit
+				? `Maximum number of lines to return (slice mode, default: no limit - reads entire file)`
+				: `Maximum number of lines to return (slice mode, default: ${effectiveLimit})`,
 		},
 		indentation: {
 			type: "object",
diff --git a/src/core/task/Task.ts b/src/core/task/Task.ts
index 1d4320493a..1248bd8533 100644
--- a/src/core/task/Task.ts
+++ b/src/core/task/Task.ts
@@ -1670,6 +1670,7 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
 				apiConfiguration,
 				disabledTools: state?.disabledTools,
 				modelInfo,
+				maxReadFileLine: state?.maxReadFileLine,
 				includeAllToolsWithRestrictions: false,
 			})
 			allTools = toolsResult.tools
@@ -3858,6 +3859,7 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
 				apiConfiguration,
 				disabledTools: state?.disabledTools,
 				modelInfo,
+				maxReadFileLine: state?.maxReadFileLine,
 				includeAllToolsWithRestrictions: false,
 			})
 			allTools = toolsResult.tools
@@ -4072,6 +4074,7 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
 						apiConfiguration,
 						disabledTools: state?.disabledTools,
 						modelInfo,
+						maxReadFileLine: state?.maxReadFileLine,
 						includeAllToolsWithRestrictions: false,
 					})
 					contextMgmtTools = toolsResult.tools
@@ -4236,6 +4239,7 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
 				apiConfiguration,
 				disabledTools: state?.disabledTools,
 				modelInfo,
+				maxReadFileLine: state?.maxReadFileLine,
 				includeAllToolsWithRestrictions: supportsAllowedFunctionNames,
 			})
 			allTools = toolsResult.tools
diff --git a/src/core/task/build-tools.ts b/src/core/task/build-tools.ts
index c32d8f6f9b..2ce483f08e 100644
--- a/src/core/task/build-tools.ts
+++ b/src/core/task/build-tools.ts
@@ -24,6 +24,8 @@ interface BuildToolsOptions {
 	apiConfiguration: ProviderSettings | undefined
 	disabledTools?: string[]
 	modelInfo?: ModelInfo
+	/** Maximum line limit for read_file tool. -1 or undefined = DEFAULT_LINE_LIMIT, 0 = no limit */
+	maxReadFileLine?: number
 	/**
 	 * If true, returns all tools without mode filtering, but also includes
 	 * the list of allowed tool names for use with allowedFunctionNames.
@@ -89,6 +91,7 @@ export async function buildNativeToolsArrayWithRestrictions(options: BuildToolsO
 		apiConfiguration,
 		disabledTools,
 		modelInfo,
+		maxReadFileLine,
 		includeAllToolsWithRestrictions,
 	} = options
 
@@ -111,6 +114,7 @@ export async function buildNativeToolsArrayWithRestrictions(options: BuildToolsO
 	// Build native tools with dynamic read_file tool based on settings.
 	const nativeTools = getNativeTools({
 		supportsImages,
+		maxReadFileLine,
 	})
 
 	// Filter native tools based on mode restrictions.
diff --git a/src/core/tools/ReadFileTool.ts b/src/core/tools/ReadFileTool.ts
index 8ad6a3b33d..99da35d5ae 100644
--- a/src/core/tools/ReadFileTool.ts
+++ b/src/core/tools/ReadFileTool.ts
@@ -66,6 +66,27 @@ interface FileResult {
 	entry?: InternalFileEntry
 }
 
+// ─── Helpers ──────────────────────────────────────────────────────────────────
+
+/**
+ * Resolve the effective line limit from the maxReadFileLine user setting.
+ *
+ * @param maxReadFileLine - The user setting value:
+ *   - `-1` or `undefined`: use DEFAULT_LINE_LIMIT (2000)
+ *   - `0`: no limit (read entire file) — returns `Infinity`
+ *   - positive number: use that value as the limit
+ * @returns The resolved line limit
+ */
+export function resolveLineLimit(maxReadFileLine?: number): number {
+	if (maxReadFileLine === undefined || maxReadFileLine === null || maxReadFileLine === -1) {
+		return DEFAULT_LINE_LIMIT
+	}
+	if (maxReadFileLine === 0) {
+		return Infinity
+	}
+	return maxReadFileLine > 0 ? maxReadFileLine : DEFAULT_LINE_LIMIT
+}
+
 // ─── Tool Implementation ──────────────────────────────────────────────────────
 
 export class ReadFileTool extends BaseTool<"read_file"> {
@@ -169,10 +190,17 @@ export class ReadFileTool extends BaseTool<"read_file"> {
 			const imageMemoryTracker = new ImageMemoryTracker()
 			const state = await task.providerRef.deref()?.getState()
 			const {
+				maxReadFileLine,
 				maxImageFileSize = DEFAULT_MAX_IMAGE_FILE_SIZE_MB,
 				maxTotalImageSize = DEFAULT_MAX_TOTAL_IMAGE_SIZE_MB,
 			} = state ?? {}
 
+			// Resolve the effective line limit from the maxReadFileLine setting.
+			// -1 (default): use DEFAULT_LINE_LIMIT (2000)
+			// 0: no limit (read entire file)
+			// positive number: use that as the limit
+			const effectiveLineLimit = resolveLineLimit(maxReadFileLine)
+
 			for (const fileResult of fileResults) {
 				if (fileResult.status !== "approved") continue
 
@@ -216,7 +244,7 @@ export class ReadFileTool extends BaseTool<"read_file"> {
 					// (they become U+FFFD replacement characters instead of throwing)
 					const buffer = await fs.readFile(fullPath)
 					const fileContent = buffer.toString("utf-8")
-					const result = this.processTextFile(fileContent, entry)
+					const result = this.processTextFile(fileContent, entry, effectiveLineLimit)
 
 					await task.fileContextTracker.trackFileContext(relPath, "read_tool" as RecordSource)
 
@@ -266,7 +294,11 @@ export class ReadFileTool extends BaseTool<"read_file"> {
 	/**
 	 * Process a text file according to the requested mode.
 	 */
-	private processTextFile(content: string, entry: InternalFileEntry): string {
+	private processTextFile(
+		content: string,
+		entry: InternalFileEntry,
+		effectiveLineLimit: number = DEFAULT_LINE_LIMIT,
+	): string {
 		const mode = entry.mode || "slice"
 
 		if (mode === "indentation") {
@@ -278,7 +310,7 @@ export class ReadFileTool extends BaseTool<"read_file"> {
 				maxLevels: entry.max_levels,
 				includeSiblings: entry.include_siblings,
 				includeHeader: entry.include_header,
-				limit: entry.limit ?? DEFAULT_LINE_LIMIT,
+				limit: entry.limit ?? effectiveLineLimit,
 				maxLines: entry.max_lines,
 			})
 
@@ -287,7 +319,7 @@ export class ReadFileTool extends BaseTool<"read_file"> {
 			if (result.wasTruncated && result.includedRanges.length > 0) {
 				const [start, end] = result.includedRanges[0]
 				const nextOffset = end + 1
-				const effectiveLimit = entry.limit ?? DEFAULT_LINE_LIMIT
+				const effectiveLimit = entry.limit ?? effectiveLineLimit
 				// Put truncation warning at TOP (before content) to match @ mention format
 				output = `IMPORTANT: File content truncated.
 	Status: Showing lines ${start}-${end} of ${result.totalLines} total lines.
@@ -306,7 +338,7 @@ export class ReadFileTool extends BaseTool<"read_file"> {
 		// NOTE: read_file offset is 1-based externally; convert to 0-based for readWithSlice.
 		const offset1 = entry.offset ?? 1
 		const offset0 = Math.max(0, offset1 - 1)
-		const limit = entry.limit ?? DEFAULT_LINE_LIMIT
+		const limit = entry.limit ?? effectiveLineLimit
 
 		const result = readWithSlice(content, offset0, limit)
 
@@ -786,8 +818,10 @@ export class ReadFileTool extends BaseTool<"read_file"> {
 					}
 					content = selectedLines.join("\n")
 				} else {
-					// Read with default limits using slice mode
-					const result = readWithSlice(rawContent, 0, DEFAULT_LINE_LIMIT)
+					// Read with effective limits using slice mode
+					const legacyState = await task.providerRef.deref()?.getState()
+					const legacyLineLimit = resolveLineLimit(legacyState?.maxReadFileLine)
+					const result = readWithSlice(rawContent, 0, legacyLineLimit)
 					content = result.content
 					if (result.wasTruncated) {
 						content += `\n\n[File truncated: showing ${result.returnedLines} of ${result.totalLines} total lines]`
diff --git a/src/core/tools/__tests__/resolveLineLimit.spec.ts b/src/core/tools/__tests__/resolveLineLimit.spec.ts
new file mode 100644
index 0000000000..3010c654fd
--- /dev/null
+++ b/src/core/tools/__tests__/resolveLineLimit.spec.ts
@@ -0,0 +1,30 @@
+import { resolveLineLimit } from "../ReadFileTool"
+import { DEFAULT_LINE_LIMIT } from "../../prompts/tools/native-tools/read_file"
+
+describe("resolveLineLimit", () => {
+	it("returns DEFAULT_LINE_LIMIT when undefined", () => {
+		expect(resolveLineLimit(undefined)).toBe(DEFAULT_LINE_LIMIT)
+	})
+
+	it("returns DEFAULT_LINE_LIMIT when -1 (default setting)", () => {
+		expect(resolveLineLimit(-1)).toBe(DEFAULT_LINE_LIMIT)
+	})
+
+	it("returns Infinity when 0 (no limit / read entire file)", () => {
+		expect(resolveLineLimit(0)).toBe(Infinity)
+	})
+
+	it("returns the positive value as-is", () => {
+		expect(resolveLineLimit(500)).toBe(500)
+		expect(resolveLineLimit(10000)).toBe(10000)
+	})
+
+	it("returns DEFAULT_LINE_LIMIT for negative values other than -1", () => {
+		expect(resolveLineLimit(-5)).toBe(DEFAULT_LINE_LIMIT)
+	})
+
+	it("returns DEFAULT_LINE_LIMIT when null-ish (null cast as number)", () => {
+		// In practice, state?.maxReadFileLine could be null
+		expect(resolveLineLimit(null as unknown as number)).toBe(DEFAULT_LINE_LIMIT)
+	})
+})
diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts
index 231e2794c5..5015767775 100644
--- a/src/core/webview/ClineProvider.ts
+++ b/src/core/webview/ClineProvider.ts
@@ -2180,6 +2180,7 @@ export class ClineProvider
 			showRooIgnoredFiles,
 			enableSubfolderRules,
 			language,
+			maxReadFileLine,
 			maxImageFileSize,
 			maxTotalImageSize,
 			historyPreviewCollapsed,
@@ -2305,6 +2306,7 @@ export class ClineProvider
 			enableSubfolderRules: enableSubfolderRules ?? false,
 			language: language ?? formatLanguage(vscode.env.language),
 			renderContext: this.renderContext,
+			maxReadFileLine: maxReadFileLine ?? -1,
 			maxImageFileSize: maxImageFileSize ?? 5,
 			maxTotalImageSize: maxTotalImageSize ?? 20,
 			settingsImportedAt: this.settingsImportedAt,
@@ -2529,6 +2531,7 @@ export class ClineProvider
 			telemetrySetting: stateValues.telemetrySetting || "unset",
 			showRooIgnoredFiles: stateValues.showRooIgnoredFiles ?? false,
 			enableSubfolderRules: stateValues.enableSubfolderRules ?? false,
+			maxReadFileLine: stateValues.maxReadFileLine ?? -1,
 			maxImageFileSize: stateValues.maxImageFileSize ?? 5,
 			maxTotalImageSize: stateValues.maxTotalImageSize ?? 20,
 			historyPreviewCollapsed: stateValues.historyPreviewCollapsed ?? false,
