Create an AI Writing Coach: Real-Time Feedback That Actually Improves Your Writing
Build a writing assistant that gives actionable feedback on clarity, structure, tone, and style. Not just grammar — real coaching.
Grammar checkers catch typos. Writing coaches improve thinking. There’s a chasm between “your comma is wrong” and “your argument structure buries the most compelling point in paragraph four.” Most writing tools operate in the grammar checker lane. This tutorial builds a genuine writing coach.
Our AI writing coach analyzes clarity, structure, argument strength, tone, and readability. It gives specific, actionable feedback that makes writing genuinely better — not just grammatically correct. And it does it in real time, as you write.
What We’re Building

A writing analysis tool that:
- Evaluates text across five dimensions: clarity, structure, tone, argument strength, and readability
- Provides specific, actionable improvement suggestions
- Shows readability metrics (Flesch-Kincaid, sentence length distribution)
- Offers before/after rewrites for weak sections
- Adapts feedback style to writing context (blog, email, academic, business)
Tech Stack
- Python 3.11+
- Streamlit for the web interface
- Claude API for writing analysis
- textstat for readability metrics
- Plotly for visualization
Step 1: Readability Analysis Engine

import textstat
import re
from collections import Counter
def analyze_readability(text: str) -> dict:
sentences = re.split(r'[.!?]+', text)
sentences = [s.strip() for s in sentences if s.strip()]
words = text.split()
sentence_lengths = [len(s.split()) for s in sentences]
return {
"flesch_reading_ease": textstat.flesch_reading_ease(text),
"flesch_kincaid_grade": textstat.flesch_kincaid_grade(text),
"gunning_fog": textstat.gunning_fog(text),
"word_count": len(words),
"sentence_count": len(sentences),
"avg_sentence_length": sum(sentence_lengths) / max(len(sentence_lengths), 1),
"max_sentence_length": max(sentence_lengths) if sentence_lengths else 0,
"paragraph_count": text.count("\n\n") + 1,
"passive_voice_estimate": estimate_passive(text),
"adverb_count": count_adverbs(text),
"sentence_length_distribution": sentence_lengths
}
def estimate_passive(text: str) -> int:
passive_patterns = [
r'\b(was|were|been|being|is|are|am)\s+\w+ed\b',
r'\b(was|were|been|being|is|are|am)\s+\w+en\b',
]
count = 0
for pattern in passive_patterns:
count += len(re.findall(pattern, text, re.IGNORECASE))
return count
def count_adverbs(text: str) -> int:
adverb_pattern = r'\b\w+ly\b'
common_non_adverbs = {'only', 'early', 'daily', 'family', 'likely', 'apply', 'reply', 'supply', 'July', 'holy'}
matches = re.findall(adverb_pattern, text, re.IGNORECASE)
return len([m for m in matches if m.lower() not in common_non_adverbs])
Step 2: AI Writing Analysis

from anthropic import Anthropic
import json
client = Anthropic()
def analyze_writing(text: str, context: str = "blog post") -> dict:
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=2048,
system=f"""You are an expert writing coach analyzing a {context}.
Evaluate the text and return JSON:
{{
"overall_score": 1-10,
"clarity": {{"score": 1-10, "feedback": "specific feedback", "examples": ["quote problematic sentence -> suggestion"]}},
"structure": {{"score": 1-10, "feedback": "specific feedback", "suggestions": ["reorder suggestion"]}},
"tone": {{"score": 1-10, "detected_tone": "formal/casual/etc", "consistency": "consistent/mixed", "feedback": "feedback"}},
"argument_strength": {{"score": 1-10, "feedback": "feedback", "weak_points": ["specific weak arguments"]}},
"engagement": {{"score": 1-10, "feedback": "feedback", "hooks": "assessment of opening hook"}},
"top_3_improvements": ["most impactful changes ranked by priority"],
"strongest_element": "what the writer does best"
}}
Be specific. Quote actual sentences. Suggest concrete rewrites. Be encouraging but honest.""",
messages=[{"role": "user", "content": text}]
)
result_text = response.content[0].text
if "```json" in result_text:
result_text = result_text.split("```json")[1].split("```")[0]
return json.loads(result_text.strip())
Step 3: Streamlit Interface

import streamlit as st
import plotly.graph_objects as go
st.set_page_config(page_title="AI Writing Coach", layout="wide")
st.title("AI Writing Coach")
# Context selector
context = st.selectbox(
"What are you writing?",
["Blog post", "Business email", "Academic paper",
"Marketing copy", "Technical documentation", "Personal essay"]
)
# Text input
text = st.text_area("Paste your text here:", height=400,
placeholder="Enter at least 100 words for meaningful analysis...")
if text and len(text.split()) >= 50:
col1, col2 = st.columns([1, 1])
with col1:
st.subheader("Readability Metrics")
metrics = analyze_readability(text)
# Score gauges
fig = go.Figure(go.Indicator(
mode="gauge+number",
value=metrics["flesch_reading_ease"],
title={"text": "Readability Score"},
gauge={"axis": {"range": [0, 100]},
"bar": {"color": "darkblue"},
"steps": [
{"range": [0, 30], "color": "red"},
{"range": [30, 60], "color": "yellow"},
{"range": [60, 100], "color": "green"}
]}
))
st.plotly_chart(fig, use_container_width=True)
st.metric("Words", metrics["word_count"])
st.metric("Avg Sentence Length", f"{metrics['avg_sentence_length']:.1f} words")
st.metric("Passive Voice", metrics["passive_voice_estimate"])
with col2:
st.subheader("AI Analysis")
with st.spinner("Analyzing your writing..."):
analysis = analyze_writing(text, context.lower())
# Score cards
for dimension in ["clarity", "structure", "tone", "argument_strength", "engagement"]:
data = analysis[dimension]
score = data["score"]
color = "green" if score >= 7 else "orange" if score >= 5 else "red"
st.markdown(f"**{dimension.replace('_', ' ').title()}**: :{color}[{score}/10]")
st.caption(data["feedback"])
st.subheader("Top Improvements")
for i, improvement in enumerate(analysis["top_3_improvements"], 1):
st.markdown(f"{i}. {improvement}")
st.success(f"Strongest element: {analysis['strongest_element']}")
Step 4: Section-by-Section Rewriting

Add a feature that lets users select weak sections and get AI-generated rewrites:
def rewrite_section(original: str, feedback: str, context: str) -> str:
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
system=f"Rewrite this {context} section based on the feedback. Maintain the author's voice while improving clarity and impact.",
messages=[{"role": "user", "content": f"Original:\n{original}\n\nFeedback:\n{feedback}\n\nProvide the rewritten version:"}]
)
return response.content[0].text
Step 5: Writing Style Profiles

Create style profiles for different writing contexts:
- Blog: Casual, engaging, scannable. Target Flesch score 60-80.
- Business Email: Clear, direct, actionable. Target Flesch score 50-70.
- Academic: Precise, evidence-based, formal. Target Flesch score 30-50.
- Marketing: Persuasive, emotional, benefit-focused. Target Flesch score 60-80.
- Technical Docs: Clear, structured, example-rich. Target Flesch score 40-60.
Each profile adjusts the AI’s evaluation criteria and feedback style.
Step 6: Progress Tracking

Track improvement over time by storing analysis results and showing trend charts. Writers can see their clarity, structure, and engagement scores improve across drafts.
Step 7: Export and Integration

Add export options:
- Download analysis report as PDF
- Copy improved text to clipboard
- Generate a “writing checklist” based on the analysis
- Export readability metrics as JSON for integration with content management systems
The Bottom Line
A writing coach that gives specific, contextual feedback is fundamentally different from a grammar checker. It improves the quality of thinking, not just the mechanics of writing. And unlike a human editor who charges $50-100/hour, an AI writing coach is available 24/7 for pennies per analysis.
Build time: 3-4 hours. Cost: $5-15/month for typical individual use. Impact: dramatically better writing across your team, with measurable improvement in engagement metrics for published content.
Sources
> Want more like this?
Get the best AI insights delivered weekly.
> Related Articles
Web Scraping with AI: Build a Smart Data Extraction Pipeline
Traditional web scraping breaks when websites change layouts. AI-powered scraping understands page structure and extracts data intelligently. Here's how to build one using Python, Beautiful Soup, and Claude.
Create an AI Art Portfolio: From Generation to Gallery in One Weekend
Build a professional AI art portfolio website with curated collections, consistent style, and proper attribution. Covers prompt engineering, style consistency, curation, and deployment.
Build an AI Chrome Extension: Add Claude to Any Webpage in 60 Minutes
Build a Chrome extension that summarizes web pages, answers questions about content, and rewrites selected text — all powered by Claude. Full source code and step-by-step instructions included.
Tags
> Stay in the loop
Weekly AI tools & insights.