cc-habits · docs
Getting started
Everything cc-habits does, in roughly the order you'll need it. Start at Install.
Install
cc-habits is a global npm package. You'll need Node 20+ (already installed if you use most AI coding CLIs).
$ npm install -g cc-habits@latest
$ cch init # cch is short for cc-habits
cch is a short alias for cc-habits. All
commands work with either form (cch init,
cch view, cch status, etc.).
cch init walks you through provider setup interactively.
Pick whichever fits your situation:
No API key? A coding-tool subscription and an AI provider key are billed separately. If you only have a tool subscription, Ollama is the recommended free alternative - it runs locally and needs no API key.
# Quickest path with no API key:
brew install ollama # or download from ollama.com
ollama pull llama3.2
ollama serve &
cch init --provider ollama
During init, if cc-habits finds past Claude Code sessions for this project, it offers to bootstrap - retroactively learning habits from your existing work:
Found 4 Claude Code sessions for this project.
Bootstrap habits from past sessions? [y/N] y
Extracting patterns...
✓ Learned 7 habits across 4 categories from 42 edits
You can re-run this at any time with cch bootstrap.
How it works
cc-habits installs hooks into whichever tools you use, the same way
across Claude Code, Gemini CLI, Codex, and Kimi. Each tool uses its
own event names, so an --adapter flag (set automatically
at install) normalizes every payload into one shape. Run
cch tools to see which tools are detected:
PostToolUse (Write|Edit|MultiEdit)
→ captures the diff
→ appends to ~/.cc-habits/log.jsonl
→ exits in ~5ms of work (full hook ~70ms p50, dominated by Node startup)
Stop (session end)
→ reads session signals from log.jsonl
→ one small-model call to extract patterns
→ updates ~/.cc-habits/habits.md
→ prints "cc-habits: learned 2, updated 3."
UserPromptSubmit (every prompt)
→ injects your strongest active habits into context
→ survives context compaction; "laws, not requests"
→ set CC_HABITS_INJECT=0 to disable
SessionStart (session begins)
→ prints "cc-habits: N habits active this session"
→ stays silent when nothing is active
habits.md is also auto-imported into every session via an
@import line in your tool's memory file (for example
~/.claude/CLAUDE.md or GEMINI.md), and synced
into AGENTS.md and rules files for the rest. The import
gives the agent the full picture at session start; the UserPromptSubmit
hook re-asserts the top habits on every turn so they don't get
summarised away when the context compacts mid-session.
No per-project setup. Hooks live at the user level; habits live in
~/.cc-habits/. cc-habits works globally across every
repository you open.
For tools without a hook mechanism (Cursor, Windsurf, Copilot),
there is nothing to install: run cch sync
and your habits land in their rules files. And for any
workflow at all, cch git-capture
mines your commit history for patterns; cch init
can install a Git post-commit hook so this happens automatically
every time you commit.
What it learns
After a few sessions of Claude Code, your habits.md
might look like this:
# Coding habits
Auto-generated by cc-habits. Do not edit manually; changes will be overwritten.
## Python
- Add type hints to all function parameters and return types. Confidence: 0.75
- Signal: 7 reinforcing, 0 contradicting
- First learned: 2026-05-18
- Last updated: 2026-05-20
- Use f-strings instead of .format() or string concatenation. Confidence: 0.65
- Signal: 4 reinforcing, 1 contradicting
- First learned: 2026-05-18
## Error Handling
- Wrap external I/O in try/except and re-raise as RuntimeError. Confidence: 0.55
- Signal: 2 reinforcing, 0 contradicting
Your agent reads this file at the start of every session. When it generates code, it already knows your preferences.
Mistake memories
Habits are only half the picture. Habits capture how you prefer code written; memories capture what agents got wrong before, and when that warning is relevant. It is a separate companion to habits with the same plain-text storage, the same graduation gate, and the same tombstones. It is on by default.
$ cch memories # view what's been remembered
$ cch memories --disable # turn it off (persists to config.yml)
By default, the session-end pass runs a second extraction that looks
for repeated mistakes (the same class of bug you fixed twice) and
writes them to ~/.cc-habits/memories.md. Each memory carries
a trigger so your agent only sees it when it is about
to do that thing again, injected at most a few at a time to stay cheap.
# Coding memories
## Async
- Forgot to await an async call; the promise was used as a value.
Correction: await the call, or return the promise.
Trigger: async, await, Promise · Confidence: 0.70
## SQL
- Interpolated a variable straight into a SQL string.
Correction: use a parameterized query.
Trigger: query, SQL, execute · Confidence: 0.60
Manage them the same way as habits: cch memories --delete "<text>"
tombstones a memory so it is never re-learned, and
cch memories --tombstones lists what you have blocked.
Disable the whole feature any time with cch memories --disable.
View your habits
$ cch view
cc-habits · your coding habits
3 active habits across 2 categories · 12 signals processed
── Python ──────────────────────────────────────────
Add type hints to all function parameters and return types
[███████████████░░░░░░░] 75% ↑7 ↓0 · since 2026-05-18
Use f-strings instead of .format()
[█████████████░░░░░░░░░] 65% ↑4 ↓1 · since 2026-05-18
── Error Handling ──────────────────────────────────
Wrap external I/O in try/except and re-raise as RuntimeError
[███████████░░░░░░░░░░░] 55% ↑2 ↓0 · since 2026-05-19
Status & health
cch status (alias
cch doctor) is a one-glance health
check: which tools are wired up, whether each one has actually
fired its hook (a liveness proof, not just “registered”),
your provider, and your habit and signal counts.
$ cch status
┌──────────────────────────────────────────────────────────────┐
│ ✓ Claude Code live · 2 minutes ago · 546 sigs │
│ ~ Cursor git capture on commit │
│ ✓ Gemini CLI live · 7 days ago · 1 sig │
│ ✓ Codex CLI registered (edit in Codex CLI to confirm) │
│ ✓ Kimi Code CLI registered (edit in Kimi Code CLI) │
├──────────────────────────────────────────────────────────────┤
│ provider ollama (gemma4:31b-cloud) │
│ import ✓ preferences.md in CLAUDE.md │
│ habits 19 active · 3 learning │
│ signals 1362 total · 5 this session │
│ memory on │
│ version 0.7.12 │
└──────────────────────────────────────────────────────────────┘
All good. Start a coding session to keep learning.
The “live · N ago” line is logged only when the tool itself
runs the hook, so it is a real liveness signal rather than a claim that
the config exists. Add --proof to print the exact hook
commands written into each tool's config.
The confidence math
Habits are weighted by how consistently you apply them.
Intentionally simple. Symbolic Bayesian-ish updates with session gating, contradiction velocity, and staleness decay. Honest about the math.
Cost
One small-model call per session. That's it.
With Ollama (free, local): $0 / month - runs entirely on your machine.
With Anthropic Haiku 4.5:
You provide your own API key. cc-habits does not collect or proxy keys.
Commands
cch init # install hooks, choose a provider
cch bootstrap # learn habits from past Claude Code sessions
cch learn --repo # scan this repo with the LLM and learn directly
cch view [habits|memories|prefs] # show current habits, memories, or preferences
cch memories # show coding memories (on by default; --disable to turn off)
cch diff [--since N] # changes since the last write
cch explain "<rule>" # show signals that produced a habit
cch lint <file> [--json] # check a source file against your habits
cch export [path] # print habits.md (or write to path)
cch import <file> # merge a portable habits file
cch sync [targets] [--dir P] # write habits to AGENTS.md / Cursor / Cline
cch git-capture [--range r] # learn from your Git commit history
cch status [--proof] # health check: hooks, provider, last-fired liveness
cch tools # list supported tools and which are detected
cch faq [query] # search the built-in FAQ, or browse categories
cch on # re-enable capture after cch off
cch off # pause all capture globally (reversible)
cch migrate # migrate storage to ~/.cc-habits/
cch shell-init # print a shell wrapper: eval "$(cch shell-init)"
cch uninstall # remove all hooks and config
cch tombstone "<rule>" # block a rule permanently
cch tombstone # list tombstoned rules
cch reset --yes # wipe habits.md, preferences.md, memories.md, log.jsonl
cch --version # print installed version
Safety guarantees
-
Never fails a coding session. Every hook is
wrapped in
try/catch. On error: logs to~/.cc-habits/error.log, exits 0. The|| truein the hook command is an extra layer. - No data leaves your machine except the extraction API call. No telemetry, no analytics, no server.
-
habits.md is human-readable. Read, edit, or delete
it at any time.
cch reset --yesgives you a clean slate. -
Append-only log. Signals in
log.jsonlare never modified or deleted except bycch reset.
Privacy
cc-habits is a local-first tool. It is designed so that you are the only data controller for everything it captures.
What is stored, where
Every artifact lives in your home directory. None of these are synced or uploaded by cc-habits.
What leaves the machine
Outbound calls go only to the AI provider you chose: the session-end hook sends a redacted batch of signals for habit extraction. With Ollama, that runs locally and nothing leaves your machine. With a cloud provider it uses your API key, hits the provider directly, and is governed by your agreement with them.
cc-habits does not operate a server. There is no telemetry, no analytics, no error reporting endpoint.
Redaction before any outbound call
Three patterns are replaced with sentinel tokens before signals reach the model:
The extractor prompt explicitly instructs the model: "Never output content marked <REDACTED:…>."
In addition, extracted rules are sanitized before
being written into habits.md: control characters,
URLs, zero-width and homoglyph evasions, container-escape tags, and
prompt-injection keywords (e.g. "IGNORE PREVIOUS",
SYSTEM:) are stripped to prevent a compromised signal
from poisoning your agent's context.
If you process other categories of sensitive data (non-Latin PII,
custom tokens, healthcare identifiers), audit log.jsonl
periodically and consider stricter retention.
You are the data controller
Because everything lives in your home directory and the only outbound call uses your own API key, you are the data controller and data processor under GDPR, DPDP, CCPA, and similar regimes. cc-habits has no privileged access to your data.
If you are operating in a regulated environment:
- Treat
~/.cc-habits/as you would any folder containing source-code diffs. - Set your provider key (for example
ANTHROPIC_API_KEY) via your secrets manager rather than storing it inconfig.yml. - Periodically run
cch reset --yesto clear local history. Tombstones survive. - For air-gapped contexts, do not run
cch init. Without an API key, the Stop hook fails closed.
Recommended hygiene
-
Do not sync
~/.cc-habits/via Dropbox, iCloud, Syncthing, or similar. Diffs of your code travelling between machines materially expands the data-loss surface. Add it to your sync tool's ignore list. -
Move your API key to a secrets manager.
Storing it in
config.ymlis convenient but co-resident processes can read it. SettingANTHROPIC_API_KEYvia your shell profile + a secrets agent is stronger. -
Audit
log.jsonlif you handle sensitive data. It contains 30+ days of code diffs by default. Consider periodic rotation.
What cc-habits will never do
- It will not phone home. There is no cc-habits server.
- It will not modify code in your repositories. It only writes to
~/.cc-habits/and your tools' own config files. - It will not register itself with any tool without
cch initrunning explicitly. - It will not fail a coding session. Every hook is wrapped in
try/catchand exits 0 on error.
Reporting a privacy concern
If you believe cc-habits has leaked data or has a vulnerability with privacy impact, please report it via a GitHub security advisory rather than a public issue: github.com/Shreyan1/cc-habits/security/advisories/new.
cc-habits · spec
habits-format v0.3
A portable, human-readable schema for representing a developer's learned coding habits. Designed so any tool - not just cc-habits - can read, write, and exchange habits files.
This document is the normative specification. Where the reference implementation and this document disagree, this document governs the on-disk format and the implementation is the bug.
1. Design goals
- Human-readable. Anyone can
catthe file and understand it. - Markdown-native. It IS markdown. No second parser needed for rendering.
- Idempotent round-trip. Parsing and re-serialising must preserve all semantic content.
- Editor-friendly. A user can manually edit, delete, or reorder rules without breaking tools.
- Tool-portable. cc-habits is one valid renderer; nothing in the spec depends on its internals.
2. File structure
A habits file is a single UTF-8 markdown document with these sections, in order:
1. Format version comment (REQUIRED)
2. Document title (REQUIRED)
3. Edit-policy note (RECOMMENDED)
4. Zero or more category sections (## <CategoryName>)
5. Zero or one Learning section (## Learning (not yet active))
2.1 Format version comment
The first non-empty line MUST be an HTML comment of the form:
<!-- cc-habits format v0.3 -->
Readers MUST refuse to parse files whose major version they do not implement. Older minor versions SHOULD be parsed best-effort (v0.x minor versions are additive).
2.2 Document title
The document title MUST be exactly:
# Coding habits
2.3 Edit-policy note
A single paragraph explaining the file's behaviour. Recommended text:
Auto-generated by cc-habits. You may edit this file; rules you delete will not be recreated.
2.4 Category section
## <CategoryName>
- <Rule text>. Confidence: <0.00-1.00>
- Signal: <int> reinforcing, <int> contradicting
- Sessions seen: <int>
- Languages: <comma-separated list> [OPTIONAL]
- First learned: <YYYY-MM-DD> [OPTIONAL]
- Last updated: <YYYY-MM-DD> [OPTIONAL]
Rule text is a single declarative sentence. The
trailing period before Confidence: is REQUIRED.
Confidence is a decimal between 0.00 and 1.00 with
two decimal places.
2.5 Learning section
## Learning (not yet active)
> These habits have been observed in only one session. They are
> quarantined here until reinforced in a second distinct session.
> Claude should not apply rules in this section.
- [<CategoryName>] <Rule text>. Confidence: <0.00-1.00>
- Signal: ...
- Sessions seen: 1
...
Learning rules carry their owning category in [brackets].
Once observed in a second distinct session, the writer MUST move
the rule out of Learning into its category section.
3. Semantics
3.1 Sessions seen
Sessions seen: N is the count of distinct work sessions
in which this rule has been observed. It is the canonical promotion gate:
Sessions seen: 1→ Learning section, NOT appliedSessions seen ≥ 2→ category section, applied
3.2 Confidence
Confidence is updated by the writer according to its own model. The reference cc-habits implementation uses:
- New rule: start at 0.50
- Reinforcing signal: +0.05 (cap 0.95)
- Contradicting signal: −0.10 (−0.20 when 3+ in the same batch)
- Decay: −0.05 per week unused after a 7-day grace period
- Prune: rules below 0.30 are removed
Other implementations MAY use different update rules. The on-disk number is the source of truth.
3.3 Languages & dates
Languages: ts, py, go is an optional set of file
extensions in which this habit was observed.
First learned and Last updated are
ISO-8601 UTC dates.
4. Companion files
Implementations MAY produce companion files alongside the habits file. They are NOT part of the portable format. A tool that doesn't recognise a companion file MUST leave it untouched.
5. Tombstones
A tombstone is a single normalised rule string. Format:
[
"use strict mode",
"prefer async await over promise chains"
]
Normalisation: trim whitespace, strip trailing
period, lowercase. When a writer receives a create
decision for a rule whose normalised form matches an entry in
tombstones, it MUST skip the create.
6. Compatibility & versioning
- Files MUST declare their format version in the leading HTML comment.
- A reader encountering an unknown minor version MAY proceed but SHOULD warn.
- A reader encountering an unknown major version MUST refuse to parse.
This spec is v0.3. Minor versions are additive and backward-compatible. Breaking changes will bump the major version.
7. Reference grammar (informal)
File = VersionComment Title EditPolicy? CategoryBlock* LearningBlock?
VersionComment = "<!-- cc-habits format v0.3 -->"
Title = "# Coding habits"
CategoryBlock = "## " CategoryName HabitEntry*
LearningBlock = "## Learning (not yet active)" BlockQuote LearningEntry*
HabitEntry = "- " RuleText ". Confidence: " Confidence Newline MetaLine*
LearningEntry = "- [" CategoryName "] " RuleText ". Confidence: " Confidence Newline MetaLine*
MetaLine = SignalLine | SessionsLine | LanguagesLine | FirstLearnedLine | LastUpdatedLine
This specification is licensed CC-BY 4.0. You may build commercial or open-source tools that implement it without attribution beyond a link to this document. The reference implementation is separately licensed MIT.