Skip to content

Conversation

@vladislavdonchev
Copy link

Hook System Implementation - PR

Hey! This is a DRAFT, just floating the idea around (while testing it).
Interested to see what you guys think!

Summary

This pull request introduces a comprehensive hook system to Qwen Code, enabling users to execute custom scripts at key points in the application lifecycle. The implementation includes:

  • Complete hook system with HookManager, HookService, and configuration
  • 17 different hook types covering app lifecycle, tool execution, model interaction, file operations, and error handling
  • Support for hooks to execute any application via shell command execution
  • Claude Code hook format compatibility with event mapping
  • Claude-compatible hook execution with stdin/stdout communication
  • Support for both script file and inline hook definitions
  • Security measures for external script execution
  • New integration test suite for Claude-compatible hooks
  • Configuration files for event, tool name, and tool input format mappings

TLDR

This PR adds a powerful hook system that allows executing custom scripts at 17 different lifecycle events in Qwen Code. The system maintains full compatibility with Claude Code hooks while adding enhanced functionality for Qwen-specific workflows.

Dive Deeper

The implementation adds several new components to support the hook system:

  1. HookManager - Central registry that manages different hook types and executes them in priority order
  2. HookService - Service layer that integrates hooks with the configuration system
  3. HookSettings - Type definitions for hook configuration supporting both Qwen native and Claude-compatible hooks
  4. ToolNameMapper - Handles mapping between Claude Code and Qwen Code tool names
  5. ToolInputFormatMapper - Maps Qwen tool input formats to Claude-compatible formats
  6. PayloadConverter - Converts between Qwen and Claude payload formats for compatibility
  7. HookExecutor - Executes both external scripts and inline hook functions
  8. HookConfigLoader - Loads configuration mappings for events, tool names, and input formats

The system supports two types of hooks:

  • Qwen native hooks (scriptPath, inlineScript)
  • Claude-compatible hooks (with event mapping via claudeHooks configuration)

Security measures are maintained with path validation ensuring hooks run within the project directory, and configuration validation prevents insecure execution.

The Claude compatibility layer allows executing external commands that receive JSON payloads and can return responses that influence the Qwen workflow, including tool usage permissions and input modifications.

Reviewer Test Plan

  1. Check out the branch and run npm run build to ensure the project builds correctly
  2. Review the new hook system by examining the new files in packages/core/src/hooks/
  3. Test hook execution by creating a simple hook configuration in .qwen/settings.json:
    {
      "hooks": {
        "enabled": true,
        "hooks": [
          {
            "type": "session.start",
            "inlineScript": "console.log('Hook executed with payload:', payload);"
          }
        ]
      }
    }
  4. Run the hook tests with npx vitest run packages/core/src/hooks/ to ensure all tests pass
  5. Verify the README documentation accurately describes the new functionality
  6. Test Claude-compatible hooks by configuring claudeHooks in settings.json and running external scripts
  7. Review the new documentation files in docs/features/ to understand the hook system capabilities

Testing Matrix

🍏 🪟 🐧
npm run
npx
Docker
Podman - -
Seatbelt - -

Successfully tested on Linux and MacOS (build and test execution). All tests pass including the comprehensive new hook-specific tests.

Linked issues / bugs

Resolves the need for a comprehensive hook system to enable custom automation and integration in Qwen Code, including Claude Code compatibility for easy workflow migration!

Additional Features

The PR also includes implementation and documentation for other important Claude-compatible features:

  • Claude Compatibility Mode with qwen-alt CLI alias that supports Claude-style commands and arguments
  • System Prompt Customization using --append-system-prompt argument
  • Streaming JSON Output mode with --output-format stream-json for real-time processing of responses
  • Full compatibility with Claude Code workflows and hook systems

vladislavdonchev and others added 18 commits November 8, 2025 23:47
- Add complete hook system with HookManager, HookService, and configuration
- Implement 17 different hook types covering app lifecycle, tool execution, etc.
- Enable Claude Code hook compatibility with event mapping
- Add tool name mapping for Claude to Qwen tools
- Allow hooks to execute any application via shell command execution
- Add comprehensive documentation in README and docs/
- Include unit, integration, and error handling tests
- Support both script file and inline hook definitions
- Implement security measures for external script execution
… hook system

- Add created_at and completed_at timestamp fields to TodoItem interface for Claude compatibility
- Update todoWrite tool to properly handle Claude-compatible timestamp fields
- Enhance todoWrite tests to cover timestamp functionality
- Add Claude-compatible configuration files and adapter
- Update hook manager tests with proper Config interface
- Update alias creation script to support Claude compatibility adapter
…hook mapping functionality

- Add created_at and completed_at fields to TodoItem interface for Claude compatibility
- Update todoWrite tool to properly handle Claude-compatible timestamp fields
- Enhance todoWrite tests to cover Claude-compatible functionality
- Update HookService and ToolNameMapper with improved Claude compatibility
- Update the claude adapter with proper help text and mappings
- Add proper validation for Claude-compatible timestamp fields
- Update documentation to reflect implemented features
- Fixed property access errors by using bracket notation for index signatures
- Resolved type mismatches in HookService.ts and related test files
- Fixed fs import inconsistencies in HookService.ts
- Applied proper type assertions where needed
- Removed unused imports and variables
- Updated color theme definitions to use specified palette
- Improved error handling and type safety in multiple modules
- Restored original ASCII art and theme files as requested
- Fixed syntax and structural issues in multiple files
- Fix all TypeScript compilation errors in HookService.ts by removing incorrect casting syntax
- Correct malformed import statements and method calls
- Fix property access issues with unknown types
- Update hook-compatibility-claude.md with complete hook documentation including:
  - Additional Claude hook events like Notification
  - More complete tool mappings
  - Hook execution behavior and configuration options
  - Tool input format mapping configuration details

Co-authored-by: Qwen-Coder <[email protected]>
- Implement timeoutMs functionality in HookExecutionOptions
- Remove unused payload parameters from PayloadConverter methods
- Use HookConfigLoader for all configuration loading in PayloadConverter
- Add proper dependency injection of HookConfigLoader to PayloadConverter
- Remove unused methods and fix architectural issues

Co-authored-by: Qwen-Coder <[email protected]>
- Add HookConfigLoader for loading configuration mappings
- Add HookExecutor for executing scripts with security validations
- Add HookManager for managing hook lifecycle and execution
- Add HookService as the main service interface
- Add PayloadConverter for Claude-compatible format conversion
- Add comprehensive tests for all hook system components
- Include security features: path traversal prevention and timeout enforcement
- Add integration tests for end-to-end functionality
- Update .gitignore to include scripts/log/ directory
- Add appendSystemPrompt field to CliArgs interface
- Add --append-system-prompt option to yargs configuration
- Update ConfigParameters interface to include additionalSystemPrompt
- Update Config class to store and provide additional system prompt
- Modify getCoreSystemPrompt function to append additional prompt
- Update all relevant calls to pass the additional system prompt
- Add tests for append-system-prompt functionality in CLI and core
- Extend existing tests to include the new functionality
- Add STREAM_JSON output format option to OutputFormat enum
- Implement stream-json mode in nonInteractiveCli with Claude-compatible event structure
- Add tests for stream-json output format covering content, tool calls, errors, and thoughts
- Update CLI argument parser to accept 'stream-json' as output format choice
- Update claude-adapter.js help text to document new stream-json format
- Create SPEC-STREAMING.md specification document for the feature
…prompt alias

- Document qwen-alt Claude-compatible alias in README
- Document --append-system-prompt argument with examples
- Document streaming JSON output mode with examples
- Remove incorrect --system-prompt parameter alias from claude adapter
- Only --append-system-prompt is now allowed as per requirements

Co-authored-by: Qwen-Coder <[email protected]>
@Mingholy
Copy link
Collaborator

Thanks for the contribution!
We do have a PR #926 that provides stream-json output and sets up a basic control system for input-format=stream-json, which is prepared for potential SDK use. We're going to build more things based on that.
We will build a hook system similar to Claude-code, but will not immediately eliminate the differences in tools/settings.
Furthermore, we need to consider that hooks must meet two common requirements: configuration via settings.json, or via control protocol (used by the SDK).

We appreciate your ideas and feedback and will try to implement them as soon as we can, but this PR will not be merged for the time being.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants