Coder Social home page Coder Social logo

lurk's Introduction

lurk

CICD

lurk is a simple and pretty alternative to strace. It allows the user to trace system calls of a process or of a command. In contrast to strace, lurk focuses on a simple, yet pretty, user experience while implementing the most important use cases of strace.

Demo

Demo

Features

  • Supports an opinionated subset of strace flags.
  • Supports JSON output for further processing via e.g. jq
  • Uses colorized, formatted output ;-).

Installation

cURL

curl -L -o /tmp/lurk.tar.gz "https://github.com/JakWai01/lurk/releases/latest/download/lurk-x86_64-unknown-linux-gnu.tar.gz"
tar -xzf /tmp/lurk.tar.gz -C /tmp
sudo install /tmp/lurk /usr/local/bin

Cargo

cargo install lurk-cli

Arch Linux

pacman -S lurk

Usage

To get a quick overview, you can run lurk --help:

lurk 0.2.7

USAGE:
    lurk [OPTIONS] [command]...

ARGS:
    <command>...    Trace command

OPTIONS:
    -c, --summary-only
            Report a summary instead of the regular output

    -C, --summary
            Report a summary in addition to the regular output

    -e, --expr <expr>
            A qualifying expression which modifies which events to trace or how to trace them.

    -E, --env <env>
            --env var=val adds an environment variable. --env var removes an environment variable.

    -f, --follow-forks
            Trace child processes as they are created by currently traced processes.

    -h, --help
            Print help information

    -j, --json
            Display output in JSON format

    -n, --syscall-number
            Display system call numbers

    -o, --file <file>
            Name of the file to print output to

    -p, --attach <attach>
            Attach to a running process

    -s, --string-limit <string-limit>
            Maximum string size to print

    -T, --syscall-times
            Show the time spent in system calls in ms.

    -u, --username <username>
            Run the command with uid, gid and supplementary groups of username.

    -v, --no-abbrev
            Print unabbreviated versions of strings

    -V, --version
            Print version information

    -z, --successful-only
            Print only syscalls that returned without an error code

    -Z, --failed-only
            Print only syscalls that returned with an error code

Basic trace

Basically, there are two ways of tracing system calls. You can either execute a command directly or attach to a running process by providing the process ID (PID) via --attach. In the latter case, the command has to be run with escalated privileges (sudo).

Executing a command

$ lurk ls
[54605] execve("", "", "") = 0
[54605] brk(NULL) = 0x55578000
[54605] arch_prctl(12289, 0xffffe780) = -22
[54605] access("", 4) = -2
[54605] openat(4294967196, "/etc/ld.so.cache", 524288) = 3
[54605] newfstatat(3, "", 0xffffd9a0, 4096) = 0
[54605] mmap(NULL, 92599, 1, 2, 3, 0) = 0xf7fa9000
...

Attaching to a running process

$ sudo lurk --attach $PID
[54683] epoll_wait(5, 0xd01a3c20, 8, 4294967295) = -4
[54683] recvmsg(3, 0x4a4a0020, 0) = -11
[54683] recvmsg(3, 0x4a4a0020, 0) = -11
[54683] clock_gettime(1, 0x4a49df40) = 0
[54683] clock_gettime(1, 0x4a4a0220) = 0
[54683] recvmsg(3, 0x4a4a0050, 0) = -11
...

Filtering with --expr

Unlike in strace, lurk only supports --expr trace. Since this flag behaves almost exactly like in strace, here a short, slightly changed, excerpt of the strace manpage on how to use lurk --expr trace:

 -e trace=syscall_set
       --trace=syscall_set
              Trace only the specified set of system calls.  syscall_set
              is defined as [!]value[,value], and value can be one of
              the following:

              syscall
                     Trace specific syscall, specified by its name (but
                     see NOTES).

              ?value Question mark before the syscall qualification
                     allows suppression of error in case no syscalls
                     matched the qualification provided.

              /regex Trace only those system calls that match the regex.
                     You can use POSIX Extended Regular Expression
                     syntax (see regex(7)).

              %file
              file   Trace all system calls which take a file name as an
                     argument.  You can think of this as an abbreviation
                     for -e trace=open,stat,chmod,unlink,...  which is
                     useful to seeing what files the process is
                     referencing.  Furthermore, using the abbreviation
                     will ensure that you don't accidentally forget to
                     include a call like lstat(2) in the list.  Betchya
                     woulda forgot that one.  The syntax without a
                     preceding percent sign ("-e trace=file") is
                     deprecated.

              %process
              process
                     Trace system calls associated with process
                     lifecycle (creation, exec, termination).  The
                     syntax without a preceding percent sign ("-e
                     trace=process") is deprecated.

              %net
              %network
              network
                     Trace all the network related system calls.  The
                     syntax without a preceding percent sign ("-e
                     trace=network") is deprecated.

              %signal
              signal Trace all signal related system calls.  The syntax
                     without a preceding percent sign ("-e
                     trace=signal") is deprecated.

              %ipc
              ipc    Trace all IPC related system calls.  The syntax
                     without a preceding percent sign ("-e trace=ipc")
                     is deprecated.

              %desc
              desc   Trace all file descriptor related system calls.
                     The syntax without a preceding percent sign ("-e
                     trace=desc") is deprecated.

              %memory
              memory Trace all memory mapping related system calls.  The
                     syntax without a preceding percent sign ("-e
                     trace=memory") is deprecated.

              %creds Trace system calls that read or modify user and
                     group identifiers or capability sets.

              %stat  Trace stat syscall variants.

              %lstat Trace lstat syscall variants.

              %fstat Trace fstat, fstatat, and statx syscall variants.

              %%stat Trace syscalls used for requesting file status
                     (stat, lstat, fstat, fstatat, statx, and their
                     variants).

              %statfs
                     Trace statfs, statfs64, statvfs, osf_statfs, and
                     osf_statfs64 system calls.  The same effect can be
                     achieved with -e trace=/^(.*_)?statv?fs regular
                     expression.

              %fstatfs
                     Trace fstatfs, fstatfs64, fstatvfs, osf_fstatfs,
                     and osf_fstatfs64 system calls.  The same effect
                     can be achieved with -e trace=/fstatv?fs regular
                     expression.

              %%statfs
                     Trace syscalls related to file system statistics
                     (statfs-like, fstatfs-like, and ustat).  The same
                     effect can be achieved with
                     -e trace=/statv?fs|fsstat|ustat regular expression.

              %clock Trace system calls that read or modify system
                     clocks.

              %pure  Trace syscalls that always succeed and have no
                     arguments.  Currently, this list includes
                     arc_gettls(2), getdtablesize(2), getegid(2),
                     getegid32(2), geteuid(2), geteuid32(2), getgid(2),
                     getgid32(2), getpagesize(2), getpgrp(2), getpid(2),
                     getppid(2), get_thread_area(2) (on architectures
                     other than x86), gettid(2), get_tls(2), getuid(2),
                     getuid32(2), getxgid(2), getxpid(2), getxuid(2),
                     kern_features(2), and metag_get_tls(2) syscalls.

              The -c option is useful for determining which system calls
              might be useful to trace.  For example,
              trace=open,close,read,write means to only trace those four
              system calls.  Be careful when making inferences about the
              user/kernel boundary if only a subset of system calls are
              being monitored.  The default is trace=all.

Note: When negating a statement with !, make sure to escape it (\!) when using bash.

Filtering for system calls not containing the letter o

$ lurk --expr trace=\!/o ls
[55155] execve("", "", "") = 0
[55155] brk(NULL) = 0x55578000
[55155] arch_prctl(12289, 0xffffe780) = -22
[55155] access("", 4) = -2
[55155] newfstatat(3, "", 0xffffd9a0, 4096) = 0
[55155] mmap(NULL, 92599, 1, 2, 3, 0) = 0xf7fa9000
[55155] read(3, "\u{7f}ELF\u{2}\u{1}\u{1}", 832) = 832
...

Filtering only for all system calls taking a file as an argument

$ lurk --expr trace=%file ls
[55121] access("", 4) = -2
[55121] openat(4294967196, "/etc/ld.so.cache", 524288) = 3
[55121] newfstatat(3, "", 0xffffd9a0, 4096) = 0
[55121] openat(4294967196, "/usr/lib/libcap.so.2", 524288) = 3
[55121] newfstatat(3, "", 0xffffd9a0, 4096) = 0
[55121] openat(4294967196, "/usr/lib/libc.so.6", 524288) = 3
[55121] newfstatat(3, "", 0xffffd980, 4096) = 0
...

Suppress error for prctl system call

$ lurk --expr trace=?prctl ls
[55407] execve("", "", "") = 0
[55407] brk(NULL) = 0x55578000
[55407] arch_prctl(12289, 0xffffe780) = -22
[55407] access("", 4) = -2
[55407] openat(4294967196, "/etc/ld.so.cache", 524288) = 3
[55407] newfstatat(3, "", 0xffffd9a0, 4096) = 0
[55407] mmap(NULL, 92599, 1, 2, 3, 0) = 0xf7fa9000

Only output openat, close and mmap system calls

$ lurk --expr trace=openat,close,mmap ls
[55440] openat(4294967196, "/etc/ld.so.cache", 524288) = 3
[55440] mmap(NULL, 92599, 1, 2, 3, 0) = 0xf7fa9000
[55440] close(3) = 0
[55440] openat(4294967196, "/usr/lib/libcap.so.2", 524288) = 3
[55440] mmap(NULL, 8192, 3, 34, 4294967295, 0) = 0xf7fa7000
[55440] mmap(NULL, 45128, 1, 2050, 3, 0) = 0xf7f9b000
[55440] mmap(0xf7f9e000, 20480, 5, 2066, 3, 12288) = 0xf7f9e000

Using as a Rust library

See the tracer example.

Acknowledgements

  • sharkdp/fd as an inspiration on how to structure a Rust CLI and its README.
  • All maintainers of the dependencies used to create lurk and all of those who answered my questions regarding ptrace.

License

lurk (c) 2022-2023 Jakob Waibel, Yuri Astrakhan, and contributors

SPDX-License-Identifier: MIT OR Apache-2.0

lurk's People

Contributors

aiellochan avatar badboy avatar figsoda avatar heroickatora avatar jakwai01 avatar kianmeng avatar kxxt avatar m1dsummer avatar nyurik avatar orhun avatar tramasys avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

lurk's Issues

Migrate to new Clap crate

I'll be happy to contribute this (and possibly other) minor linting of the code, e.g. make formatting a bit more streamlined and remove some code dups

32 bit syscalls not showing up

Summary

I wrote a very show assembly script and compiled it with nasm that just executes the getpid and exit syscalls. These syscalls never show up in lurk but strace shows them.

Details

Code

SECTION .text
	global main

	main:
	  xor eax, eax             ; eax = 0
	  mov al, 20               ; syscall: getpid
	  int 0x80                 ; execute

	  xor eax, eax             ; eax = 0
	  xor ebx, ebx             ; exit code = 0
	  mov al, 1                ; syscalL: exit
	  int 0x80                 ; execute syscall

Compilation

nasm -f elf64 syscall.asm
clang -o asm syscall.o

Execution

❯ lurk ./asm
[74982] execve("", "", "") = 0
[74982] brk(0x0) = 0x555555559000
[74982] arch_prctl(12289, 0x7FFFFFFFE450) = -22
[74982] access("/etc/ld.so.preload", 4) = -2
[74982] openat(4294967196, "/etc/ld.so.cache", 524288) = 3
[74982] newfstatat(3, "", 0x7FFFFFFFD680, 4096) = 0
[74982] mmap(0x0, 79203, 1, 2, 3, 0) = 0x7FFFF7FB0000
[74982] close(3) = 0
[74982] openat(4294967196, "/usr/lib/libc.so.6", 524288) = 3
[74982] read(3, "ELF\u0002\u0001\u0001\u0003", 832) = 832
[74982] pread64(3, "\u0006", 784, 64) = 784
[74982] newfstatat(3, "", 0x7FFFFFFFD680, 4096) = 0
[74982] mmap(0x0, 8192, 3, 34, 4294967295, 0) = 0x7FFFF7FAE000
[74982] pread64(3, "\u0006", 784, 64) = 784
[74982] mmap(0x0, 1973104, 1, 2050, 3, 0) = 0x7FFFF7DCC000
[74982] mmap(0x7FFFF7DF2000, 1417216, 5, 2066, 3, 155648) = 0x7FFFF7DF2000
[74982] mmap(0x7FFFF7F4C000, 344064, 1, 2066, 3, 1572864) = 0x7FFFF7F4C000
[74982] mmap(0x7FFFF7FA0000, 24576, 3, 2066, 3, 1912832) = 0x7FFFF7FA0000
[74982] mmap(0x7FFFF7FA6000, 31600, 3, 50, 4294967295, 0) = 0x7FFFF7FA6000
[74982] close(3) = 0
[74982] mmap(0x0, 8192, 3, 34, 4294967295, 0) = 0x7FFFF7DCA000
[74982] arch_prctl(4098, 0x7FFFF7FAF640) = 0
[74982] set_tid_address(0x7FFFF7FAF910) = 0x124E6
[74982] set_robust_list(0x7FFFF7FAF920, 24) = 0
[74982] rseq() = 0
[74982] mprotect(0x7FFFF7FA0000, 16384, 1) = 0
[74982] mprotect(0x555555557000, 4096, 1) = 0
[74982] mprotect(0x7FFFF7FFB000, 8192, 1) = 0
[74982] prlimit64(0, 3, 0x0, 0x7FFFFFFFE1C0) = 0
[74982] munmap(0x7FFFF7FB0000, 79203) = 0
[74982] writev(1, 0x7FFFFFFFE5A8, 140737488348600) = 0x124E6

strace

❯ strace ./asm
execve("./asm", ["./asm"], 0x7fff374545a0 /* 56 vars */) = 0
brk(NULL)                               = 0x55fcbfd58000
arch_prctl(0x3001 /* ARCH_??? */, 0x7ffe155b8950) = -1 EINVAL (Invalid argument)
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=79203, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 79203, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f8134589000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\220~\2\0\0\0\0\0"..., 832) = 832
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
newfstatat(3, "", {st_mode=S_IFREG|0755, st_size=1948832, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f8134587000
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
mmap(NULL, 1973104, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f81343a5000
mmap(0x7f81343cb000, 1417216, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x26000) = 0x7f81343cb000
mmap(0x7f8134525000, 344064, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x180000) = 0x7f8134525000
mmap(0x7f8134579000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1d3000) = 0x7f8134579000
mmap(0x7f813457f000, 31600, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f813457f000
close(3)                                = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f81343a3000
arch_prctl(ARCH_SET_FS, 0x7f8134588640) = 0
set_tid_address(0x7f8134588910)         = 75997
set_robust_list(0x7f8134588920, 24)     = 0
rseq(0x7f8134588f60, 0x20, 0, 0x53053053) = 0
mprotect(0x7f8134579000, 16384, PROT_READ) = 0
mprotect(0x55fcbf7a6000, 4096, PROT_READ) = 0
mprotect(0x7f81345ce000, 8192, PROT_READ) = 0
prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
munmap(0x7f8134589000, 79203)           = 0
[ Process PID=75997 runs in 32 bit mode. ]
strace: WARNING: Proper structure decoding for this personality is not supported, please consider building strace with mpers support enabled.
getpid()                                = 75997
exit(0)                                 = ?
+++ exited with 0 +++

Version details

lurk 0.3.4
strace 6.6
NASM 2.16.01
clang 16.0.6
linux 6.5.9-arch2-1

execve no argument

when I tracing ls command, execve system function has no arguments.

(base) ubuntu@ubuntu-Parallels-Virtual-Platform:~$ lurk ls | head
[23549] execve("", "", "") = 0
[23549] brk(0x0) = 0x555555579000
[23549] arch_prctl(12289, 0x7FFFFFFFE060) = -22

Is this a bug? strace do it well.

follow-forks flag seems to be not working correctly

Hello, thanks for this nice project

I tried debugging a project with lurk but I noticed 2 problems with -f:

  • Sometimes it hang and doesn't terminate
  • When it does terminate paradoxically the output is really short its shorter then without -f flag

For example here is a comparison of running without -f and with -f

without -f:
https://pastebin.com/4bD03gYG
with -f:
https://pastebin.com/e6AjTwRm

Reproduction

lurk -f deno run --unstable -A https://pastebin.com/raw/XkLSzG34

If you try this multiple times sometimes it hangs on epollwait, and when it succeeds the output is very short, shorter then without -f flag.

meta:

  • Linux 5.18.13-arch1-1 1 SMP PREEMPT_DYNAMIC Fri, 22 Jul 2022 13:05:04 +0000 x86_64 GNU/Linux
  • deno 1.24.0
  • lurk 0.2.9

String argument formatting

Command

lurk -j cat /etc/fstab|jq 'select(.syscall == "openat") | .args[1]'

Result

"\"/usr/local/lib/x86_64-linux-gnu/\"..."
"\"/usr/local/lib/x86_64-linux-gnu/\"..."

Expected Result

"/usr/local/lib..."

Using Json and output interleaves output formats

Reproduction

lurk --json -o /tmp/test ls

Expected

The output file /tmp/test to represent valid json.

Actual

$ jq < /tmp/test 
[
  7008
]
parse error: Invalid numeric literal at line 1, column 15

This is because the file starts with some non-json print in addition to the json document:

[7008] execve("", "", "") = 0
{"args":["\"\"","\"\"","\"\""],"pid":"7008","result":"0","syscall":"execve","type":"SYSCALL"}[7008] brk(NULL) = 0x55578000

Streamline output handling

There is a lot of if/else if/... code to handle various output cases. I think it can be streamlined and simplified.

Use `lurk` as a library

Hello! 🐻

I'm currently starting a new Rust project about strace and it would be really nice to use lurk as a library.

For that, I think we need to restructure the project a little bit and add lib.rs.

Let me know what you think!

Enhancements to syscall Arguments Display and Special Flags Interpretation

Description

While comparing traces from lurk and strace, I've noticed a couple of areas where lurk could potentially enhance its output for better clarity and completeness. Specifically:

  1. execve Arguments Display: The execve call in lurk's output doesn't display the full details of the arguments, environment variables, and the command being executed. In contrast, strace provides a more detailed view of these parameters, which is helpful for debugging and analysis purposes.

  2. Special Flags Interpretation: There are instances where lurk displays certain special values (e.g., NULL, AT_FDCWD) as their raw numerical equivalents (e.g., 0x0 for NULL, 4294967196 for AT_FDCWD). This raw display might not be immediately clear to users unfamiliar with these values' significance. In comparison, strace translates these into more understandable representations.

Examples

  • lurk output for execve:
    [10063] execve("", "", "") = 0

  • strace output for execve:
    execve("/usr/sbin/ls", ["ls"], 0x7fff550534c0 /* 68 vars */) = 0

  • Special flags:

  • lurk shows AT_FDCWD as 4294967196.

  • lurk displays NULL as 0x0.

Suggested Enhancements

  1. Enhance execve Output: It would be beneficial for lurk to include more details in the execve output, similar to strace. This might include the full command, arguments array, and environment variables block.

  2. Improve Special Flags Interpretation: For special constants like AT_FDCWD and NULL, translating these values into their well-known symbolic names (or at least including the symbolic names alongside the raw values) would enhance readability and user understanding.

These enhancements could significantly improve the utility and user experience of lurk for tracing system calls, especially for users transitioning from or comparing outputs with strace.

Additional Information

  • Lurk Version: 0.3.4

Thank you for considering these suggestions to improve lurk.

lurk ls -l hangs

lurk ls works

but lurk ls -l hangs , the last syscalls before it hangs looks like this

[16980] futex(0x7FFFF7D800E0, 129, 2147483647, 0x0, 140737353468592, 64) = 0
[16980] getdents64(4, 0x5555555AE730, 32768) = 0
[16980] close(4) = 0
[16980] epoll_ctl(6, 3, 5, 0x7FFFFFFFD16C) = 0
[16980] openat(4294967196, "/proc/sys/kernel/random/boot_id", 524544) = 4
[16980] read(4, "serialnumber-azezae..", 38) = 37
[16980] read(4, "", 1) = 0
[16980] close(4) = 0
[16980] timerfd_settime(7, 1, 0x7FFFFFFFD170) = 0

using gdb I can see its stuck in wait4

#0  0x00007f19da6f8707 in wait4 () from /usr/lib/libc.so.6
#1  0x000055cb93b4401c in nix::sys::wait::waitpid<core::option::Option<nix::unistd::Pid>> (pid=..., options=...) at src/sys/wait.rs:319
#2  0x000055cb93b44162 in nix::sys::wait::wait () at src/sys/wait.rs:336
#3  0x000055cb939529df in lurk_cli::Tracer::run_tracer (self=0x7ffc8347bf18) at src/lib.rs:98
#4  0x000055cb9392c36c in lurk::main () at src/main.rs:35

Implement additional flags for professional use

Needs to be implemented

  • Implement -ff
  • Implement -x
  • Implement -xx
  • Implement -yy
  • Try to increase precision of wall clock time

Further information

Source: https://news.ycombinator.com/item?id=32275902

Heavy professional strace user here. Afaics the wall clock time of the call is not implemented. This is effectively useless to me without that. The second -ff is critical for following busy multiprocess stuff like a JVM. If you aren't resolving every known struct then -x and -xx can be useful. The FD resolution provided by -yy is not critical but can be a real time saver. The flags I use most often are -ffttTyy -o -s.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.