Topic: Qwen Code Hook Examples
Difficulty level: Medium
Estimated study time: 4-6 hours (theory + practice)
Prerequisites: Basic knowledge of Python (syntax, file operations, JSON)
Understanding of command line and Bash operation
Experience working with Qwen Code or similar AI programming assistants
Familiarity with the concept of hooks in software systems
Basic skills working with Git and version control systems
Learning objectives: Configure and activate three types of Qwen Code hooks (pre_tool_guard, log_tool_result, inject_sdd_context) according to examples from the documentation
Modify the pre_tool_guard.py script to add user-defined dangerous commands to the block list
Analyze and extend the tool logging system via log_tool_result.py for a specific project's needs
Integrate project SDD file context into the workflow via inject_sdd_context.py
Manually merge settings from settings-workflow.example.json with the existing .qwen/settings.json without losing configuration
Overview: This study guide is dedicated to the practical mastery of the hook system in Qwen Code — a mechanism for extending the functionality of an AI programming assistant. Hooks allow intercepting and modifying tool behavior at various stages of execution: before launch (pre-), after completion (post-), as well as injecting additional context into the workflow. The material is based on three production-ready examples from part 17 of the tutorial: the pre_tool_guard.py security system, the log_tool_result.py audit system, and the inject_sdd_context.py contextual enrichment mechanism. Studying these examples will give you the skills to create your own hooks for solving real-world tasks: from preventing accidental data deletion to automatic documentation of AI assistant actions.
Key concepts: Hook: An extension point in the Qwen Code architecture, representing an executable script (usually in Python) that is called at a specific moment in a tool's lifecycle. Hooks allow modifying system behavior without changing its core, implementing the Inversion of Control principle.
Pre-tool hook: A hook that executes BEFORE a tool is launched. Used for validation, blocking dangerous operations, requesting additional confirmations. The pre_tool_guard.py example implements protection against executing destructive Bash commands.
Post-tool hook: A hook that executes AFTER a tool has completed. Applied for logging, analyzing results, notifications, post-processing data. The log_tool_result.py example demonstrates compact event logging in JSON Lines format.
Context hook (context injection): A hook that injects additional information into the conversation context with AI. The inject_sdd_context.py example automatically adds a reminder about SDD file structure (Software Design Document), helping the model follow the project's architectural decisions.
Settings-workflow.example.json: An example configuration file demonstrating the syntax for connecting multiple hooks simultaneously. Contains a hooks structure with specified path, event type, and execution priority.
JSON Lines (jsonl): A text file format where each line represents a separate valid JSON object. Used in log_tool_result.py for compact and easily parseable logging: new events are simply appended to the end of the file without needing to rewrite the entire structure.
SDD (Software Design Document): A document describing software architecture. In the context of the inject_sdd_context.py hook, this is meta-information about the project that the AI must consider when generating code to maintain consistency with adopted project decisions.
Executable permissions (chmod +x): A file system attribute in Unix-like operating systems that allows running a script as a program. Critically important for Qwen Code hooks, as the system calls them directly through the exec mechanism.
Manual settings merging: The process of integrating example configuration into an existing settings.json without automatic merge tools. Requires attention to preserve current user settings and correctly maintain JSON syntax.
Practice exercises: Name: Installation and activation of a basic security hook
Problem: Copy the pre_tool_guard.py file from examples into the .qwen/hooks/ directory, make it executable, manually add the corresponding section to your .qwen/settings.json. Test the operation: launch Qwen Code and ask it to execute the command 'rm -rf /tmp/test'. Ensure the hook blocks execution. Then add 'dd if=/dev/zero of=/dev/sda' to the forbidden commands list and verify blocking of this command.
Solution: 1. Create directory: mkdir -p ~/.qwen/hooks/
- Copy script: cp pre_tool_guard.py ~/.qwen/hooks/
- Make executable: chmod +x ~/.qwen/hooks/pre_tool_guard.py
- Open ~/.qwen/settings.json in editor
- Add hooks section (or extend existing):
{ "hooks": [ { "path": "~/.qwen/hooks/pre_tool_guard.py", "event": "pre_tool", "tool": "Bash", "priority": 100 } ] }
- Save file, verify JSON validity
- Launch Qwen Code, request execution of 'rm -rf /tmp/test'
- Verify blocking by hook message
- Edit pre_tool_guard.py: add 'dd if=/dev/zero of=/dev/sda' to dangerous_commands list
- Restart Qwen Code, verify blocking of new command
Complexity: beginner
Name: Extending the logging system with filtering
Problem: Activate the log_tool_result.py hook. Create a scenario where a log accumulates during 10 minutes of work with Qwen Code. Then modify the hook: add filtering — only log Bash tool events and only if the command executed longer than 1 second. Verify that the filtered log contains only the needed records.
Solution: 1. Install log_tool_result.py following the same procedure as the first exercise
- Add hook to settings.json with event: "post_tool"
- Perform various tasks: reading files, Bash commands, search
- Check accumulated log: cat ~/.qwen/hooks/logs/tool-events.jsonl | jq .
- Create backup copy of original hook
- Modify script: add check at beginning of processing function:
if tool_name != 'Bash': return if result.get('duration_ms', 0) < 1000: return
- Save, make executable again
- Clear log: > ~/.qwen/hooks/logs/tool-events.jsonl
- Repeat work scenario
- Verify that log contains only long Bash commands
- Compare log volumes before and after filtering
Complexity: intermediate
Name: Creating a comprehensive SDD context for the team
Problem: Develop a system of three SDD files for your project: architecture.md, api-contracts.md, code-style.md. Configure inject_sdd_context.py for automatic injection of relevant context depending on the type of user request. If the request contains 'API' or 'endpoint' — inject api-contracts.md, if 'refactoring' or 'style' — code-style.md, in other cases — architecture.md. Verify operation on test requests.
Solution: 1. Create project directory: mkdir -p ~/my-project/sdd/
- Create three files with meaningful content (5-10 items each)
- Copy inject_sdd_context.py to ~/.qwen/hooks/
- Modify file selection logic:
import re def select_sdd(user_message): msg_lower = user_message.lower() if any(kw in msg_lower for kw in ['api', 'endpoint', 'rest']): return 'api-contracts.md' elif any(kw in msg_lower for kw in ['refactoring', 'style', 'formatting']): return 'code-style.md' else: return 'architecture.md'
- Update hook's main function to use select_sdd
- Configure in settings.json hook with event: "pre_tool" or "pre_message" (depending on Qwen Code version)
- Test sequentially:
- "Create API endpoint for users" → should pull api-contracts.md
- "Refactor this module according to project style" → code-style.md
- "How to organize the database?" → architecture.md
- Check via debug output or log which file was selected
- Document selection rules in project README
Complexity: intermediate
Name: Backup and recovery of settings during merging
Problem: You already have a complex .qwen/settings.json configured with custom prompts, model preferences, and one legacy hook. Obtain settings-workflow.example.json from the tutorial and correctly integrate all three new hooks while preserving the existing configuration. Create a validator script that will verify the integrity of the resulting JSON and absence of duplicates in the hooks array.
Solution: 1. Create backup copy: cp ~/.qwen/settings.json ~/.qwen/settings.json.backup.$(date +%s)
- Study current structure: cat ~/.qwen/settings.json | jq 'keys'
- Study settings-workflow.example.json: cat settings-workflow.example.json | jq '.hooks'
- Create intermediate file merge.json
- Manually merge: copy root fields from both files
- For hooks array: extract existing, add new with correct priorities
- Ensure uniqueness of combinations (path + event + tool):
jq '.hooks | group_by(.path, .event, .tool) | map(select(length > 1)) | length' merge.json Result should be 0
- Verify JSON validity: python3 -c "import json; json.load(open('merge.json'))"
- Create validate-settings.py script to automate checks
- Apply: cp merge.json ~/.qwen/settings.json
- Launch Qwen Code, verify all hooks work
- In case of error — rollback from backup
Complexity: advanced
Case studies: Name: Implementing security hooks in a fintech startup
Scenario: A team of 8 developers at a fintech startup actively used Qwen Code to accelerate microservices development. In the first month, two incidents occurred: once the AI assistant suggested and almost executed the command 'DROP TABLE transactions CASCADE' in a developer's working database, another time — 'kubectl delete namespace production' due to ambiguous context in the request. Management demanded implementation of a multi-level protection system without substantially slowing down the workflow.
Challenge: Main difficulties: (1) The existing pre_tool_guard.py from examples covered only obviously dangerous commands rm -rf, mkfs, dd, but knew nothing about fintech infrastructure specifics (kubectl, psql, liquibase). (2) Developers resisted additional confirmations, considering them "bottlenecks". (3) A centralized audit system was needed for incident investigation. (4) The team worked with sensitive data, so logs could not be sent to external systems.
Solution: The team adapted three hooks from the tutorial into a comprehensive system: (1) Extended pre_tool_guard.py: added patterns for SQL commands (DROP, TRUNCATE without WHERE), kubectl operations (delete, drain, taint), and specific utilities (liquibase dropAll, flyway clean). Implemented danger gradation: "block" for catastrophic commands, "require explicit confirmation" for risky, "warning" for potentially problematic. (2) Configured log_tool_result.py with local storage on an encrypted partition, added masking of sensitive data (PAN, CVV) via regex replacement before writing. (3) Created inject_sdd_context.py with corporate standards: when working with DB — reminder about prohibition of direct operations without migrations, when working with k8s — namespace isolation rules. Introduced gradually: first in logging mode without blocking (observation week), then soft warnings, finally — full blocking.
Result: Over 6 months of system operation: prevented 23 potentially dangerous operations (14 — SQL commands without migrations, 7 — kubectl operations in production context, 2 — data cleanup attempts). Average time for confirming "gray zone" commands — 8 seconds, which the team considered acceptable. Audit trail allowed reconstructing the chronology of an incident with test customer data in 15 minutes. Developers noted that SDD context reduced time explaining architectural decisions to new team members by 30%. The system became a benchmark for other teams in the holding.
Lessons learned: Start security hook implementation in audit-only mode: log without blocking to measure real frequency of dangerous scenarios and avoid false positives
Adapt dangerous command lists to your infrastructure specifics: universal pre_tool_guard.py is only a starting point
Reaction gradation (block / confirmation / warning) is critically important for balancing security and development speed
Local logging with masking resolves the conflict between audit needs and information security requirements
Context hooks (inject_sdd_context) work as "passive protection": prevent errors before they occur, reducing load on active blocks
Related concepts: Pre-tool hook
Post-tool hook
Context hook (Context injection)
Manual settings merging
JSON Lines (JSONL)
Name: Optimizing logging in a distributed development team
Scenario: A distributed team of 15 developers in three time zones worked on a large open-source project using Qwen Code. Coordinators faced a problem: when errors occurred in AI-generated code, it was impossible to reconstruct which specific tools and with what parameters were executed. Standard Qwen Code logs were insufficiently detailed, and developers forgot to manually document complex sessions.
Challenge: Key problems: (1) Standard log_tool_result.py wrote locally on each developer's machine, making aggregation impossible. (2) Log volume grew linearly, after a month the tool-events.jsonl file reached 500 MB, slowing down reading. (3) Logs contained no session identifier, complicating event correlation. (4) Some tools (e.g., repeated code search) generated "noise" — hundreds of useless records. (5) Privacy compliance was required: logs must not contain content from files with secrets.
Solution: The team created an evolution of the standard hook: (1) Added session identifier (UUID4, generated at Qwen Code startup via QWEN_SESSION_ID environment variable) to the log. (2) Implemented log rotation: daily creation of new file tool-events-YYYY-MM-DD.jsonl with archiving old ones via gzip. (3) Added filtering by tool type: only Bash, Edit, Write were logged — tools that change system state. Read, Search, Glob were excluded as non-modifying. (4) Implemented sanitization: before writing, content was checked against secret patterns (AWS keys, tokens via regex), with match — replaced by [REDACTED]. (5) Created optional synchronization: when QWEN_LOG_SYNC_URL variable was present, anonymized logs were sent to a central S3-compatible bucket for aggregation.
Result: The logging system became transparent and scalable: average size of active log file decreased from 500 MB to 12 MB. Log search time reduced from minutes to seconds thanks to daily segmentation. 94% of sessions were successfully correlated by session_id when escalating problems. Identified 3 systematic errors in AI behavior (cyclic calling of one tool), which were fixed upstream. Sanitization system passed security audit with zero leaks over 4 months of operation. Hook code was extracted into a separate open-source repository, receiving 340 stars.
Lessons learned: Rotation and log segmentation are mandatory for long-term operation: monolithic JSONL file does not scale
Session identifiers transform local logs into a traceable system: investment in one line of code brings order to analysis
Filtering by "state-changing" tools reduces noise by 80-90% without losing critical information
Sanitization must be proactive, not reactive: embed secret pattern checks before the first incident
Open-source approach to hook development creates network effect: external contributions improve your system without direct costs
Related concepts: Post-tool hook
JSON Lines (JSONL)
Executable permissions (chmod +x)
Study tips: Start with a single hook: install pre_tool_guard.py, verify its operation, only then add others. Parallel installation of all three increases probability of configuration error by 3-4 times
Keep a "lab journal" — a separate file where you record every change to settings.json with date and verification result. This will save you during rollback after a merge error
Use jq for validation and studying JSON structures: jq '.' settings.json checks syntax, jq '.hooks | length' counts hooks, jq '.hooks[] | select(.event=="pre_tool")' filters by type
Create a test "sandbox" — an isolated project with a copy of .qwen/ where you can experiment without risk of breaking the working configuration
To understand data flow, temporarily add debug output to stderr in each hook: print(f"DEBUG: hook triggered for {tool_name}", file=sys.stderr). Remove after debugging
Study source scripts line by line, not copying blindly. Try to predict what the next line does before reading the comment — this will accelerate understanding of the architecture
Practice manual merging on simple examples: take two small JSON files, merge them in a text editor, verify with a validator. The skill will be useful when updating Qwen Code versions
For auditory perception: read scripts aloud, explaining logic to an imaginary interlocutor. This activates other memory channels and reveals gaps in understanding
Create a hook verification checklist: executable permissions? correct shebang? valid JSON in settings? correct event? uniqueness in hooks array? — and run through before each launch
When modifying hooks, use version control: initialize git in ~/.qwen/hooks/, commit each working state. Rollback to previous commit is faster than manual recovery
Additional resources: Official Qwen Code documentation (part 17): Original tutorial containing settings-workflow.example.json and three reference hook implementations — starting point for all modifications
JSON Lines specification: https://jsonlines.org/ — formal description of the format used in log_tool_result.py, with parsing examples in different languages
Python subprocess module documentation: https://docs.python.org/3/library/subprocess.html — deep understanding of mechanisms for launching and interacting with external processes underlying hooks
jq manual: https://stedolan.github.io/jq/manual/ — indispensable tool for working with JSON configurations and logs in command line
"Secure by Design" (Manning Publications): Book about principles of designing secure systems, applicable to hook architecture — especially the chapter on fail-safe defaults and defense in depth
Git hooks documentation: https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks — parallel hook ecosystem for comparing patterns and best practices
Open-source repository enhanced-qwen-hooks: Hypothetical community extension of standard hooks with additional examples and tests (search by keywords on GitHub)
Summary: The Qwen Code hook system represents a powerful mechanism for extending an AI programming assistant through three key injection points: pre-validation (pre_tool_guard.py), post-factum audit (log_tool_result.py), and contextual enrichment (inject_sdd_context.py). Mastering these examples requires understanding not only Python and JSON syntax, but also architectural principles: inversion of control, event reaction gradation, balance of security and convenience. A critically important skill is manual configuration merging — an operation requiring attention and systematic approach. Successful application of hooks transforms Qwen Code from a passive tool into an actively managed system with corporate security policies, transparent audit, and consistent architectural discipline. Start simple, document every step, use version control for scripts — and you will obtain a reliable infrastructure, scalable from individual development to distributed teams.