Large Language Models in Finance · Chapter 4 / Lecture 4 · Practical

Hands-on with Claude Code & Cline

Your first agentic IDE session: the file-based pattern, then add an agent, a skill, a tool, and two hooks — and run a real filing-Q&A agent.
Juan F. Imbet  ·  EDHEC Business School / Paris Dauphine – PSL University
Session overview · 1 hour

What we'll actually do today

An introduction to the two agentic coding assistants this course uses. Less slide, more building: you'll open one project in Claude Code or Cline and extend it four ways — agent, skill, tool, hook — then watch a grounded filing agent run end to end.

Open this folder in Claude Code or Cline
code/practicals/04-llm-agents/ — copy-ready skeletons live in templates/, the live agents in .claude/.
  1. Meet the tools (10 min) — install, open the folder, the file-based pattern
  2. The capability map (10 min) — agents, skills, tools, hooks + the standard tools
  3. Add an agent & a skill (15 min) — from the templates, in both setups
  1. Wire two hooks (10 min) — an audit log and a timed safety commit
  2. Run the agent (10 min) — /ask a grounded, graded filing question
  3. Discussion (5 min) — when to add an agent vs. a hook
what you'll leave with A mental model of an agentic IDE as plain files under version control — and the muscle memory to add a capability to either Claude Code or Cline.
01

Meet Claude Code & Cline

Two assistants, the same idea: an LLM that reads and writes your repo through tools.
The two tools · what they are

Same loop you saw in the lecture — wrapped around your codebase

Both are the Perceive → Reason → Act loop from the lecture, with your repository as the environment. The model proposes actions (read a file, run a command); the tool executes them and feeds the result back.

LLM agent loop: observe, reason, act, with tools and memory acting on the environment
Figure. The perceive–reason–act loop. In an agentic IDE the "environment" is your repository, and the actions are tool calls — read, edit, grep, run a command. Source: Course materials, Chapter 4.
Claude Code
Anthropic's CLI / IDE agent. Capabilities are markdown files under .claude/; a native hook engine fires scripts on lifecycle events. Install: npm i -g @anthropic-ai/claude-code, then run claude in the folder.
Cline
An open-source VS Code extension. Reads .clinerules / AGENTS.md, runs workflows, and connects tools over MCP. Install from the VS Code marketplace, open the folder, point it at a model provider.
why two The skills transfer. Learn the pattern once — capabilities as files — and you can drive any agentic IDE (Cursor, generic AGENTS.md runners) the same way.
The big idea · the file-based pattern

Every capability is a plain-text file — readable, diffable, auditable

There is no hidden configuration. An agent, a skill, and a hook are each a tracked file a reviewer can read in a pull request. In a regulated workflow, the entire capability surface is inspectable from a git log.

code/practicals/04-llm-agents/
├── CLAUDE.md / AGENTS.md          # project instructions (both tools read these)
├── .clinerules                    # Cline's project rules
├── .claude/
│   ├── settings.json              # permissions + HOOKS wiring
│   ├── agents/  retriever.md analyst.md grader.md
│   ├── skills/  ask/SKILL.md      # the /ask command
│   └── hooks/   log-interaction.sh  timed-commit.sh
├── templates/                     # copy-ready skeletons (today's exercises)
└── tools/  retrieve.py grade.py   # deterministic Python the agent calls
the principle Agents are the who, skills the how, tools the actions, hooks the automatic guardrails. All four are text you can read, review, and version.
02

The capability map

Where agents, skills, tools, and hooks live in each setup — and the tools you get for free.
Four capabilities · two setups

Where each capability actually lives

The same four extension points, mapped to concrete file locations in each tool. Today you'll add one of each.

CapabilityClaude CodeCline
Agent — a persona.claude/agents/<name>.md.clinerules / AGENTS.md, or a custom mode
Skill — a /command.claude/skills/<name>/SKILL.md.clinerules/workflows/<name>.md
Tool — a new actionMCP in .mcp.json, or a CLI via BashMCP in cline_mcp_settings.json
Hook — an event callback.claude/settings.json + .claude/hooks/none native → git / MCP wrapper
the honest asymmetry Claude Code has a native hook engine; Cline does not. We'll implement the hooks natively in Claude Code and show the portable git / MCP fallback for Cline — same intent, different plumbing.
Tools · what you already have

You rarely build a tool — the standard ones ship with both

Before you reach for a custom tool, remember both assistants already act on your repo through a shared standard toolset. A custom tool is only for what the environment can't already do.

Standard (built-in) tools
  • Read — open a file
  • Edit / Write — change or create files
  • Grep — regex search across the repo
  • Glob — find files by name pattern
  • Bash — run any shell command (incl. your Python tools)
Custom tools (MCP) — when?
  • A live pricing / market-data API
  • An internal database or document store
  • A deterministic engine — a DCF, a bond pricer, a risk score
in this project The "tools" are plain Python in tools/ (retrieve.py, grade.py), called via Bash. Deterministic code does the arithmetic; the model only chooses inputs and reads outputs — never recalls a number.
03

Add an agent & a skill

From the templates — once for Claude Code, once for Cline.
Exercise 1 · add an agent

Copy the agent template and give it one job

An agent is a persona with a single responsibility, allowed tools, and one artifact it must produce. Start from templates/claude/agent.md (or templates/cline/agent.md).

---
name: risk-extractor
description: Extract the risk factors from a filing chunk as a bullet list. Use when asked "what risks…".
tools: Read, Grep
---
You are a risk-factor extractor. Read the retrieved chunks in reports/_context.json and
list each distinct risk as one bullet, citing the chunk id. Invent nothing; if no risks
appear in the context, say "No risk factors in the retrieved text."
Claude Code
Save as .claude/agents/risk-extractor.md. Claude auto-discovers it and can delegate to it based on the description.
Cline
Put the same persona into .clinerules (or .clinerules/risk-extractor.md) — Cline reads it as a project rule.
do it Add the agent, then ask: "What risks does NovaCorp disclose?" Watch which agent the assistant routes to.
Exercise 2 · add a skill

Package a repeatable workflow behind a /command

A skill names an ordered procedure you can invoke by typing /name. In Claude Code it's a SKILL.md; in Cline it's a workflow file — same idea.

# .claude/skills/risk-brief/SKILL.md   →   invoke with  /risk-brief "<company>"
---
name: risk-brief
description: Retrieve, extract, and grade a one-paragraph risk brief. Usage /risk-brief "<company>"
---
1. python -m tools.retrieve "<company> risk factors" -k 4 > reports/_context.json
2. Delegate to the risk-extractor agent to list the risks with citations.
3. python -m tools.grade ... ; if faithfulness < 0.7, revise.
4. Save to reports/<company>-risks.md.
Cline equivalent Save the same steps as .clinerules/workflows/risk-brief.md and run /risk-brief. Skeleton: templates/cline/workflow.md.
04

Wire two hooks

Deterministic guardrails the model can't skip — an audit log and a safety commit.
Exercise 3 · the two hooks

An audit log and a timed safety commit

A hook is a shell script wired to a lifecycle event in .claude/settings.json. Both scripts already exist in .claude/hooks/; you just wire and observe them.

1 · log-interaction.sh
On UserPromptSubmit and PostToolUse, appends one timestamped line per turn to logs/llm-interactions.log — the audit trail, made real.
2 · timed-commit.sh
On Stop, commits the working tree only if it's dirty and the last commit is older than 15 minutes — so a crash never costs more than a few minutes of work.
// .claude/settings.json
"hooks": {
  "UserPromptSubmit": [{ "hooks": [{ "type": "command", "command": ".claude/hooks/log-interaction.sh" }]}],
  "PostToolUse":      [{ "hooks": [{ "type": "command", "command": ".claude/hooks/log-interaction.sh" }]}],
  "Stop":             [{ "hooks": [{ "type": "command", "command": ".claude/hooks/timed-commit.sh" }]}]
}
Exercise 3 · observe & the Cline fallback

Watch them fire — then do it without native hooks

See them work (Claude Code)
  • Ask any question, then tail -f logs/llm-interactions.log — one line per turn.
  • Keep working past 15 min → a chore: timed safety commit appears in git log.
  • A non-zero PreToolUse hook can block an action — that's how a compliance gate works.
Cline has no hook engine
  • Timed commit: run the same script in a watch loop — while true; do bash .claude/hooks/timed-commit.sh; sleep 300; done
  • Logging: use Cline's task history, or wrap tools behind an MCP server that logs each call.
the lesson A hook is a property of the harness, not the model. When the harness lacks one, push the guardrail down to a layer that runs on its own — git, the OS scheduler, or an MCP proxy. See templates/cline/git-hooks-README.md.
05

Run the agent end to end

Put it together: a grounded, graded answer over real (fictional) filings.
Run it · the filing-Q&A agent

One command runs the whole Perceive → Reason → Act → Check loop

The bundled agent retrieves the most relevant chunks, writes a cited answer, grades it for faithfulness and relevance, and revises if it drifted off the source — entirely offline.

/ask "What is NovaCorp's customer concentration risk?"

# under the hood, the skill runs:
python -m tools.retrieve "customer concentration risk" -k 4 > reports/_context.json
# analyst agent drafts a cited answer from _context.json
python -m tools.grade --question "..." --answer "..." --context reports/_context.json
# if faithfulness < 0.7 → revise or answer "Not answerable from the available filings"
The pipeline
retrieveranalystgrader, each a one-job agent in .claude/agents/.
grounding The agent never recalls a figure from memory — it cites a chunk id for every number, and the grader blocks unfaithful answers.
Run it · break it on purpose

Things to try in the last ten minutes

  • Ask something the filings don't cover — e.g. "What was net income?" The agent must answer "Not answerable from the available filings," not guess.
  • Starve retrieval — drop -k to 1 and watch relevance fall.
  • Force a hallucination — make the analyst cite a number that isn't in the context, then run the grader and watch faithfulness drop and the loop send it back.
  • Add your /risk-brief skill from Exercise 2 and run it on NovaCorp.
  • Check the audit log — every step you just ran is one line in logs/llm-interactions.log.
tests Everything is offline and verifiable: python -m pytest -q.
Discussion · 5 min · in pairs

When would you add a second agent — or a hook?

Add a second agent when…
  • the task splits into sub-tasks with different tool needs
  • you need a critic / compliance checker separate from the generator
  • parallelism can cut latency
Add a hook when…
  • a cross-cutting concern (audit, cost) must touch every action
  • the concern is owned by a different team than the agent developer
  • you must enforce a policy without editing the agent's core logic
governance question Your filing agent's summary feeds a client note a junior analyst signs. What human-in-the-loop checkpoint would you impose, and which capability — agent, skill, or hook — enforces it?
Wrap-up

Five takeaways to carry out of the lab

  1. An agentic IDE is plain files under version control. Agents, skills, tools, and hooks are all text you can read, review, and diff.
  2. The pattern transfers. Claude Code's .claude/ and Cline's .clinerules express the same four capabilities.
  3. You rarely build a tool. Read, Grep, Bash & friends ship in; MCP is for what the environment can't already do.
  4. Hooks are deterministic guardrails. Native in Claude Code; pushed down to git / MCP in Cline. The model can't skip them.
  5. Grounding beats memory. Deterministic tools compute; the agent cites; the grader blocks unfaithful answers.
A

Appendix — stretch problem

Turn a Python tool into a real MCP tool both assistants can call.
Appendix · stretch problem

Promote a Python tool to an MCP server

Right now the agent calls tools/grade.py via Bash. Expose it as a first-class MCP tool so both Claude Code and Cline can call it by name with a typed schema.

Part 1 — define the tool
  • Wrap grade(question, answer, context) in a small MCP server
  • Give it a JSON input schema: question, answer, context_path
  • Return {faithfulness, relevance} as structured output
Part 2 — register it
  • Claude Code: add the server to .mcp.json
  • Cline: add it to cline_mcp_settings.json
  • Re-run /ask and confirm the grader is now a typed tool call, not a shell command
deliverable The MCP server file plus the registration snippet for each tool — and a one-line note on what a typed schema buys you over a raw Bash call.